mp_fput.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:5k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996, 1997, 1998, 1999, 2000
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: mp_fput.c,v 11.16 2000/11/30 00:58:41 ubell Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #endif
  14. #ifdef  HAVE_RPC
  15. #include "db_server.h"
  16. #endif
  17. #include "db_int.h"
  18. #include "db_shash.h"
  19. #include "mp.h"
  20. #ifdef HAVE_RPC
  21. #include "gen_client_ext.h"
  22. #include "rpc_client_ext.h"
  23. #endif
  24. /*
  25.  * memp_fput --
  26.  * Mpool file put function.
  27.  */
  28. int
  29. memp_fput(dbmfp, pgaddr, flags)
  30. DB_MPOOLFILE *dbmfp;
  31. void *pgaddr;
  32. u_int32_t flags;
  33. {
  34. BH *bhp;
  35. DB_ENV *dbenv;
  36. DB_MPOOL *dbmp;
  37. MPOOL *c_mp, *mp;
  38. int ret, wrote;
  39. dbmp = dbmfp->dbmp;
  40. dbenv = dbmp->dbenv;
  41. mp = dbmp->reginfo[0].primary;
  42. #ifdef HAVE_RPC
  43. if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
  44. return (__dbcl_memp_fput(dbmfp, pgaddr, flags));
  45. #endif
  46. PANIC_CHECK(dbenv);
  47. /* Validate arguments. */
  48. if (flags) {
  49. if ((ret = __db_fchk(dbenv, "memp_fput", flags,
  50.     DB_MPOOL_CLEAN | DB_MPOOL_DIRTY | DB_MPOOL_DISCARD)) != 0)
  51. return (ret);
  52. if ((ret = __db_fcchk(dbenv, "memp_fput",
  53.     flags, DB_MPOOL_CLEAN, DB_MPOOL_DIRTY)) != 0)
  54. return (ret);
  55. if (LF_ISSET(DB_MPOOL_DIRTY) && F_ISSET(dbmfp, MP_READONLY)) {
  56. __db_err(dbenv,
  57.     "%s: dirty flag set for readonly file page",
  58.     __memp_fn(dbmfp));
  59. return (EACCES);
  60. }
  61. }
  62. R_LOCK(dbenv, dbmp->reginfo);
  63. /* Decrement the pinned reference count. */
  64. if (dbmfp->pinref == 0) {
  65. __db_err(dbenv,
  66.     "%s: more pages returned than retrieved", __memp_fn(dbmfp));
  67. R_UNLOCK(dbenv, dbmp->reginfo);
  68. return (EINVAL);
  69. } else
  70. --dbmfp->pinref;
  71. /*
  72.  * If we're mapping the file, there's nothing to do.  Because we can
  73.  * stop mapping the file at any time, we have to check on each buffer
  74.  * to see if the address we gave the application was part of the map
  75.  * region.
  76.  */
  77. if (dbmfp->addr != NULL && pgaddr >= dbmfp->addr &&
  78.     (u_int8_t *)pgaddr <= (u_int8_t *)dbmfp->addr + dbmfp->len) {
  79. R_UNLOCK(dbenv, dbmp->reginfo);
  80. return (0);
  81. }
  82. /* Convert the page address to a buffer header. */
  83. bhp = (BH *)((u_int8_t *)pgaddr - SSZA(BH, buf));
  84. /* Convert the buffer header to a cache. */
  85. c_mp = BH_TO_CACHE(dbmp, bhp);
  86. /* UNLOCK THE REGION, LOCK THE CACHE. */
  87. /* Set/clear the page bits. */
  88. if (LF_ISSET(DB_MPOOL_CLEAN) && F_ISSET(bhp, BH_DIRTY)) {
  89. ++c_mp->stat.st_page_clean;
  90. --c_mp->stat.st_page_dirty;
  91. F_CLR(bhp, BH_DIRTY);
  92. }
  93. if (LF_ISSET(DB_MPOOL_DIRTY) && !F_ISSET(bhp, BH_DIRTY)) {
  94. --c_mp->stat.st_page_clean;
  95. ++c_mp->stat.st_page_dirty;
  96. F_SET(bhp, BH_DIRTY);
  97. }
  98. if (LF_ISSET(DB_MPOOL_DISCARD))
  99. F_SET(bhp, BH_DISCARD);
  100. /*
  101.  * If the page is dirty and being scheduled to be written as part of
  102.  * a checkpoint, we no longer know that the log is up-to-date.
  103.  */
  104. if (F_ISSET(bhp, BH_DIRTY) && F_ISSET(bhp, BH_SYNC))
  105. F_SET(bhp, BH_SYNC_LOGFLSH);
  106. /*
  107.  * Check for a reference count going to zero.  This can happen if the
  108.  * application returns a page twice.
  109.  */
  110. if (bhp->ref == 0) {
  111. __db_err(dbenv, "%s: page %lu: unpinned page returned",
  112.     __memp_fn(dbmfp), (u_long)bhp->pgno);
  113. R_UNLOCK(dbenv, dbmp->reginfo);
  114. return (EINVAL);
  115. }
  116. /*
  117.  * If more than one reference to the page, we're done.  Ignore the
  118.  * discard flags (for now) and leave it at its position in the LRU
  119.  * chain.  The rest gets done at last reference close.
  120.  */
  121. if (--bhp->ref > 0) {
  122. R_UNLOCK(dbenv, dbmp->reginfo);
  123. return (0);
  124. }
  125. /*
  126.  * Move the buffer to the head/tail of the LRU chain.  We do this
  127.  * before writing the buffer for checkpoint purposes, as the write
  128.  * can discard the region lock and allow another process to acquire
  129.  * buffer.  We could keep that from happening, but there seems no
  130.  * reason to do so.
  131.  */
  132. SH_TAILQ_REMOVE(&c_mp->bhq, bhp, q, __bh);
  133. if (F_ISSET(bhp, BH_DISCARD))
  134. SH_TAILQ_INSERT_HEAD(&c_mp->bhq, bhp, q, __bh);
  135. else
  136. SH_TAILQ_INSERT_TAIL(&c_mp->bhq, bhp, q);
  137. /*
  138.  * If this buffer is scheduled for writing because of a checkpoint, we
  139.  * need to write it (if it's dirty), or update the checkpoint counters
  140.  * (if it's not dirty).  If we try to write it and can't, that's not
  141.  * necessarily an error as it's not completely unreasonable that the
  142.  * application have permission to write the underlying file, but set a
  143.  * flag so that the next time the memp_sync function is called we try
  144.  * writing it there, as the checkpoint thread of control better be able
  145.  * to write all of the files.
  146.  */
  147. if (F_ISSET(bhp, BH_SYNC)) {
  148. if (F_ISSET(bhp, BH_DIRTY)) {
  149. if (__memp_bhwrite(dbmp,
  150.     dbmfp->mfp, bhp, NULL, &wrote) != 0 || !wrote)
  151. F_SET(mp, MP_LSN_RETRY);
  152. } else {
  153. F_CLR(bhp, BH_SYNC);
  154. --mp->lsn_cnt;
  155. --dbmfp->mfp->lsn_cnt;
  156. }
  157. }
  158. R_UNLOCK(dbenv, dbmp->reginfo);
  159. return (0);
  160. }