freelist.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:7k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * freelist.c
  4.  *   routines for manipulating the buffer pool's replacement strategy
  5.  *   freelist.
  6.  *
  7.  * Copyright (c) 1994, Regents of the University of California
  8.  *
  9.  *
  10.  * IDENTIFICATION
  11.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/storage/buffer/freelist.c,v 1.15 1999/05/25 16:10:59 momjian Exp $
  12.  *
  13.  *-------------------------------------------------------------------------
  14.  */
  15. /*
  16.  * OLD COMMENTS
  17.  *
  18.  * Data Structures:
  19.  * SharedFreeList is a circular queue.  Notice that this
  20.  * is a shared memory queue so the next/prev "ptrs" are
  21.  * buffer ids, not addresses.
  22.  *
  23.  * Sync: all routines in this file assume that the buffer
  24.  * semaphore has been acquired by the caller.
  25.  */
  26. #include <stdio.h>
  27. #include "postgres.h"
  28. #include "storage/bufmgr.h"
  29. #include "storage/buf_internals.h" /* where declarations go */
  30. #include "storage/spin.h"
  31. static BufferDesc *SharedFreeList;
  32. /* only actually used in debugging.  The lock
  33.  * should be acquired before calling the freelist manager.
  34.  */
  35. extern SPINLOCK BufMgrLock;
  36. #define IsInQueue(bf) 
  37. AssertMacro((bf->freeNext != INVALID_DESCRIPTOR)), 
  38. AssertMacro((bf->freePrev != INVALID_DESCRIPTOR)), 
  39. AssertMacro((bf->flags & BM_FREE)) 
  40. )
  41. #define NotInQueue(bf) 
  42. AssertMacro((bf->freeNext == INVALID_DESCRIPTOR)), 
  43. AssertMacro((bf->freePrev == INVALID_DESCRIPTOR)), 
  44. AssertMacro(! (bf->flags & BM_FREE)) 
  45. )
  46. /*
  47.  * AddBufferToFreelist
  48.  *
  49.  * In theory, this is the only routine that needs to be changed
  50.  * if the buffer replacement strategy changes. Just change
  51.  * the manner in which buffers are added to the freelist queue.
  52.  * Currently, they are added on an LRU basis.
  53.  */
  54. void
  55. AddBufferToFreelist(BufferDesc *bf)
  56. {
  57. #ifdef BMTRACE
  58. _bm_trace(bf->tag.relId.dbId, bf->tag.relId.relId, bf->tag.blockNum,
  59.   BufferDescriptorGetBuffer(bf), BMT_DEALLOC);
  60. #endif  /* BMTRACE */
  61. NotInQueue(bf);
  62. /* change bf so it points to inFrontOfNew and its successor */
  63. bf->freePrev = SharedFreeList->freePrev;
  64. bf->freeNext = Free_List_Descriptor;
  65. /* insert new into chain */
  66. BufferDescriptors[bf->freeNext].freePrev = bf->buf_id;
  67. BufferDescriptors[bf->freePrev].freeNext = bf->buf_id;
  68. }
  69. #undef PinBuffer
  70. /*
  71.  * PinBuffer -- make buffer unavailable for replacement.
  72.  */
  73. void
  74. PinBuffer(BufferDesc *buf)
  75. {
  76. long b;
  77. /* Assert (buf->refcount < 25); */
  78. if (buf->refcount == 0)
  79. {
  80. IsInQueue(buf);
  81. /* remove from freelist queue */
  82. BufferDescriptors[buf->freeNext].freePrev = buf->freePrev;
  83. BufferDescriptors[buf->freePrev].freeNext = buf->freeNext;
  84. buf->freeNext = buf->freePrev = INVALID_DESCRIPTOR;
  85. /* mark buffer as no longer free */
  86. buf->flags &= ~BM_FREE;
  87. }
  88. else
  89. NotInQueue(buf);
  90. b = BufferDescriptorGetBuffer(buf) - 1;
  91. Assert(PrivateRefCount[b] >= 0);
  92. if (PrivateRefCount[b] == 0 && LastRefCount[b] == 0)
  93. buf->refcount++;
  94. PrivateRefCount[b]++;
  95. }
  96. #ifdef NOT_USED
  97. void
  98. PinBuffer_Debug(char *file, int line, BufferDesc *buf)
  99. {
  100. PinBuffer(buf);
  101. if (ShowPinTrace)
  102. {
  103. Buffer buffer = BufferDescriptorGetBuffer(buf);
  104. fprintf(stderr, "PIN(Pin) %ld relname = %s, blockNum = %d, 
  105. refcount = %ld, file: %s, line: %dn",
  106. buffer, buf->sb_relname, buf->tag.blockNum,
  107. PrivateRefCount[buffer - 1], file, line);
  108. }
  109. }
  110. #endif
  111. #undef UnpinBuffer
  112. /*
  113.  * UnpinBuffer -- make buffer available for replacement.
  114.  */
  115. void
  116. UnpinBuffer(BufferDesc *buf)
  117. {
  118. long b = BufferDescriptorGetBuffer(buf) - 1;
  119. Assert(buf->refcount);
  120. Assert(PrivateRefCount[b] > 0);
  121. PrivateRefCount[b]--;
  122. if (PrivateRefCount[b] == 0 && LastRefCount[b] == 0)
  123. buf->refcount--;
  124. NotInQueue(buf);
  125. if (buf->refcount == 0)
  126. {
  127. AddBufferToFreelist(buf);
  128. buf->flags |= BM_FREE;
  129. }
  130. else
  131. {
  132. /* do nothing */
  133. }
  134. }
  135. #ifdef NOT_USED
  136. void
  137. UnpinBuffer_Debug(char *file, int line, BufferDesc *buf)
  138. {
  139. UnpinBuffer(buf);
  140. if (ShowPinTrace)
  141. {
  142. Buffer buffer = BufferDescriptorGetBuffer(buf);
  143. fprintf(stderr, "UNPIN(Unpin) %ld relname = %s, blockNum = %d, 
  144. refcount = %ld, file: %s, line: %dn",
  145. buffer, buf->sb_relname, buf->tag.blockNum,
  146. PrivateRefCount[buffer - 1], file, line);
  147. }
  148. }
  149. #endif
  150. /*
  151.  * GetFreeBuffer() -- get the 'next' buffer from the freelist.
  152.  *
  153.  */
  154. BufferDesc *
  155. GetFreeBuffer()
  156. {
  157. BufferDesc *buf;
  158. if (Free_List_Descriptor == SharedFreeList->freeNext)
  159. {
  160. /* queue is empty. All buffers in the buffer pool are pinned. */
  161. elog(ERROR, "out of free buffers: time to abort !n");
  162. return NULL;
  163. }
  164. buf = &(BufferDescriptors[SharedFreeList->freeNext]);
  165. /* remove from freelist queue */
  166. BufferDescriptors[buf->freeNext].freePrev = buf->freePrev;
  167. BufferDescriptors[buf->freePrev].freeNext = buf->freeNext;
  168. buf->freeNext = buf->freePrev = INVALID_DESCRIPTOR;
  169. buf->flags &= ~(BM_FREE);
  170. return buf;
  171. }
  172. /*
  173.  * InitFreeList -- initialize the dummy buffer descriptor used
  174.  * as a freelist head.
  175.  *
  176.  * Assume: All of the buffers are already linked in a circular
  177.  * queue.  Only called by postmaster and only during
  178.  * initialization.
  179.  */
  180. void
  181. InitFreeList(bool init)
  182. {
  183. SharedFreeList = &(BufferDescriptors[Free_List_Descriptor]);
  184. if (init)
  185. {
  186. /* we only do this once, normally the postmaster */
  187. SharedFreeList->data = INVALID_OFFSET;
  188. SharedFreeList->flags = 0;
  189. SharedFreeList->flags &= ~(BM_VALID | BM_DELETED | BM_FREE);
  190. SharedFreeList->buf_id = Free_List_Descriptor;
  191. /* insert it into a random spot in the circular queue */
  192. SharedFreeList->freeNext = BufferDescriptors[0].freeNext;
  193. SharedFreeList->freePrev = 0;
  194. BufferDescriptors[SharedFreeList->freeNext].freePrev =
  195. BufferDescriptors[SharedFreeList->freePrev].freeNext =
  196. Free_List_Descriptor;
  197. }
  198. }
  199. /*
  200.  * print out the free list and check for breaks.
  201.  */
  202. #ifdef NOT_USED
  203. void
  204. DBG_FreeListCheck(int nfree)
  205. {
  206. int i;
  207. BufferDesc *buf;
  208. buf = &(BufferDescriptors[SharedFreeList->freeNext]);
  209. for (i = 0; i < nfree; i++, buf = &(BufferDescriptors[buf->freeNext]))
  210. {
  211. if (!(buf->flags & (BM_FREE)))
  212. {
  213. if (buf != SharedFreeList)
  214. {
  215. printf("tfree list corrupted: %d flags %xn",
  216.    buf->buf_id, buf->flags);
  217. }
  218. else
  219. {
  220. printf("tfree list corrupted: too short -- %d not %dn",
  221.    i, nfree);
  222. }
  223. }
  224. if ((BufferDescriptors[buf->freeNext].freePrev != buf->buf_id) ||
  225. (BufferDescriptors[buf->freePrev].freeNext != buf->buf_id))
  226. {
  227. printf("tfree list links corrupted: %d %ld %ldn",
  228.    buf->buf_id, buf->freePrev, buf->freeNext);
  229. }
  230. }
  231. if (buf != SharedFreeList)
  232. {
  233. printf("tfree list corrupted: %d-th buffer is %dn",
  234.    nfree, buf->buf_id);
  235. }
  236. }
  237. #endif
  238. #ifdef NOT_USED
  239. /*
  240.  * PrintBufferFreeList -
  241.  *   prints the buffer free list, for debugging
  242.  */
  243. static void
  244. PrintBufferFreeList()
  245. {
  246. BufferDesc *buf;
  247. if (SharedFreeList->freeNext == Free_List_Descriptor)
  248. {
  249. printf("free list is empty.n");
  250. return;
  251. }
  252. buf = &(BufferDescriptors[SharedFreeList->freeNext]);
  253. for (;;)
  254. {
  255. int i = (buf - BufferDescriptors);
  256. printf("[%-2d] (%s, %d) flags=0x%x, refcnt=%d %ld, nxt=%ld prv=%ld)n",
  257.    i, buf->sb_relname, buf->tag.blockNum,
  258.    buf->flags, buf->refcount, PrivateRefCount[i],
  259.    buf->freeNext, buf->freePrev);
  260. if (buf->freeNext == Free_List_Descriptor)
  261. break;
  262. buf = &(BufferDescriptors[buf->freeNext]);
  263. }
  264. }
  265. #endif