diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c index 9ffbd0389825eb5f4d09206b725540915e13e770..362b489dac090b0500f5ef7ba6edc24a935946ef 100644 --- a/src/backend/access/gist/gistscan.c +++ b/src/backend/access/gist/gistscan.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.35 2001/05/31 18:16:54 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.36 2001/06/09 18:16:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -83,13 +83,8 @@ gistrescan(PG_FUNCTION_ARGS) /* * Clear all the pointers. */ - - ItemPointerSetInvalid(&s->previousItemData); ItemPointerSetInvalid(&s->currentItemData); - ItemPointerSetInvalid(&s->nextItemData); - ItemPointerSetInvalid(&s->previousMarkData); ItemPointerSetInvalid(&s->currentMarkData); - ItemPointerSetInvalid(&s->nextMarkData); /* * Set flags. diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index fb36736838a13d361f4b2996d202250c96ec0487..91b1763d7597f8f93f55bce096757645af944bbd 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -8,11 +8,10 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.117 2001/05/17 15:55:23 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.118 2001/06/09 18:16:55 tgl Exp $ * * * INTERFACE ROUTINES - * heapgettup - fetch next heap tuple from a scan * heap_open - open a heap relation by relationId * heap_openr - open a heap relation by name * heap_open[r]_nofail - same, but return NULL on failure instead of elog @@ -33,60 +32,20 @@ * the POSTGRES heap access method used for all POSTGRES * relations. * - * OLD COMMENTS - * struct relscan hints: (struct should be made AM independent?) - * - * rs_ctid is the tid of the last tuple returned by getnext. - * rs_ptid and rs_ntid are the tids of the previous and next tuples - * returned by getnext, respectively. NULL indicates an end of - * scan (either direction); NON indicates an unknow value. - * - * possible combinations: - * rs_p rs_c rs_n interpretation - * NULL NULL NULL empty scan - * NULL NULL NON at begining of scan - * NULL NULL t1 at begining of scan (with cached tid) - * NON NULL NULL at end of scan - * t1 NULL NULL at end of scan (with cached tid) - * NULL t1 NULL just returned only tuple - * NULL t1 NON just returned first tuple - * NULL t1 t2 returned first tuple (with cached tid) - * NON t1 NULL just returned last tuple - * t2 t1 NULL returned last tuple (with cached tid) - * t1 t2 NON in the middle of a forward scan - * NON t2 t1 in the middle of a reverse scan - * ti tj tk in the middle of a scan (w cached tid) - * - * Here NULL is ...tup == NULL && ...buf == InvalidBuffer, - * and NON is ...tup == NULL && ...buf == UnknownBuffer. - * - * Currently, the NONTID values are not cached with their actual - * values by getnext. Values may be cached by markpos since it stores - * all three tids. - * - * NOTE: the calls to elog() must stop. Should decide on an interface - * between the general and specific AM calls. - * - * XXX probably do not need a free tuple routine for heaps. - * Huh? Free tuple is not necessary for tuples returned by scans, but - * is necessary for tuples which are returned by - * RelationGetTupleByItemPointer. -hirohama - * *------------------------------------------------------------------------- */ - #include "postgres.h" #include "access/heapam.h" #include "access/hio.h" #include "access/tuptoaster.h" #include "access/valid.h" +#include "access/xlogutils.h" #include "catalog/catalog.h" #include "miscadmin.h" #include "utils/inval.h" #include "utils/relcache.h" -#include "access/xlogutils.h" XLogRecPtr log_heap_move(Relation reln, Buffer oldbuf, ItemPointerData from, Buffer newbuf, HeapTuple newtup); @@ -116,7 +75,6 @@ initscan(HeapScanDesc scan, unsigned nkeys, ScanKey key) { - /* * Make sure we have up-to-date idea of number of blocks in relation. * It is sufficient to do this once at scan start, since any tuples @@ -125,50 +83,12 @@ initscan(HeapScanDesc scan, */ relation->rd_nblocks = RelationGetNumberOfBlocks(relation); - if (relation->rd_nblocks == 0) - { - - /* - * relation is empty - */ - scan->rs_ntup.t_datamcxt = scan->rs_ctup.t_datamcxt = - scan->rs_ptup.t_datamcxt = NULL; - scan->rs_ntup.t_data = scan->rs_ctup.t_data = - scan->rs_ptup.t_data = NULL; - scan->rs_nbuf = scan->rs_cbuf = scan->rs_pbuf = InvalidBuffer; - } - else if (atend) - { - - /* - * reverse scan - */ - scan->rs_ntup.t_datamcxt = scan->rs_ctup.t_datamcxt = NULL; - scan->rs_ntup.t_data = scan->rs_ctup.t_data = NULL; - scan->rs_nbuf = scan->rs_cbuf = InvalidBuffer; - scan->rs_ptup.t_datamcxt = NULL; - scan->rs_ptup.t_data = NULL; - scan->rs_pbuf = UnknownBuffer; - } - else - { - - /* - * forward scan - */ - scan->rs_ctup.t_datamcxt = scan->rs_ptup.t_datamcxt = NULL; - scan->rs_ctup.t_data = scan->rs_ptup.t_data = NULL; - scan->rs_cbuf = scan->rs_pbuf = InvalidBuffer; - scan->rs_ntup.t_datamcxt = NULL; - scan->rs_ntup.t_data = NULL; - scan->rs_nbuf = UnknownBuffer; - } /* invalid too */ + scan->rs_ctup.t_datamcxt = NULL; + scan->rs_ctup.t_data = NULL; + scan->rs_cbuf = InvalidBuffer; /* we don't have a marked position... */ - ItemPointerSetInvalid(&(scan->rs_mptid)); ItemPointerSetInvalid(&(scan->rs_mctid)); - ItemPointerSetInvalid(&(scan->rs_mntid)); - ItemPointerSetInvalid(&(scan->rs_mcd)); /* * copy the scan key, if appropriate @@ -177,62 +97,22 @@ initscan(HeapScanDesc scan, memmove(scan->rs_key, key, nkeys * sizeof(ScanKeyData)); } -/* ---------------- - * unpinscan - code common to heap_rescan and heap_endscan - * ---------------- - */ -static void -unpinscan(HeapScanDesc scan) -{ - if (BufferIsValid(scan->rs_pbuf)) - ReleaseBuffer(scan->rs_pbuf); - - /* - * Scan will pin buffer once for each non-NULL tuple pointer (ptup, - * ctup, ntup), so they have to be unpinned multiple times. - */ - if (BufferIsValid(scan->rs_cbuf)) - ReleaseBuffer(scan->rs_cbuf); - - if (BufferIsValid(scan->rs_nbuf)) - ReleaseBuffer(scan->rs_nbuf); - - /* - * we don't bother to clear rs_pbuf etc --- caller must reinitialize - * them if scan descriptor is not being deleted. - */ -} - -/* ------------------------------------------ - * nextpage - * - * figure out the next page to scan after the current page - * taking into account of possible adjustment of degrees of - * parallelism - * ------------------------------------------ - */ -static int -nextpage(int page, int dir) -{ - return (dir < 0) ? page - 1 : page + 1; -} - /* ---------------- * heapgettup - fetch next heap tuple * * routine used by heap_getnext() which does most of the * real work in scanning tuples. * - * The scan routines handle their own buffer lock/unlocking, so - * there is no reason to request the buffer number unless - * to want to perform some other operation with the result, - * like pass it to another function. + * The passed-in *buffer must be either InvalidBuffer or the pinned + * current page of the scan. If we have to move to another page, + * we will unpin this buffer (if valid). On return, *buffer is either + * InvalidBuffer or the ID of a pinned buffer. * ---------------- */ static void heapgettup(Relation relation, - HeapTuple tuple, int dir, + HeapTuple tuple, Buffer *buffer, Snapshot snapshot, int nkeys, @@ -245,8 +125,7 @@ heapgettup(Relation relation, int lines; OffsetNumber lineoff; int linesleft; - ItemPointer tid = (tuple->t_data == NULL) ? - (ItemPointer) NULL : &(tuple->t_self); + ItemPointer tid; /* * increment access statistics @@ -254,6 +133,8 @@ heapgettup(Relation relation, IncrHeapAccessStat(local_heapgettup); IncrHeapAccessStat(global_heapgettup); + tid = (tuple->t_data == NULL) ? (ItemPointer) NULL : &(tuple->t_self); + /* * debugging stuff * @@ -280,7 +161,10 @@ heapgettup(Relation relation, #endif /* !defined(HEAPDEBUGALL) */ if (!ItemPointerIsValid(tid)) + { Assert(!PointerIsValid(tid)); + tid = NULL; + } tuple->t_tableOid = relation->rd_id; @@ -289,6 +173,9 @@ heapgettup(Relation relation, */ if (!(pages = relation->rd_nblocks)) { + if (BufferIsValid(*buffer)) + ReleaseBuffer(*buffer); + *buffer = InvalidBuffer; tuple->t_datamcxt = NULL; tuple->t_data = NULL; return; @@ -299,22 +186,23 @@ heapgettup(Relation relation, */ if (!dir) { - /* - * ``no movement'' scan direction + * ``no movement'' scan direction: refetch same tuple */ - /* assume it is a valid TID XXX */ - if (ItemPointerIsValid(tid) == false) + if (tid == NULL) { + if (BufferIsValid(*buffer)) + ReleaseBuffer(*buffer); *buffer = InvalidBuffer; tuple->t_datamcxt = NULL; tuple->t_data = NULL; return; } - *buffer = RelationGetBufferWithBuffer(relation, - ItemPointerGetBlockNumber(tid), - *buffer); + *buffer = ReleaseAndReadBuffer(*buffer, + relation, + ItemPointerGetBlockNumber(tid), + false); if (!BufferIsValid(*buffer)) elog(ERROR, "heapgettup: failed ReadBuffer"); @@ -333,12 +221,9 @@ heapgettup(Relation relation, } else if (dir < 0) { - /* * reverse scan direction */ - if (ItemPointerIsValid(tid) == false) - tid = NULL; if (tid == NULL) { page = pages - 1; /* final page */ @@ -349,12 +234,18 @@ heapgettup(Relation relation, } if (page < 0) { + if (BufferIsValid(*buffer)) + ReleaseBuffer(*buffer); *buffer = InvalidBuffer; + tuple->t_datamcxt = NULL; tuple->t_data = NULL; return; } - *buffer = RelationGetBufferWithBuffer(relation, page, *buffer); + *buffer = ReleaseAndReadBuffer(*buffer, + relation, + page, + false); if (!BufferIsValid(*buffer)) elog(ERROR, "heapgettup: failed ReadBuffer"); @@ -376,11 +267,10 @@ heapgettup(Relation relation, } else { - /* * forward scan direction */ - if (ItemPointerIsValid(tid) == false) + if (tid == NULL) { page = 0; /* first page */ lineoff = FirstOffsetNumber; /* first offnum */ @@ -394,14 +284,18 @@ heapgettup(Relation relation, if (page >= pages) { + if (BufferIsValid(*buffer)) + ReleaseBuffer(*buffer); *buffer = InvalidBuffer; tuple->t_datamcxt = NULL; tuple->t_data = NULL; return; } - /* page and lineoff now reference the physically next tid */ - *buffer = RelationGetBufferWithBuffer(relation, page, *buffer); + *buffer = ReleaseAndReadBuffer(*buffer, + relation, + page, + false); if (!BufferIsValid(*buffer)) elog(ERROR, "heapgettup: failed ReadBuffer"); @@ -409,6 +303,8 @@ heapgettup(Relation relation, dp = (Page) BufferGetPage(*buffer); lines = PageGetMaxOffsetNumber(dp); + /* page and lineoff now reference the physically next tid */ + } /* 'dir' is now non-zero */ @@ -469,13 +365,13 @@ heapgettup(Relation relation, /* * if we get here, it means we've exhausted the items on this page - * and it's time to move to the next.. + * and it's time to move to the next. */ LockBuffer(*buffer, BUFFER_LOCK_UNLOCK); - page = nextpage(page, dir); + page = (dir < 0) ? (page - 1) : (page + 1); /* - * return NULL if we've exhausted all the pages.. + * return NULL if we've exhausted all the pages */ if (page < 0 || page >= pages) { @@ -487,10 +383,13 @@ heapgettup(Relation relation, return; } - *buffer = ReleaseAndReadBuffer(*buffer, relation, page, false); - + *buffer = ReleaseAndReadBuffer(*buffer, + relation, + page, + false); if (!BufferIsValid(*buffer)) elog(ERROR, "heapgettup: failed ReadBuffer"); + LockBuffer(*buffer, BUFFER_LOCK_SHARE); dp = (Page) BufferGetPage(*buffer); lines = PageGetMaxOffsetNumber((Page) dp); @@ -766,7 +665,6 @@ heap_beginscan(Relation relation, scan = (HeapScanDesc) palloc(sizeof(HeapScanDescData)); scan->rs_rd = relation; - scan->rs_atend = atend; scan->rs_snapshot = snapshot; scan->rs_nkeys = (short) nkeys; @@ -793,7 +691,6 @@ heap_rescan(HeapScanDesc scan, bool scanFromEnd, ScanKey key) { - /* * increment access statistics */ @@ -803,12 +700,12 @@ heap_rescan(HeapScanDesc scan, /* * unpin scan buffers */ - unpinscan(scan); + if (BufferIsValid(scan->rs_cbuf)) + ReleaseBuffer(scan->rs_cbuf); /* * reinitialize scan descriptor */ - scan->rs_atend = scanFromEnd; initscan(scan, scan->rs_rd, scanFromEnd, scan->rs_nkeys, key); } @@ -822,7 +719,6 @@ heap_rescan(HeapScanDesc scan, void heap_endscan(HeapScanDesc scan) { - /* * increment access statistics */ @@ -834,7 +730,8 @@ heap_endscan(HeapScanDesc scan) /* * unpin scan buffers */ - unpinscan(scan); + if (BufferIsValid(scan->rs_cbuf)) + ReleaseBuffer(scan->rs_cbuf); /* * decrement relation reference count and free scan descriptor storage @@ -862,38 +759,20 @@ elog(DEBUG, "heap_getnext([%s,nkeys=%d],backw=%d) called", \ RelationGetRelationName(scan->rs_rd), scan->rs_nkeys, backw) #define HEAPDEBUG_2 \ - elog(DEBUG, "heap_getnext called with backw (no tracing yet)") - -#define HEAPDEBUG_3 \ - elog(DEBUG, "heap_getnext returns NULL at end") - -#define HEAPDEBUG_4 \ - elog(DEBUG, "heap_getnext valid buffer UNPIN'd") - -#define HEAPDEBUG_5 \ - elog(DEBUG, "heap_getnext next tuple was cached") - -#define HEAPDEBUG_6 \ elog(DEBUG, "heap_getnext returning EOS") -#define HEAPDEBUG_7 \ +#define HEAPDEBUG_3 \ elog(DEBUG, "heap_getnext returning tuple"); #else #define HEAPDEBUG_1 #define HEAPDEBUG_2 #define HEAPDEBUG_3 -#define HEAPDEBUG_4 -#define HEAPDEBUG_5 -#define HEAPDEBUG_6 -#define HEAPDEBUG_7 #endif /* !defined(HEAPDEBUGALL) */ HeapTuple -heap_getnext(HeapScanDesc scandesc, int backw) +heap_getnext(HeapScanDesc scan, int backw) { - HeapScanDesc scan = scandesc; - /* * increment access statistics */ @@ -908,165 +787,45 @@ heap_getnext(HeapScanDesc scandesc, int backw) if (scan == NULL) elog(ERROR, "heap_getnext: NULL relscan"); - /* - * initialize return buffer to InvalidBuffer - */ - HEAPDEBUG_1; /* heap_getnext( info ) */ if (backw) { - /* * handle reverse scan */ - HEAPDEBUG_2; /* heap_getnext called with backw */ - - if (scan->rs_ptup.t_data == scan->rs_ctup.t_data && - BufferIsInvalid(scan->rs_pbuf)) - return NULL; - - /* - * Copy the "current" tuple/buffer to "next". Pin/unpin the - * buffers accordingly - */ - if (scan->rs_nbuf != scan->rs_cbuf) - { - if (BufferIsValid(scan->rs_nbuf)) - ReleaseBuffer(scan->rs_nbuf); - if (BufferIsValid(scan->rs_cbuf)) - IncrBufferRefCount(scan->rs_cbuf); - } - scan->rs_ntup = scan->rs_ctup; - scan->rs_nbuf = scan->rs_cbuf; - - if (scan->rs_ptup.t_data != NULL) - { - if (scan->rs_cbuf != scan->rs_pbuf) - { - if (BufferIsValid(scan->rs_cbuf)) - ReleaseBuffer(scan->rs_cbuf); - if (BufferIsValid(scan->rs_pbuf)) - IncrBufferRefCount(scan->rs_pbuf); - } - scan->rs_ctup = scan->rs_ptup; - scan->rs_cbuf = scan->rs_pbuf; - } - else - { /* NONTUP */ - - /* - * Don't release scan->rs_cbuf at this point, because - * heapgettup doesn't increase PrivateRefCount if it is - * already set. On a backward scan, both rs_ctup and rs_ntup - * usually point to the same buffer page, so - * PrivateRefCount[rs_cbuf] should be 2 (or more, if for - * instance ctup is stored in a TupleTableSlot). - 01/09/94 - */ - - heapgettup(scan->rs_rd, - &(scan->rs_ctup), - -1, - &(scan->rs_cbuf), - scan->rs_snapshot, - scan->rs_nkeys, - scan->rs_key); - } + heapgettup(scan->rs_rd, + -1, + &(scan->rs_ctup), + &(scan->rs_cbuf), + scan->rs_snapshot, + scan->rs_nkeys, + scan->rs_key); if (scan->rs_ctup.t_data == NULL && !BufferIsValid(scan->rs_cbuf)) { - if (BufferIsValid(scan->rs_pbuf)) - ReleaseBuffer(scan->rs_pbuf); - scan->rs_ptup.t_datamcxt = NULL; - scan->rs_ptup.t_data = NULL; - scan->rs_pbuf = InvalidBuffer; + HEAPDEBUG_2; /* heap_getnext returning EOS */ return NULL; } - - if (BufferIsValid(scan->rs_pbuf)) - ReleaseBuffer(scan->rs_pbuf); - scan->rs_ptup.t_datamcxt = NULL; - scan->rs_ptup.t_data = NULL; - scan->rs_pbuf = UnknownBuffer; - } else { - /* * handle forward scan */ - if (scan->rs_ctup.t_data == scan->rs_ntup.t_data && - BufferIsInvalid(scan->rs_nbuf)) - { - HEAPDEBUG_3; /* heap_getnext returns NULL at end */ - return NULL; - } - - /* - * Copy the "current" tuple/buffer to "previous". Pin/unpin the - * buffers accordingly - */ - if (scan->rs_pbuf != scan->rs_cbuf) - { - if (BufferIsValid(scan->rs_pbuf)) - ReleaseBuffer(scan->rs_pbuf); - if (BufferIsValid(scan->rs_cbuf)) - IncrBufferRefCount(scan->rs_cbuf); - } - scan->rs_ptup = scan->rs_ctup; - scan->rs_pbuf = scan->rs_cbuf; - - if (scan->rs_ntup.t_data != NULL) - { - if (scan->rs_cbuf != scan->rs_nbuf) - { - if (BufferIsValid(scan->rs_cbuf)) - ReleaseBuffer(scan->rs_cbuf); - if (BufferIsValid(scan->rs_nbuf)) - IncrBufferRefCount(scan->rs_nbuf); - } - scan->rs_ctup = scan->rs_ntup; - scan->rs_cbuf = scan->rs_nbuf; - HEAPDEBUG_5; /* heap_getnext next tuple was cached */ - } - else - { /* NONTUP */ - - /* - * Don't release scan->rs_cbuf at this point, because - * heapgettup doesn't increase PrivateRefCount if it is - * already set. On a forward scan, both rs_ctup and rs_ptup - * usually point to the same buffer page, so - * PrivateRefCount[rs_cbuf] should be 2 (or more, if for - * instance ctup is stored in a TupleTableSlot). - 01/09/93 - */ - - heapgettup(scan->rs_rd, - &(scan->rs_ctup), - 1, - &scan->rs_cbuf, - scan->rs_snapshot, - scan->rs_nkeys, - scan->rs_key); - } + heapgettup(scan->rs_rd, + 1, + &(scan->rs_ctup), + &(scan->rs_cbuf), + scan->rs_snapshot, + scan->rs_nkeys, + scan->rs_key); if (scan->rs_ctup.t_data == NULL && !BufferIsValid(scan->rs_cbuf)) { - if (BufferIsValid(scan->rs_nbuf)) - ReleaseBuffer(scan->rs_nbuf); - scan->rs_ntup.t_datamcxt = NULL; - scan->rs_ntup.t_data = NULL; - scan->rs_nbuf = InvalidBuffer; - HEAPDEBUG_6; /* heap_getnext returning EOS */ + HEAPDEBUG_2; /* heap_getnext returning EOS */ return NULL; } - - if (BufferIsValid(scan->rs_nbuf)) - ReleaseBuffer(scan->rs_nbuf); - scan->rs_ntup.t_datamcxt = NULL; - scan->rs_ntup.t_data = NULL; - scan->rs_nbuf = UnknownBuffer; } /* @@ -1074,7 +833,7 @@ heap_getnext(HeapScanDesc scandesc, int backw) * to the proper return buffer and return the tuple. */ - HEAPDEBUG_7; /* heap_getnext returning tuple */ + HEAPDEBUG_3; /* heap_getnext returning tuple */ return ((scan->rs_ctup.t_data == NULL) ? NULL : &(scan->rs_ctup)); } @@ -1987,7 +1746,6 @@ l3: void heap_markpos(HeapScanDesc scan) { - /* * increment access statistics */ @@ -1996,47 +1754,10 @@ heap_markpos(HeapScanDesc scan) /* Note: no locking manipulations needed */ - if (scan->rs_ptup.t_data == NULL && - BufferIsUnknown(scan->rs_pbuf)) - { /* == NONTUP */ - scan->rs_ptup = scan->rs_ctup; - heapgettup(scan->rs_rd, - &(scan->rs_ptup), - -1, - &scan->rs_pbuf, - scan->rs_snapshot, - scan->rs_nkeys, - scan->rs_key); - - } - else if (scan->rs_ntup.t_data == NULL && - BufferIsUnknown(scan->rs_nbuf)) - { /* == NONTUP */ - scan->rs_ntup = scan->rs_ctup; - heapgettup(scan->rs_rd, - &(scan->rs_ntup), - 1, - &scan->rs_nbuf, - scan->rs_snapshot, - scan->rs_nkeys, - scan->rs_key); - } - - /* - * Should not unpin the buffer pages. They may still be in use. - */ - if (scan->rs_ptup.t_data != NULL) - scan->rs_mptid = scan->rs_ptup.t_self; - else - ItemPointerSetInvalid(&scan->rs_mptid); if (scan->rs_ctup.t_data != NULL) scan->rs_mctid = scan->rs_ctup.t_self; else ItemPointerSetInvalid(&scan->rs_mctid); - if (scan->rs_ntup.t_data != NULL) - scan->rs_mntid = scan->rs_ntup.t_self; - else - ItemPointerSetInvalid(&scan->rs_mntid); } /* ---------------- @@ -2048,10 +1769,6 @@ heap_markpos(HeapScanDesc scan) * cause the added tuples to be visible when the scan continues. * Problems also arise if the TID's are rearranged!!! * - * Now pins buffer once for each valid tuple pointer (rs_ptup, - * rs_ctup, rs_ntup) referencing it. - * - 01/13/94 - * * XXX might be better to do direct access instead of * using the generality of heapgettup(). * @@ -2063,7 +1780,6 @@ heap_markpos(HeapScanDesc scan) void heap_restrpos(HeapScanDesc scan) { - /* * increment access statistics */ @@ -2074,31 +1790,12 @@ heap_restrpos(HeapScanDesc scan) /* Note: no locking manipulations needed */ - unpinscan(scan); - - /* force heapgettup to pin buffer for each loaded tuple */ - scan->rs_pbuf = InvalidBuffer; + /* + * unpin scan buffers + */ + if (BufferIsValid(scan->rs_cbuf)) + ReleaseBuffer(scan->rs_cbuf); scan->rs_cbuf = InvalidBuffer; - scan->rs_nbuf = InvalidBuffer; - - if (!ItemPointerIsValid(&scan->rs_mptid)) - { - scan->rs_ptup.t_datamcxt = NULL; - scan->rs_ptup.t_data = NULL; - } - else - { - scan->rs_ptup.t_self = scan->rs_mptid; - scan->rs_ptup.t_datamcxt = NULL; - scan->rs_ptup.t_data = (HeapTupleHeader) 0x1; /* for heapgettup */ - heapgettup(scan->rs_rd, - &(scan->rs_ptup), - 0, - &(scan->rs_pbuf), - false, - 0, - (ScanKey) NULL); - } if (!ItemPointerIsValid(&scan->rs_mctid)) { @@ -2111,29 +1808,10 @@ heap_restrpos(HeapScanDesc scan) scan->rs_ctup.t_datamcxt = NULL; scan->rs_ctup.t_data = (HeapTupleHeader) 0x1; /* for heapgettup */ heapgettup(scan->rs_rd, - &(scan->rs_ctup), 0, + &(scan->rs_ctup), &(scan->rs_cbuf), - false, - 0, - (ScanKey) NULL); - } - - if (!ItemPointerIsValid(&scan->rs_mntid)) - { - scan->rs_ntup.t_datamcxt = NULL; - scan->rs_ntup.t_data = NULL; - } - else - { - scan->rs_ntup.t_datamcxt = NULL; - scan->rs_ntup.t_self = scan->rs_mntid; - scan->rs_ntup.t_data = (HeapTupleHeader) 0x1; /* for heapgettup */ - heapgettup(scan->rs_rd, - &(scan->rs_ntup), - 0, - &scan->rs_nbuf, - false, + scan->rs_snapshot, 0, (ScanKey) NULL); } diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c index 13499eef0a8cfb066a1ed2ca13d5f5a52edbcdda..ee9cea6646ce3cebe89ed04152522c7682be6086 100644 --- a/src/backend/access/index/genam.c +++ b/src/backend/access/index/genam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/index/genam.c,v 1.26 2001/01/24 19:42:48 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/index/genam.c,v 1.27 2001/06/09 18:16:56 tgl Exp $ * * NOTES * many of the old access method routines have been turned into @@ -107,12 +107,8 @@ RelationGetIndexScan(Relation relation, scan->opaque = NULL; scan->numberOfKeys = numberOfKeys; - ItemPointerSetInvalid(&scan->previousItemData); ItemPointerSetInvalid(&scan->currentItemData); - ItemPointerSetInvalid(&scan->nextItemData); - ItemPointerSetInvalid(&scan->previousMarkData); ItemPointerSetInvalid(&scan->currentMarkData); - ItemPointerSetInvalid(&scan->nextMarkData); /* * mark cached function lookup data invalid; it will be set on first @@ -176,9 +172,7 @@ IndexScanRestart(IndexScanDesc scan, if (!IndexScanIsValid(scan)) elog(ERROR, "IndexScanRestart: invalid scan"); - ItemPointerSetInvalid(&scan->previousItemData); ItemPointerSetInvalid(&scan->currentItemData); - ItemPointerSetInvalid(&scan->nextItemData); if (RelationGetNumberOfBlocks(scan->relation) == 0) scan->flags = ScanUnmarked; @@ -213,37 +207,7 @@ IndexScanRestart(IndexScanDesc scan, void IndexScanMarkPosition(IndexScanDesc scan) { - RetrieveIndexResult result; - - if (scan->flags & ScanUncheckedPrevious) - { - result = index_getnext(scan, BackwardScanDirection); - - if (result != NULL) - { - scan->previousItemData = result->index_iptr; - pfree(result); - } - else - ItemPointerSetInvalid(&scan->previousItemData); - } - else if (scan->flags & ScanUncheckedNext) - { - result = (RetrieveIndexResult) - index_getnext(scan, ForwardScanDirection); - - if (result != NULL) - { - scan->nextItemData = result->index_iptr; - pfree(result); - } - else - ItemPointerSetInvalid(&scan->nextItemData); - } - - scan->previousMarkData = scan->previousItemData; scan->currentMarkData = scan->currentItemData; - scan->nextMarkData = scan->nextItemData; scan->flags = 0x0; /* XXX should have a symbolic name */ } @@ -269,9 +233,7 @@ IndexScanRestorePosition(IndexScanDesc scan) if (scan->flags & ScanUnmarked) elog(ERROR, "IndexScanRestorePosition: no mark to restore"); - scan->previousItemData = scan->previousMarkData; scan->currentItemData = scan->currentMarkData; - scan->nextItemData = scan->nextMarkData; scan->flags = 0x0; /* XXX should have a symbolic name */ } diff --git a/src/backend/access/rtree/rtscan.c b/src/backend/access/rtree/rtscan.c index f3e6d52fe67314abb06c34e929f90cce963c94b7..c9f1ab7b893c6b4752f20155054ec60ff8239fe4 100644 --- a/src/backend/access/rtree/rtscan.c +++ b/src/backend/access/rtree/rtscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.36 2001/03/22 03:59:16 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.37 2001/06/09 18:16:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -85,13 +85,8 @@ rtrescan(PG_FUNCTION_ARGS) /* * Clear all the pointers. */ - - ItemPointerSetInvalid(&s->previousItemData); ItemPointerSetInvalid(&s->currentItemData); - ItemPointerSetInvalid(&s->nextItemData); - ItemPointerSetInvalid(&s->previousMarkData); ItemPointerSetInvalid(&s->currentMarkData); - ItemPointerSetInvalid(&s->nextMarkData); /* * Set flags. diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index d5ff24df0227f19a0a954c71280bb795bd4c3efb..06abd2e8675da388c867c6b6e7c93b9c9fbd9dd6 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.111 2001/05/12 19:58:27 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.112 2001/06/09 18:16:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -96,43 +96,6 @@ static int ReleaseBufferWithBufferLock(Buffer buffer); static int BufferReplace(BufferDesc *bufHdr); void PrintBufferDescs(void); -/* --------------------------------------------------- - * RelationGetBufferWithBuffer - * see if the given buffer is what we want - * if yes, we don't need to bother the buffer manager - * --------------------------------------------------- - */ -Buffer -RelationGetBufferWithBuffer(Relation relation, - BlockNumber blockNumber, - Buffer buffer) -{ - BufferDesc *bufHdr; - - if (BufferIsValid(buffer)) - { - if (!BufferIsLocal(buffer)) - { - bufHdr = &BufferDescriptors[buffer - 1]; - SpinAcquire(BufMgrLock); - if (bufHdr->tag.blockNum == blockNumber && - RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node)) - { - SpinRelease(BufMgrLock); - return buffer; - } - return ReadBufferInternal(relation, blockNumber, false, true); - } - else - { - bufHdr = &LocalBufferDescriptors[-buffer - 1]; - if (bufHdr->tag.blockNum == blockNumber && - RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node)) - return buffer; - } - } - return ReadBufferInternal(relation, blockNumber, false, false); -} /* * ReadBuffer -- returns a buffer containing the requested @@ -141,7 +104,8 @@ RelationGetBufferWithBuffer(Relation relation, * allocate a new block. * * Returns: the buffer number for the buffer containing - * the block read or NULL on an error. + * the block read, or NULL on an error. If successful, + * the returned buffer has been pinned. * * Assume when this function is called, that reln has been * opened already. @@ -300,8 +264,8 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum, } /* - * BufferAlloc -- Get a buffer from the buffer pool but dont - * read it. + * BufferAlloc -- Get a buffer from the buffer pool but don't + * read it. If successful, the returned buffer is pinned. * * Returns: descriptor for buffer * @@ -684,6 +648,11 @@ WriteNoReleaseBuffer(Buffer buffer) * Note: it is OK to pass buffer = InvalidBuffer, indicating that no old * buffer actually needs to be released. This case is the same as ReadBuffer * except for the isExtend option. + * + * Also, if the passed buffer is valid and already contains the desired block + * number, we simply return it without ever acquiring the spinlock at all. + * Since the passed buffer must be pinned, it's OK to examine its block + * number without getting the lock first. */ Buffer ReleaseAndReadBuffer(Buffer buffer, @@ -698,12 +667,19 @@ ReleaseAndReadBuffer(Buffer buffer, if (BufferIsLocal(buffer)) { Assert(LocalRefCount[-buffer - 1] > 0); + bufHdr = &LocalBufferDescriptors[-buffer - 1]; + if (bufHdr->tag.blockNum == blockNum && + RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node)) + return buffer; LocalRefCount[-buffer - 1]--; } else { - bufHdr = &BufferDescriptors[buffer - 1]; Assert(PrivateRefCount[buffer - 1] > 0); + bufHdr = &BufferDescriptors[buffer - 1]; + if (bufHdr->tag.blockNum == blockNum && + RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node)) + return buffer; if (PrivateRefCount[buffer - 1] > 1) PrivateRefCount[buffer - 1]--; else @@ -1002,7 +978,7 @@ BufferPoolCheckLeak() BufferDesc *buf = &(BufferDescriptors[i - 1]); elog(NOTICE, - "Buffer Leak: [%03d] (freeNext=%ld, freePrev=%ld, \ + "Buffer Leak: [%03d] (freeNext=%d, freePrev=%d, \ relname=%s, blockNum=%d, flags=0x%x, refcount=%d %ld)", i - 1, buf->freeNext, buf->freePrev, buf->blind.relname, buf->tag.blockNum, buf->flags, @@ -1396,7 +1372,7 @@ PrintBufferDescs() SpinAcquire(BufMgrLock); for (i = 0; i < NBuffers; ++i, ++buf) { - elog(DEBUG, "[%02d] (freeNext=%ld, freePrev=%ld, relname=%s, \ + elog(DEBUG, "[%02d] (freeNext=%d, freePrev=%d, relname=%s, \ blockNum=%d, flags=0x%x, refcount=%d %ld)", i, buf->freeNext, buf->freePrev, buf->blind.relname, buf->tag.blockNum, buf->flags, @@ -1426,7 +1402,7 @@ PrintPinnedBufs() for (i = 0; i < NBuffers; ++i, ++buf) { if (PrivateRefCount[i] > 0) - elog(NOTICE, "[%02d] (freeNext=%ld, freePrev=%ld, relname=%s, \ + elog(NOTICE, "[%02d] (freeNext=%d, freePrev=%d, relname=%s, \ blockNum=%d, flags=0x%x, refcount=%d %ld)\n", i, buf->freeNext, buf->freePrev, buf->blind.relname, buf->tag.blockNum, buf->flags, @@ -1719,7 +1695,7 @@ IncrBufferRefCount_Debug(char *file, int line, Buffer buffer) { BufferDesc *buf = &BufferDescriptors[buffer - 1]; - fprintf(stderr, "PIN(Incr) %ld relname = %s, blockNum = %d, \ + fprintf(stderr, "PIN(Incr) %d relname = %s, blockNum = %d, \ refcount = %ld, file: %s, line: %d\n", buffer, buf->blind.relname, buf->tag.blockNum, PrivateRefCount[buffer - 1], file, line); @@ -1737,7 +1713,7 @@ ReleaseBuffer_Debug(char *file, int line, Buffer buffer) { BufferDesc *buf = &BufferDescriptors[buffer - 1]; - fprintf(stderr, "UNPIN(Rel) %ld relname = %s, blockNum = %d, \ + fprintf(stderr, "UNPIN(Rel) %d relname = %s, blockNum = %d, \ refcount = %ld, file: %s, line: %d\n", buffer, buf->blind.relname, buf->tag.blockNum, PrivateRefCount[buffer - 1], file, line); @@ -1765,7 +1741,7 @@ ReleaseAndReadBuffer_Debug(char *file, { BufferDesc *buf = &BufferDescriptors[buffer - 1]; - fprintf(stderr, "UNPIN(Rel&Rd) %ld relname = %s, blockNum = %d, \ + fprintf(stderr, "UNPIN(Rel&Rd) %d relname = %s, blockNum = %d, \ refcount = %ld, file: %s, line: %d\n", buffer, buf->blind.relname, buf->tag.blockNum, PrivateRefCount[buffer - 1], file, line); @@ -1774,7 +1750,7 @@ refcount = %ld, file: %s, line: %d\n", { BufferDesc *buf = &BufferDescriptors[b - 1]; - fprintf(stderr, "PIN(Rel&Rd) %ld relname = %s, blockNum = %d, \ + fprintf(stderr, "PIN(Rel&Rd) %d relname = %s, blockNum = %d, \ refcount = %ld, file: %s, line: %d\n", b, buf->blind.relname, buf->tag.blockNum, PrivateRefCount[b - 1], file, line); @@ -2057,7 +2033,7 @@ LockBuffer(Buffer buffer, int mode) { S_UNLOCK(&(buf->cntx_lock)); RESUME_INTERRUPTS(); - elog(ERROR, "UNLockBuffer: buffer %lu is not locked", buffer); + elog(ERROR, "UNLockBuffer: buffer %d is not locked", buffer); } } else if (mode == BUFFER_LOCK_SHARE) diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h index b97b52979e467a022880d9ce0366b84f923f830a..8bfb514b1e445ed7af2e101390407f8ee2a21171 100644 --- a/src/include/access/relscan.h +++ b/src/include/access/relscan.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: relscan.h,v 1.20 2001/01/24 19:43:19 momjian Exp $ + * $Id: relscan.h,v 1.21 2001/06/09 18:16:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,25 +16,16 @@ #include "utils/tqual.h" -typedef ItemPointerData MarkData; typedef struct HeapScanDescData { Relation rs_rd; /* pointer to relation descriptor */ - HeapTupleData rs_ptup; /* previous tuple in scan */ - HeapTupleData rs_ctup; /* current tuple in scan */ - HeapTupleData rs_ntup; /* next tuple in scan */ - Buffer rs_pbuf; /* previous buffer in scan */ - Buffer rs_cbuf; /* current buffer in scan */ - Buffer rs_nbuf; /* next buffer in scan */ - ItemPointerData rs_mptid; /* marked previous tid */ - ItemPointerData rs_mctid; /* marked current tid */ - ItemPointerData rs_mntid; /* marked next tid */ - ItemPointerData rs_mcd; /* marked current delta XXX ??? */ + HeapTupleData rs_ctup; /* current tuple in scan, if any */ + Buffer rs_cbuf; /* current buffer in scan, if any */ + /* NB: if rs_cbuf is not InvalidBuffer, we hold a pin on that buffer */ + ItemPointerData rs_mctid; /* marked tid, if any */ Snapshot rs_snapshot; /* snapshot to see */ - bool rs_atend; /* restart scan at end? */ - uint16 rs_cdelta; /* current delta in chain */ - uint16 rs_nkeys; /* number of attributes in keys */ + uint16 rs_nkeys; /* number of scan keys to select tuples */ ScanKey rs_key; /* key descriptors */ } HeapScanDescData; @@ -43,22 +34,24 @@ typedef HeapScanDescData *HeapScanDesc; typedef struct IndexScanDescData { Relation relation; /* relation descriptor */ - void *opaque; /* am-specific slot */ - ItemPointerData previousItemData; /* previous index pointer */ + void *opaque; /* access-method-specific info */ ItemPointerData currentItemData; /* current index pointer */ - ItemPointerData nextItemData; /* next index pointer */ - MarkData previousMarkData; /* marked previous pointer */ - MarkData currentMarkData;/* marked current pointer */ - MarkData nextMarkData; /* marked next pointer */ + ItemPointerData currentMarkData; /* marked current pointer */ uint8 flags; /* scan position flags */ bool scanFromEnd; /* restart scan at end? */ - uint16 numberOfKeys; /* number of key attributes */ - ScanKey keyData; /* key descriptor */ + uint16 numberOfKeys; /* number of scan keys to select tuples */ + ScanKey keyData; /* key descriptors */ FmgrInfo fn_getnext; /* cached lookup info for am's getnext fn */ } IndexScanDescData; typedef IndexScanDescData *IndexScanDesc; +/* IndexScanDesc flag bits (none of these are actually used currently) */ +#define ScanUnmarked 0x01 +#define ScanUncheckedPrevious 0x02 +#define ScanUncheckedNext 0x04 + + /* ---------------- * IndexScanDescPtr is used in the executor where we have to * keep track of several index scans when using several indices diff --git a/src/include/access/skey.h b/src/include/access/skey.h index 2a00e26744e4caf611835f435fbe7abe2f7134b5..4e49f51afb1cc86b4178e589e5d35dc440726c03 100644 --- a/src/include/access/skey.h +++ b/src/include/access/skey.h @@ -7,8 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: skey.h,v 1.15 2001/06/01 02:41:36 tgl Exp $ - * + * $Id: skey.h,v 1.16 2001/06/09 18:16:59 tgl Exp $ * * Note: * Needs more accessor/assignment routines. @@ -20,6 +19,7 @@ #include "access/attnum.h" #include "fmgr.h" + typedef struct ScanKeyData { bits16 sk_flags; /* flags */ @@ -38,11 +38,6 @@ typedef ScanKeyData *ScanKey; #define SK_COMMUTE 0x8 /* commute function (not fully supported) */ -#define ScanUnmarked 0x01 -#define ScanUncheckedPrevious 0x02 -#define ScanUncheckedNext 0x04 - - /* * prototypes for functions in access/common/scankey.c */ diff --git a/src/include/storage/buf.h b/src/include/storage/buf.h index c65e4cc9975ae04179a55ebe93c417827bd8f3ff..f31d5d5cc8d20be72394562eb615eac1cecdc9e8 100644 --- a/src/include/storage/buf.h +++ b/src/include/storage/buf.h @@ -7,17 +7,22 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: buf.h,v 1.8 2001/01/24 19:43:27 momjian Exp $ + * $Id: buf.h,v 1.9 2001/06/09 18:16:59 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef BUF_H #define BUF_H -#define InvalidBuffer (0) -#define UnknownBuffer (-99999) +/* + * Buffer identifiers. + * + * Zero is invalid, positive is the index of a shared buffer (1..NBuffers), + * negative is the index of a local buffer (-1 .. -NLocBuffer). + */ +typedef int Buffer; -typedef long Buffer; +#define InvalidBuffer 0 /* * BufferIsInvalid @@ -25,12 +30,6 @@ typedef long Buffer; */ #define BufferIsInvalid(buffer) ((buffer) == InvalidBuffer) -/* - * BufferIsUnknown - * True iff the buffer is unknown. - */ -#define BufferIsUnknown(buffer) ((buffer) == UnknownBuffer) - /* * BufferIsLocal * True iff the buffer is local (not visible to other servers). diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h index d45c8888c1d0ebacf3a120762b64591e9dac9ee9..9d7f568e193f811a459063dd37787f1520cec561 100644 --- a/src/include/storage/bufmgr.h +++ b/src/include/storage/bufmgr.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: bufmgr.h,v 1.51 2001/05/12 19:58:28 tgl Exp $ + * $Id: bufmgr.h,v 1.52 2001/06/09 18:16:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -75,10 +75,6 @@ extern long *LocalRefCount; * True iff the given buffer number is valid (either as a shared * or local buffer). * - * Note: - * BufferIsValid(InvalidBuffer) is False. - * BufferIsValid(UnknownBuffer) is False. - * * Note: For a long time this was defined the same as BufferIsPinned, * that is it would say False if you didn't hold a pin on the buffer. * I believe this was bogus and served only to mask logic errors. @@ -158,8 +154,6 @@ extern long *LocalRefCount; /* * prototypes for functions in bufmgr.c */ -extern Buffer RelationGetBufferWithBuffer(Relation relation, - BlockNumber blockNumber, Buffer buffer); extern Buffer ReadBuffer(Relation reln, BlockNumber blockNum); extern int WriteBuffer(Buffer buffer); extern int WriteNoReleaseBuffer(Buffer buffer);