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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * hio.c
  4.  *   POSTGRES heap access method input/output code.
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Id: hio.c,v 1.22.2.1 1999/08/02 05:56:37 scrappy Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include "postgres.h"
  15. #include "access/heapam.h"
  16. #include "access/hio.h"
  17. /*
  18.  * amputunique - place tuple at tid
  19.  *  Currently on errors, calls elog.  Perhaps should return -1?
  20.  *  Possible errors include the addition of a tuple to the page
  21.  *  between the time the linep is chosen and the page is L_UP'd.
  22.  *
  23.  *  This should be coordinated with the B-tree code.
  24.  *  Probably needs to have an amdelunique to allow for
  25.  *  internal index records to be deleted and reordered as needed.
  26.  *  For the heap AM, this should never be needed.
  27.  *
  28.  *  Note - we assume that caller hold BUFFER_LOCK_EXCLUSIVE on the buffer.
  29.  *
  30.  */
  31. void
  32. RelationPutHeapTuple(Relation relation,
  33.  Buffer buffer,
  34.  HeapTuple tuple)
  35. {
  36. Page pageHeader;
  37. OffsetNumber offnum;
  38. unsigned int len;
  39. ItemId itemId;
  40. Item item;
  41. /* ----------------
  42.  * increment access statistics
  43.  * ----------------
  44.  */
  45. IncrHeapAccessStat(local_RelationPutHeapTuple);
  46. IncrHeapAccessStat(global_RelationPutHeapTuple);
  47. pageHeader = (Page) BufferGetPage(buffer);
  48. len = (unsigned) MAXALIGN(tuple->t_len); /* be conservative */
  49. Assert((int) len <= PageGetFreeSpace(pageHeader));
  50. offnum = PageAddItem((Page) pageHeader, (Item) tuple->t_data,
  51.  tuple->t_len, InvalidOffsetNumber, LP_USED);
  52. itemId = PageGetItemId((Page) pageHeader, offnum);
  53. item = PageGetItem((Page) pageHeader, itemId);
  54. ItemPointerSet(&((HeapTupleHeader) item)->t_ctid,
  55.    BufferGetBlockNumber(buffer), offnum);
  56. /*
  57.  * Let the caller do this!
  58.  *
  59.  * WriteBuffer(buffer);
  60.  */
  61. /* return an accurate tuple */
  62. ItemPointerSet(&tuple->t_self, BufferGetBlockNumber(buffer), offnum);
  63. }
  64. /*
  65.  * This routine is another in the series of attempts to reduce the number
  66.  * of I/O's and system calls executed in the various benchmarks.  In
  67.  * particular, this routine is used to append data to the end of a relation
  68.  * file without excessive lseeks.  This code should do no more than 2 semops
  69.  * in the ideal case.
  70.  *
  71.  * Eventually, we should cache the number of blocks in a relation somewhere.
  72.  * Until that time, this code will have to do an lseek to determine the number
  73.  * of blocks in a relation.
  74.  *
  75.  * This code should ideally do at most 4 semops, 1 lseek, and possibly 1 write
  76.  * to do an append; it's possible to eliminate 2 of the semops if we do direct
  77.  * buffer stuff (!); the lseek and the write can go if we get
  78.  * RelationGetNumberOfBlocks to be useful.
  79.  *
  80.  * NOTE: This code presumes that we have a write lock on the relation.
  81.  * Not now - we use extend locking...
  82.  *
  83.  * Also note that this routine probably shouldn't have to exist, and does
  84.  * screw up the call graph rather badly, but we are wasting so much time and
  85.  * system resources being massively general that we are losing badly in our
  86.  * performance benchmarks.
  87.  */
  88. void
  89. RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
  90. {
  91. Buffer buffer;
  92. Page pageHeader;
  93. BlockNumber lastblock;
  94. OffsetNumber offnum;
  95. unsigned int len;
  96. ItemId itemId;
  97. Item item;
  98. /*
  99.  * Lock relation for extention. We can use LockPage here as long as in
  100.  * all other places we use page-level locking for indices only.
  101.  * Alternatevely, we could define pseudo-table as we do for
  102.  * transactions with XactLockTable.
  103.  */
  104. if (!relation->rd_myxactonly)
  105. LockPage(relation, 0, ExclusiveLock);
  106. /*
  107.  * XXX This does an lseek - VERY expensive - but at the moment it is
  108.  * the only way to accurately determine how many blocks are in a
  109.  * relation.  A good optimization would be to get this to actually
  110.  * work properly.
  111.  */
  112. lastblock = RelationGetNumberOfBlocks(relation);
  113. if (lastblock == 0)
  114. {
  115. buffer = ReadBuffer(relation, lastblock);
  116. pageHeader = (Page) BufferGetPage(buffer);
  117. /*
  118.  * There was IF instead of ASSERT here ?!
  119.  */
  120. Assert(PageIsNew((PageHeader) pageHeader));
  121. buffer = ReleaseAndReadBuffer(buffer, relation, P_NEW);
  122. pageHeader = (Page) BufferGetPage(buffer);
  123. PageInit(pageHeader, BufferGetPageSize(buffer), 0);
  124. }
  125. else
  126. buffer = ReadBuffer(relation, lastblock - 1);
  127. LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
  128. pageHeader = (Page) BufferGetPage(buffer);
  129. len = (unsigned) MAXALIGN(tuple->t_len); /* be conservative */
  130. /*
  131.  * Note that this is true if the above returned a bogus page, which it
  132.  * will do for a completely empty relation.
  133.  */
  134. if (len > PageGetFreeSpace(pageHeader))
  135. {
  136. LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
  137. buffer = ReleaseAndReadBuffer(buffer, relation, P_NEW);
  138. LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
  139. pageHeader = (Page) BufferGetPage(buffer);
  140. PageInit(pageHeader, BufferGetPageSize(buffer), 0);
  141. if (len > PageGetFreeSpace(pageHeader))
  142. elog(ERROR, "Tuple is too big: size %d", len);
  143. }
  144. if (len > MaxTupleSize)
  145. elog(ERROR, "Tuple is too big: size %d, max size %d", len, MaxTupleSize);
  146. if (!relation->rd_myxactonly)
  147. UnlockPage(relation, 0, ExclusiveLock);
  148. offnum = PageAddItem((Page) pageHeader, (Item) tuple->t_data,
  149.  tuple->t_len, InvalidOffsetNumber, LP_USED);
  150. itemId = PageGetItemId((Page) pageHeader, offnum);
  151. item = PageGetItem((Page) pageHeader, itemId);
  152. lastblock = BufferGetBlockNumber(buffer);
  153. ItemPointerSet(&((HeapTupleHeader) item)->t_ctid, lastblock, offnum);
  154. /* return an accurate tuple */
  155. ItemPointerSet(&tuple->t_self, lastblock, offnum);
  156. LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
  157. WriteBuffer(buffer);
  158. }