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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * localbuf.c
  4.  *   local buffer manager. Fast buffer manager for temporary tables
  5.  *   or special cases when the operation is not visible to other backends.
  6.  *
  7.  *   When a relation is being created, the descriptor will have rd_islocal
  8.  *   set to indicate that the local buffer manager should be used. During
  9.  *   the same transaction the relation is being created, any inserts or
  10.  *   selects from the newly created relation will use the local buffer
  11.  *   pool. rd_islocal is reset at the end of a transaction (commit/abort).
  12.  *   This is useful for queries like SELECT INTO TABLE and create index.
  13.  *
  14.  * Copyright (c) 1994-5, Regents of the University of California
  15.  *
  16.  *
  17.  * IDENTIFICATION
  18.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/storage/buffer/localbuf.c,v 1.22 1999/05/10 00:45:36 momjian Exp $
  19.  *
  20.  *-------------------------------------------------------------------------
  21.  */
  22. #include <sys/types.h>
  23. #include <sys/file.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <math.h>
  27. #include <signal.h>
  28. #include "postgres.h"
  29. /* declarations split between these three files */
  30. #include "storage/buf.h"
  31. #include "storage/buf_internals.h"
  32. #include "storage/bufmgr.h"
  33. #include "storage/fd.h"
  34. #include "storage/ipc.h"
  35. #include "storage/shmem.h"
  36. #include "storage/spin.h"
  37. #include "storage/smgr.h"
  38. #include "storage/lmgr.h"
  39. #include "miscadmin.h"
  40. #include "utils/builtins.h"
  41. #include "utils/hsearch.h"
  42. #include "utils/memutils.h"
  43. #include "utils/relcache.h"
  44. #include "executor/execdebug.h" /* for NDirectFileRead */
  45. #include "catalog/catalog.h"
  46. extern long int LocalBufferFlushCount;
  47. int NLocBuffer = 64;
  48. BufferDesc *LocalBufferDescriptors = NULL;
  49. long    *LocalRefCount = NULL;
  50. static int nextFreeLocalBuf = 0;
  51. /*#define LBDEBUG*/
  52. /*
  53.  * LocalBufferAlloc -
  54.  *   allocate a local buffer. We do round robin allocation for now.
  55.  */
  56. BufferDesc *
  57. LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
  58. {
  59. int i;
  60. BufferDesc *bufHdr = (BufferDesc *) NULL;
  61. if (blockNum == P_NEW)
  62. {
  63. blockNum = reln->rd_nblocks;
  64. reln->rd_nblocks++;
  65. }
  66. /* a low tech search for now -- not optimized for scans */
  67. for (i = 0; i < NLocBuffer; i++)
  68. {
  69. if (LocalBufferDescriptors[i].tag.relId.relId == RelationGetRelid(reln) &&
  70. LocalBufferDescriptors[i].tag.blockNum == blockNum)
  71. {
  72. #ifdef LBDEBUG
  73. fprintf(stderr, "LB ALLOC (%u,%d) %dn",
  74. RelationGetRelid(reln), blockNum, -i - 1);
  75. #endif
  76. LocalRefCount[i]++;
  77. *foundPtr = TRUE;
  78. return &LocalBufferDescriptors[i];
  79. }
  80. }
  81. #ifdef LBDEBUG
  82. fprintf(stderr, "LB ALLOC (%u,%d) %dn",
  83. RelationGetRelid(reln), blockNum, -nextFreeLocalBuf - 1);
  84. #endif
  85. /* need to get a new buffer (round robin for now) */
  86. for (i = 0; i < NLocBuffer; i++)
  87. {
  88. int b = (nextFreeLocalBuf + i) % NLocBuffer;
  89. if (LocalRefCount[b] == 0)
  90. {
  91. bufHdr = &LocalBufferDescriptors[b];
  92. LocalRefCount[b]++;
  93. nextFreeLocalBuf = (b + 1) % NLocBuffer;
  94. break;
  95. }
  96. }
  97. if (bufHdr == NULL)
  98. elog(ERROR, "no empty local buffer.");
  99. /*
  100.  * this buffer is not referenced but it might still be dirty (the last
  101.  * transaction to touch it doesn't need its contents but has not
  102.  * flushed it).  if that's the case, write it out before reusing it!
  103.  */
  104. if (bufHdr->flags & BM_DIRTY)
  105. {
  106. Relation bufrel = RelationIdCacheGetRelation(bufHdr->tag.relId.relId);
  107. Assert(bufrel != NULL);
  108. /* flush this page */
  109. smgrwrite(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum,
  110.   (char *) MAKE_PTR(bufHdr->data));
  111. LocalBufferFlushCount++;
  112. RelationDecrementReferenceCount(bufrel);
  113. }
  114. /*
  115.  * it's all ours now.
  116.  */
  117. bufHdr->tag.relId.relId = RelationGetRelid(reln);
  118. bufHdr->tag.blockNum = blockNum;
  119. bufHdr->flags &= ~BM_DIRTY;
  120. /*
  121.  * lazy memory allocation. (see MAKE_PTR for why we need to do
  122.  * MAKE_OFFSET.)
  123.  */
  124. if (bufHdr->data == (SHMEM_OFFSET) 0)
  125. {
  126. char    *data = (char *) malloc(BLCKSZ);
  127. bufHdr->data = MAKE_OFFSET(data);
  128. }
  129. *foundPtr = FALSE;
  130. return bufHdr;
  131. }
  132. /*
  133.  * WriteLocalBuffer -
  134.  *   writes out a local buffer
  135.  */
  136. int
  137. WriteLocalBuffer(Buffer buffer, bool release)
  138. {
  139. int bufid;
  140. Assert(BufferIsLocal(buffer));
  141. #ifdef LBDEBUG
  142. fprintf(stderr, "LB WRITE %dn", buffer);
  143. #endif
  144. bufid = -(buffer + 1);
  145. LocalBufferDescriptors[bufid].flags |= BM_DIRTY;
  146. if (release)
  147. {
  148. Assert(LocalRefCount[bufid] > 0);
  149. LocalRefCount[bufid]--;
  150. }
  151. return true;
  152. }
  153. /*
  154.  * FlushLocalBuffer -
  155.  *   flushes a local buffer
  156.  */
  157. int
  158. FlushLocalBuffer(Buffer buffer, bool release)
  159. {
  160. int bufid;
  161. Relation bufrel;
  162. BufferDesc *bufHdr;
  163. Assert(BufferIsLocal(buffer));
  164. #ifdef LBDEBUG
  165. fprintf(stderr, "LB FLUSH %dn", buffer);
  166. #endif
  167. bufid = -(buffer + 1);
  168. bufHdr = &LocalBufferDescriptors[bufid];
  169. bufHdr->flags &= ~BM_DIRTY;
  170. bufrel = RelationIdCacheGetRelation(bufHdr->tag.relId.relId);
  171. Assert(bufrel != NULL);
  172. smgrflush(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum,
  173.   (char *) MAKE_PTR(bufHdr->data));
  174. LocalBufferFlushCount++;
  175. RelationDecrementReferenceCount(bufrel);
  176. Assert(LocalRefCount[bufid] > 0);
  177. if (release)
  178. LocalRefCount[bufid]--;
  179. return true;
  180. }
  181. /*
  182.  * InitLocalBuffer -
  183.  *   init the local buffer cache. Since most queries (esp. multi-user ones)
  184.  *   don't involve local buffers, we delay allocating memory for actual the
  185.  *   buffer until we need it.
  186.  */
  187. void
  188. InitLocalBuffer(void)
  189. {
  190. int i;
  191. /*
  192.  * these aren't going away. I'm not gonna use palloc.
  193.  */
  194. LocalBufferDescriptors =
  195. (BufferDesc *) malloc(sizeof(BufferDesc) * NLocBuffer);
  196. MemSet(LocalBufferDescriptors, 0, sizeof(BufferDesc) * NLocBuffer);
  197. nextFreeLocalBuf = 0;
  198. for (i = 0; i < NLocBuffer; i++)
  199. {
  200. BufferDesc *buf = &LocalBufferDescriptors[i];
  201. /*
  202.  * negative to indicate local buffer. This is tricky: shared
  203.  * buffers start with 0. We have to start with -2. (Note that the
  204.  * routine BufferDescriptorGetBuffer adds 1 to buf_id so our first
  205.  * buffer id is -1.)
  206.  */
  207. buf->buf_id = -i - 2;
  208. }
  209. LocalRefCount = (long *) malloc(sizeof(long) * NLocBuffer);
  210. MemSet(LocalRefCount, 0, sizeof(long) * NLocBuffer);
  211. }
  212. /*
  213.  * LocalBufferSync -
  214.  *   flush all dirty buffers in the local buffer cache. Since the buffer
  215.  *   cache is only used for keeping relations visible during a transaction,
  216.  *   we will not need these buffers again.
  217.  */
  218. void
  219. LocalBufferSync(void)
  220. {
  221. int i;
  222. for (i = 0; i < NLocBuffer; i++)
  223. {
  224. BufferDesc *buf = &LocalBufferDescriptors[i];
  225. Relation bufrel;
  226. if (buf->flags & BM_DIRTY)
  227. {
  228. #ifdef LBDEBUG
  229. fprintf(stderr, "LB SYNC %dn", -i - 1);
  230. #endif
  231. bufrel = RelationIdCacheGetRelation(buf->tag.relId.relId);
  232. Assert(bufrel != NULL);
  233. smgrwrite(DEFAULT_SMGR, bufrel, buf->tag.blockNum,
  234.   (char *) MAKE_PTR(buf->data));
  235. LocalBufferFlushCount++;
  236. RelationDecrementReferenceCount(bufrel);
  237. buf->tag.relId.relId = InvalidOid;
  238. buf->flags &= ~BM_DIRTY;
  239. }
  240. }
  241. MemSet(LocalRefCount, 0, sizeof(long) * NLocBuffer);
  242. nextFreeLocalBuf = 0;
  243. }
  244. void
  245. ResetLocalBufferPool(void)
  246. {
  247. int i;
  248. for (i = 0; i < NLocBuffer; i++)
  249. {
  250. BufferDesc *buf = &LocalBufferDescriptors[i];
  251. buf->tag.relId.relId = InvalidOid;
  252. buf->flags &= ~BM_DIRTY;
  253. buf->buf_id = -i - 2;
  254. }
  255. MemSet(LocalRefCount, 0, sizeof(long) * NLocBuffer);
  256. nextFreeLocalBuf = 0;
  257. }