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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * mm.c
  4.  *   main memory storage manager
  5.  *
  6.  *   This code manages relations that reside in (presumably stable)
  7.  *   main memory.
  8.  *
  9.  * Copyright (c) 1994, Regents of the University of California
  10.  *
  11.  *
  12.  * IDENTIFICATION
  13.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/storage/smgr/mm.c,v 1.16 1999/05/25 16:11:32 momjian Exp $
  14.  *
  15.  *-------------------------------------------------------------------------
  16.  */
  17. #include "postgres.h"
  18. #ifdef STABLE_MEMORY_STORAGE
  19. #include <math.h>
  20. #include "storage/ipc.h"
  21. #include "storage/smgr.h" /* where the declarations go */
  22. #include "storage/block.h"
  23. #include "storage/shmem.h"
  24. #include "storage/spin.h"
  25. #include "utils/hsearch.h"
  26. #include "utils/rel.h"
  27. #include "utils/memutils.h"
  28. /*
  29.  * MMCacheTag -- Unique triplet for blocks stored by the main memory
  30.  *   storage manager.
  31.  */
  32. typedef struct MMCacheTag
  33. {
  34. Oid mmct_dbid;
  35. Oid mmct_relid;
  36. BlockNumber mmct_blkno;
  37. } MMCacheTag;
  38. /*
  39.  * Shared-memory hash table for main memory relations contains
  40.  * entries of this form.
  41.  */
  42. typedef struct MMHashEntry
  43. {
  44. MMCacheTag mmhe_tag;
  45. int mmhe_bufno;
  46. } MMHashEntry;
  47. /*
  48.  * MMRelTag -- Unique identifier for each relation that is stored in the
  49.  * main-memory storage manager.
  50.  */
  51. typedef struct MMRelTag
  52. {
  53. Oid mmrt_dbid;
  54. Oid mmrt_relid;
  55. } MMRelTag;
  56. /*
  57.  * Shared-memory hash table for # blocks in main memory relations contains
  58.  * entries of this form.
  59.  */
  60. typedef struct MMRelHashEntry
  61. {
  62. MMRelTag mmrhe_tag;
  63. int mmrhe_nblocks;
  64. } MMRelHashEntry;
  65. #define MMNBUFFERS 10
  66. #define MMNRELATIONS 2
  67. SPINLOCK MMCacheLock;
  68. extern Oid MyDatabaseId;
  69. static int *MMCurTop;
  70. static int *MMCurRelno;
  71. static MMCacheTag *MMBlockTags;
  72. static char *MMBlockCache;
  73. static HTAB *MMCacheHT;
  74. static HTAB *MMRelCacheHT;
  75. int
  76. mminit()
  77. {
  78. char    *mmcacheblk;
  79. int mmsize = 0;
  80. bool found;
  81. HASHCTL info;
  82. SpinAcquire(MMCacheLock);
  83. mmsize += MAXALIGN(BLCKSZ * MMNBUFFERS);
  84. mmsize += MAXALIGN(sizeof(*MMCurTop));
  85. mmsize += MAXALIGN(sizeof(*MMCurRelno));
  86. mmsize += MAXALIGN((MMNBUFFERS * sizeof(MMCacheTag)));
  87. mmcacheblk = (char *) ShmemInitStruct("Main memory smgr", mmsize, &found);
  88. if (mmcacheblk == (char *) NULL)
  89. {
  90. SpinRelease(MMCacheLock);
  91. return SM_FAIL;
  92. }
  93. info.keysize = sizeof(MMCacheTag);
  94. info.datasize = sizeof(MMHashEntry) - sizeof(MMCacheTag);
  95. info.hash = tag_hash;
  96. MMCacheHT = (HTAB *) ShmemInitHash("Main memory store HT",
  97.    MMNBUFFERS, MMNBUFFERS,
  98.  &info, (HASH_ELEM | HASH_FUNCTION));
  99. if (MMCacheHT == (HTAB *) NULL)
  100. {
  101. SpinRelease(MMCacheLock);
  102. return SM_FAIL;
  103. }
  104. info.keysize = sizeof(MMRelTag);
  105. info.datasize = sizeof(MMRelHashEntry) - sizeof(MMRelTag);
  106. info.hash = tag_hash;
  107. MMRelCacheHT = (HTAB *) ShmemInitHash("Main memory rel HT",
  108.   MMNRELATIONS, MMNRELATIONS,
  109.  &info, (HASH_ELEM | HASH_FUNCTION));
  110. if (MMRelCacheHT == (HTAB *) NULL)
  111. {
  112. SpinRelease(MMCacheLock);
  113. return SM_FAIL;
  114. }
  115. if (IsUnderPostmaster) /* was IsPostmaster bjm */
  116. {
  117. MemSet(mmcacheblk, 0, mmsize);
  118. SpinRelease(MMCacheLock);
  119. return SM_SUCCESS;
  120. }
  121. SpinRelease(MMCacheLock);
  122. MMCurTop = (int *) mmcacheblk;
  123. mmcacheblk += sizeof(int);
  124. MMCurRelno = (int *) mmcacheblk;
  125. mmcacheblk += sizeof(int);
  126. MMBlockTags = (MMCacheTag *) mmcacheblk;
  127. mmcacheblk += (MMNBUFFERS * sizeof(MMCacheTag));
  128. MMBlockCache = mmcacheblk;
  129. return SM_SUCCESS;
  130. }
  131. int
  132. mmshutdown()
  133. {
  134. return SM_SUCCESS;
  135. }
  136. int
  137. mmcreate(Relation reln)
  138. {
  139. MMRelHashEntry *entry;
  140. bool found;
  141. MMRelTag tag;
  142. SpinAcquire(MMCacheLock);
  143. if (*MMCurRelno == MMNRELATIONS)
  144. {
  145. SpinRelease(MMCacheLock);
  146. return SM_FAIL;
  147. }
  148. (*MMCurRelno)++;
  149. tag.mmrt_relid = RelationGetRelid(reln);
  150. if (reln->rd_rel->relisshared)
  151. tag.mmrt_dbid = (Oid) 0;
  152. else
  153. tag.mmrt_dbid = MyDatabaseId;
  154. entry = (MMRelHashEntry *) hash_search(MMRelCacheHT,
  155.   (char *) &tag, HASH_ENTER, &found);
  156. if (entry == (MMRelHashEntry *) NULL)
  157. {
  158. SpinRelease(MMCacheLock);
  159. elog(FATAL, "main memory storage mgr rel cache hash table corrupt");
  160. }
  161. if (found)
  162. {
  163. /* already exists */
  164. SpinRelease(MMCacheLock);
  165. return SM_FAIL;
  166. }
  167. entry->mmrhe_nblocks = 0;
  168. SpinRelease(MMCacheLock);
  169. return SM_SUCCESS;
  170. }
  171. /*
  172.  * mmunlink() -- Unlink a relation.
  173.  */
  174. int
  175. mmunlink(Relation reln)
  176. {
  177. int i;
  178. Oid reldbid;
  179. MMHashEntry *entry;
  180. MMRelHashEntry *rentry;
  181. bool found;
  182. MMRelTag rtag;
  183. if (reln->rd_rel->relisshared)
  184. reldbid = (Oid) 0;
  185. else
  186. reldbid = MyDatabaseId;
  187. SpinAcquire(MMCacheLock);
  188. for (i = 0; i < MMNBUFFERS; i++)
  189. {
  190. if (MMBlockTags[i].mmct_dbid == reldbid
  191. && MMBlockTags[i].mmct_relid == RelationGetRelid(reln))
  192. {
  193. entry = (MMHashEntry *) hash_search(MMCacheHT,
  194. (char *) &MMBlockTags[i],
  195. HASH_REMOVE, &found);
  196. if (entry == (MMHashEntry *) NULL || !found)
  197. {
  198. SpinRelease(MMCacheLock);
  199. elog(FATAL, "mmunlink: cache hash table corrupted");
  200. }
  201. MMBlockTags[i].mmct_dbid = (Oid) 0;
  202. MMBlockTags[i].mmct_relid = (Oid) 0;
  203. MMBlockTags[i].mmct_blkno = (BlockNumber) 0;
  204. }
  205. }
  206. rtag.mmrt_dbid = reldbid;
  207. rtag.mmrt_relid = RelationGetRelid(reln);
  208. rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT, (char *) &rtag,
  209. HASH_REMOVE, &found);
  210. if (rentry == (MMRelHashEntry *) NULL || !found)
  211. {
  212. SpinRelease(MMCacheLock);
  213. elog(FATAL, "mmunlink: rel cache hash table corrupted");
  214. }
  215. (*MMCurRelno)--;
  216. SpinRelease(MMCacheLock);
  217. return 1;
  218. }
  219. /*
  220.  * mmextend() -- Add a block to the specified relation.
  221.  *
  222.  * This routine returns SM_FAIL or SM_SUCCESS, with errno set as
  223.  * appropriate.
  224.  */
  225. int
  226. mmextend(Relation reln, char *buffer)
  227. {
  228. MMRelHashEntry *rentry;
  229. MMHashEntry *entry;
  230. int i;
  231. Oid reldbid;
  232. int offset;
  233. bool found;
  234. MMRelTag rtag;
  235. MMCacheTag tag;
  236. if (reln->rd_rel->relisshared)
  237. reldbid = (Oid) 0;
  238. else
  239. reldbid = MyDatabaseId;
  240. tag.mmct_dbid = rtag.mmrt_dbid = reldbid;
  241. tag.mmct_relid = rtag.mmrt_relid = RelationGetRelid(reln);
  242. SpinAcquire(MMCacheLock);
  243. if (*MMCurTop == MMNBUFFERS)
  244. {
  245. for (i = 0; i < MMNBUFFERS; i++)
  246. {
  247. if (MMBlockTags[i].mmct_dbid == 0 &&
  248. MMBlockTags[i].mmct_relid == 0)
  249. break;
  250. }
  251. if (i == MMNBUFFERS)
  252. {
  253. SpinRelease(MMCacheLock);
  254. return SM_FAIL;
  255. }
  256. }
  257. else
  258. {
  259. i = *MMCurTop;
  260. (*MMCurTop)++;
  261. }
  262. rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT, (char *) &rtag,
  263. HASH_FIND, &found);
  264. if (rentry == (MMRelHashEntry *) NULL || !found)
  265. {
  266. SpinRelease(MMCacheLock);
  267. elog(FATAL, "mmextend: rel cache hash table corrupt");
  268. }
  269. tag.mmct_blkno = rentry->mmrhe_nblocks;
  270. entry = (MMHashEntry *) hash_search(MMCacheHT, (char *) &tag,
  271. HASH_ENTER, &found);
  272. if (entry == (MMHashEntry *) NULL || found)
  273. {
  274. SpinRelease(MMCacheLock);
  275. elog(FATAL, "mmextend: cache hash table corrupt");
  276. }
  277. entry->mmhe_bufno = i;
  278. MMBlockTags[i].mmct_dbid = reldbid;
  279. MMBlockTags[i].mmct_relid = RelationGetRelid(reln);
  280. MMBlockTags[i].mmct_blkno = rentry->mmrhe_nblocks;
  281. /* page numbers are zero-based, so we increment this at the end */
  282. (rentry->mmrhe_nblocks)++;
  283. /* write the extended page */
  284. offset = (i * BLCKSZ);
  285. memmove(&(MMBlockCache[offset]), buffer, BLCKSZ);
  286. SpinRelease(MMCacheLock);
  287. return SM_SUCCESS;
  288. }
  289. /*
  290.  * mmopen() -- Open the specified relation.
  291.  */
  292. int
  293. mmopen(Relation reln)
  294. {
  295. /* automatically successful */
  296. return 0;
  297. }
  298. /*
  299.  * mmclose() -- Close the specified relation.
  300.  *
  301.  * Returns SM_SUCCESS or SM_FAIL with errno set as appropriate.
  302.  */
  303. int
  304. mmclose(Relation reln)
  305. {
  306. /* automatically successful */
  307. return SM_SUCCESS;
  308. }
  309. /*
  310.  * mmread() -- Read the specified block from a relation.
  311.  *
  312.  * Returns SM_SUCCESS or SM_FAIL.
  313.  */
  314. int
  315. mmread(Relation reln, BlockNumber blocknum, char *buffer)
  316. {
  317. MMHashEntry *entry;
  318. bool found;
  319. int offset;
  320. MMCacheTag tag;
  321. if (reln->rd_rel->relisshared)
  322. tag.mmct_dbid = (Oid) 0;
  323. else
  324. tag.mmct_dbid = MyDatabaseId;
  325. tag.mmct_relid = RelationGetRelid(reln);
  326. tag.mmct_blkno = blocknum;
  327. SpinAcquire(MMCacheLock);
  328. entry = (MMHashEntry *) hash_search(MMCacheHT, (char *) &tag,
  329. HASH_FIND, &found);
  330. if (entry == (MMHashEntry *) NULL)
  331. {
  332. SpinRelease(MMCacheLock);
  333. elog(FATAL, "mmread: hash table corrupt");
  334. }
  335. if (!found)
  336. {
  337. /* reading nonexistent pages is defined to fill them with zeroes */
  338. SpinRelease(MMCacheLock);
  339. MemSet(buffer, 0, BLCKSZ);
  340. return SM_SUCCESS;
  341. }
  342. offset = (entry->mmhe_bufno * BLCKSZ);
  343. memmove(buffer, &MMBlockCache[offset], BLCKSZ);
  344. SpinRelease(MMCacheLock);
  345. return SM_SUCCESS;
  346. }
  347. /*
  348.  * mmwrite() -- Write the supplied block at the appropriate location.
  349.  *
  350.  * Returns SM_SUCCESS or SM_FAIL.
  351.  */
  352. int
  353. mmwrite(Relation reln, BlockNumber blocknum, char *buffer)
  354. {
  355. MMHashEntry *entry;
  356. bool found;
  357. int offset;
  358. MMCacheTag tag;
  359. if (reln->rd_rel->relisshared)
  360. tag.mmct_dbid = (Oid) 0;
  361. else
  362. tag.mmct_dbid = MyDatabaseId;
  363. tag.mmct_relid = RelationGetRelid(reln);
  364. tag.mmct_blkno = blocknum;
  365. SpinAcquire(MMCacheLock);
  366. entry = (MMHashEntry *) hash_search(MMCacheHT, (char *) &tag,
  367. HASH_FIND, &found);
  368. if (entry == (MMHashEntry *) NULL)
  369. {
  370. SpinRelease(MMCacheLock);
  371. elog(FATAL, "mmread: hash table corrupt");
  372. }
  373. if (!found)
  374. {
  375. SpinRelease(MMCacheLock);
  376. elog(FATAL, "mmwrite: hash table missing requested page");
  377. }
  378. offset = (entry->mmhe_bufno * BLCKSZ);
  379. memmove(&MMBlockCache[offset], buffer, BLCKSZ);
  380. SpinRelease(MMCacheLock);
  381. return SM_SUCCESS;
  382. }
  383. /*
  384.  * mmflush() -- Synchronously write a block to stable storage.
  385.  *
  386.  * For main-memory relations, this is exactly equivalent to mmwrite().
  387.  */
  388. int
  389. mmflush(Relation reln, BlockNumber blocknum, char *buffer)
  390. {
  391. return mmwrite(reln, blocknum, buffer);
  392. }
  393. /*
  394.  * mmblindwrt() -- Write a block to stable storage blind.
  395.  *
  396.  * We have to be able to do this using only the name and OID of
  397.  * the database and relation in which the block belongs.
  398.  */
  399. int
  400. mmblindwrt(char *dbstr,
  401.    char *relstr,
  402.    Oid dbid,
  403.    Oid relid,
  404.    BlockNumber blkno,
  405.    char *buffer)
  406. {
  407. return SM_FAIL;
  408. }
  409. /*
  410.  * mmnblocks() -- Get the number of blocks stored in a relation.
  411.  *
  412.  * Returns # of blocks or -1 on error.
  413.  */
  414. int
  415. mmnblocks(Relation reln)
  416. {
  417. MMRelTag rtag;
  418. MMRelHashEntry *rentry;
  419. bool found;
  420. int nblocks;
  421. if (reln->rd_rel->relisshared)
  422. rtag.mmrt_dbid = (Oid) 0;
  423. else
  424. rtag.mmrt_dbid = MyDatabaseId;
  425. rtag.mmrt_relid = RelationGetRelid(reln);
  426. SpinAcquire(MMCacheLock);
  427. rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT, (char *) &rtag,
  428. HASH_FIND, &found);
  429. if (rentry == (MMRelHashEntry *) NULL)
  430. {
  431. SpinRelease(MMCacheLock);
  432. elog(FATAL, "mmnblocks: rel cache hash table corrupt");
  433. }
  434. if (found)
  435. nblocks = rentry->mmrhe_nblocks;
  436. else
  437. nblocks = -1;
  438. SpinRelease(MMCacheLock);
  439. return nblocks;
  440. }
  441. /*
  442.  * mmcommit() -- Commit a transaction.
  443.  *
  444.  * Returns SM_SUCCESS or SM_FAIL with errno set as appropriate.
  445.  */
  446. int
  447. mmcommit()
  448. {
  449. return SM_SUCCESS;
  450. }
  451. /*
  452.  * mmabort() -- Abort a transaction.
  453.  */
  454. int
  455. mmabort()
  456. {
  457. return SM_SUCCESS;
  458. }
  459. /*
  460.  * MMShmemSize() -- Declare amount of shared memory we require.
  461.  *
  462.  * The shared memory initialization code creates a block of shared
  463.  * memory exactly big enough to hold all the structures it needs to.
  464.  * This routine declares how much space the main memory storage
  465.  * manager will use.
  466.  */
  467. int
  468. MMShmemSize()
  469. {
  470. int size = 0;
  471. /*
  472.  * first compute space occupied by the (dbid,relid,blkno) hash table
  473.  */
  474. size += hash_estimate_size(MMNBUFFERS,
  475.    0, /* MMHashEntry includes key */
  476.    sizeof(MMHashEntry));
  477. /*
  478.  * now do the same for the rel hash table
  479.  */
  480. size += hash_estimate_size(MMNRELATIONS,
  481.    0, /* MMRelHashEntry includes key */
  482.    sizeof(MMRelHashEntry));
  483. /*
  484.  * finally, add in the memory block we use directly
  485.  */
  486. size += MAXALIGN(BLCKSZ * MMNBUFFERS);
  487. size += MAXALIGN(sizeof(*MMCurTop));
  488. size += MAXALIGN(sizeof(*MMCurRelno));
  489. size += MAXALIGN(MMNBUFFERS * sizeof(MMCacheTag));
  490. return size;
  491. }
  492. #endif  /* STABLE_MEMORY_STORAGE */