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

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_alloc.c,v 11.7 2000/04/20 21:14:18 bostic Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #endif
  14. #include "db_int.h"
  15. #include "db_shash.h"
  16. #include "mp.h"
  17. /*
  18.  * __memp_alloc --
  19.  * Allocate some space from a cache region.
  20.  *
  21.  * PUBLIC: int __memp_alloc __P((DB_MPOOL *,
  22.  * PUBLIC:     REGINFO *, MPOOLFILE *, size_t, roff_t *, void *));
  23.  */
  24. int
  25. __memp_alloc(dbmp, memreg, mfp, len, offsetp, retp)
  26. DB_MPOOL *dbmp;
  27. REGINFO *memreg;
  28. MPOOLFILE *mfp;
  29. size_t len;
  30. roff_t *offsetp;
  31. void *retp;
  32. {
  33. BH *bhp, *nbhp;
  34. MPOOL *c_mp;
  35. MPOOLFILE *bh_mfp;
  36. size_t total;
  37. int nomore, restart, ret, wrote;
  38. void *p;
  39. c_mp = memreg->primary;
  40. /*
  41.  * If we're allocating a buffer, and the one we're discarding is the
  42.  * same size, we don't want to waste the time to re-integrate it into
  43.  * the shared memory free list.  If the DB_MPOOLFILE argument isn't
  44.  * NULL, we'll compare the underlying page sizes of the two buffers
  45.  * before free-ing and re-allocating buffers.
  46.  */
  47. if (mfp != NULL)
  48. len = (sizeof(BH) - sizeof(u_int8_t)) + mfp->stat.st_pagesize;
  49. nomore = 0;
  50. alloc: if ((ret = __db_shalloc(memreg->addr, len, MUTEX_ALIGN, &p)) == 0) {
  51. if (offsetp != NULL)
  52. *offsetp = R_OFFSET(memreg, p);
  53. *(void **)retp = p;
  54. return (0);
  55. }
  56. if (nomore) {
  57. __db_err(dbmp->dbenv,
  58.     "Unable to allocate %lu bytes from mpool shared region: %sn",
  59.     (u_long)len, db_strerror(ret));
  60. return (ret);
  61. }
  62. retry: /* Find a buffer we can flush; pure LRU. */
  63. restart = total = 0;
  64. for (bhp =
  65.     SH_TAILQ_FIRST(&c_mp->bhq, __bh); bhp != NULL; bhp = nbhp) {
  66. nbhp = SH_TAILQ_NEXT(bhp, q, __bh);
  67. /* Ignore pinned or locked (I/O in progress) buffers. */
  68. if (bhp->ref != 0 || F_ISSET(bhp, BH_LOCKED))
  69. continue;
  70. /* Find the associated MPOOLFILE. */
  71. bh_mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset);
  72. /* Write the page if it's dirty. */
  73. if (F_ISSET(bhp, BH_DIRTY)) {
  74. ++bhp->ref;
  75. if ((ret = __memp_bhwrite(dbmp,
  76.     bh_mfp, bhp, &restart, &wrote)) != 0)
  77. return (ret);
  78. --bhp->ref;
  79. /*
  80.  * Another process may have acquired this buffer and
  81.  * incremented the ref count after we wrote it.
  82.  */
  83. if (bhp->ref != 0)
  84. goto retry;
  85. /*
  86.  * If we wrote the page, continue and free the buffer.
  87.  * We don't have to rewalk the list to acquire the
  88.  * buffer because it was never available for any other
  89.  * process to modify it.
  90.  *
  91.  * If we didn't write the page, but we discarded and
  92.  * reacquired the region lock, restart the list walk.
  93.  *
  94.  * If we neither wrote the buffer nor discarded the
  95.  * region lock, continue down the buffer list.
  96.  */
  97. if (wrote)
  98. ++c_mp->stat.st_rw_evict;
  99. else {
  100. if (restart)
  101. goto retry;
  102. continue;
  103. }
  104. } else
  105. ++c_mp->stat.st_ro_evict;
  106. /*
  107.  * Check to see if the buffer is the size we're looking for.
  108.  * If it is, simply reuse it.
  109.  */
  110. if (mfp != NULL &&
  111.     mfp->stat.st_pagesize == bh_mfp->stat.st_pagesize) {
  112. __memp_bhfree(dbmp, bhp, 0);
  113. if (offsetp != NULL)
  114. *offsetp = R_OFFSET(memreg, bhp);
  115. *(void **)retp = bhp;
  116. return (0);
  117. }
  118. /* Note how much space we've freed, and free the buffer. */
  119. total += __db_shsizeof(bhp);
  120. __memp_bhfree(dbmp, bhp, 1);
  121. /*
  122.  * Retry as soon as we've freed up sufficient space.  If we
  123.  * have to coalesce of memory to satisfy the request, don't
  124.  * try until it's likely (possible?) that we'll succeed.
  125.  */
  126. if (total >= 3 * len)
  127. goto alloc;
  128. /* Restart the walk if we discarded the region lock. */
  129. if (restart)
  130. goto retry;
  131. }
  132. nomore = 1;
  133. goto alloc;
  134. }