mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
Postgres95 1.01 Distribution - Virgin Sources
This commit is contained in:
164
src/backend/access/nbtree/nbtscan.c
Normal file
164
src/backend/access/nbtree/nbtscan.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* btscan.c--
|
||||
* manage scans on btrees.
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/Attic/nbtscan.c,v 1.1.1.1 1996/07/09 06:21:12 scrappy Exp $
|
||||
*
|
||||
*
|
||||
* NOTES
|
||||
* Because we can be doing an index scan on a relation while we update
|
||||
* it, we need to avoid missing data that moves around in the index.
|
||||
* The routines and global variables in this file guarantee that all
|
||||
* scans in the local address space stay correctly positioned. This
|
||||
* is all we need to worry about, since write locking guarantees that
|
||||
* no one else will be on the same page at the same time as we are.
|
||||
*
|
||||
* The scheme is to manage a list of active scans in the current backend.
|
||||
* Whenever we add or remove records from an index, or whenever we
|
||||
* split a leaf page, we check the list of active scans to see if any
|
||||
* has been affected. A scan is affected only if it is on the same
|
||||
* relation, and the same page, as the update.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "storage/bufmgr.h"
|
||||
#include "storage/bufpage.h"
|
||||
|
||||
#include "utils/elog.h"
|
||||
#include "utils/palloc.h"
|
||||
#include "utils/rel.h"
|
||||
#include "utils/excid.h"
|
||||
|
||||
#include "access/heapam.h"
|
||||
#include "access/genam.h"
|
||||
#include "access/sdir.h"
|
||||
#include "access/nbtree.h"
|
||||
|
||||
typedef struct BTScanListData {
|
||||
IndexScanDesc btsl_scan;
|
||||
struct BTScanListData *btsl_next;
|
||||
} BTScanListData;
|
||||
|
||||
typedef BTScanListData *BTScanList;
|
||||
|
||||
static BTScanList BTScans = (BTScanList) NULL;
|
||||
|
||||
/*
|
||||
* _bt_regscan() -- register a new scan.
|
||||
*/
|
||||
void
|
||||
_bt_regscan(IndexScanDesc scan)
|
||||
{
|
||||
BTScanList new_el;
|
||||
|
||||
new_el = (BTScanList) palloc(sizeof(BTScanListData));
|
||||
new_el->btsl_scan = scan;
|
||||
new_el->btsl_next = BTScans;
|
||||
BTScans = new_el;
|
||||
}
|
||||
|
||||
/*
|
||||
* _bt_dropscan() -- drop a scan from the scan list
|
||||
*/
|
||||
void
|
||||
_bt_dropscan(IndexScanDesc scan)
|
||||
{
|
||||
BTScanList chk, last;
|
||||
|
||||
last = (BTScanList) NULL;
|
||||
for (chk = BTScans;
|
||||
chk != (BTScanList) NULL && chk->btsl_scan != scan;
|
||||
chk = chk->btsl_next) {
|
||||
last = chk;
|
||||
}
|
||||
|
||||
if (chk == (BTScanList) NULL)
|
||||
elog(WARN, "btree scan list trashed; can't find 0x%lx", scan);
|
||||
|
||||
if (last == (BTScanList) NULL)
|
||||
BTScans = chk->btsl_next;
|
||||
else
|
||||
last->btsl_next = chk->btsl_next;
|
||||
|
||||
#ifdef PERFECT_MEM
|
||||
pfree (chk);
|
||||
#endif /* PERFECT_MEM */
|
||||
}
|
||||
|
||||
void
|
||||
_bt_adjscans(Relation rel, ItemPointer tid)
|
||||
{
|
||||
BTScanList l;
|
||||
Oid relid;
|
||||
|
||||
relid = rel->rd_id;
|
||||
for (l = BTScans; l != (BTScanList) NULL; l = l->btsl_next) {
|
||||
if (relid == l->btsl_scan->relation->rd_id)
|
||||
_bt_scandel(l->btsl_scan, ItemPointerGetBlockNumber(tid),
|
||||
ItemPointerGetOffsetNumber(tid));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_bt_scandel(IndexScanDesc scan, BlockNumber blkno, OffsetNumber offno)
|
||||
{
|
||||
ItemPointer current;
|
||||
Buffer buf;
|
||||
BTScanOpaque so;
|
||||
|
||||
if (!_bt_scantouched(scan, blkno, offno))
|
||||
return;
|
||||
|
||||
so = (BTScanOpaque) scan->opaque;
|
||||
buf = so->btso_curbuf;
|
||||
|
||||
current = &(scan->currentItemData);
|
||||
if (ItemPointerIsValid(current)
|
||||
&& ItemPointerGetBlockNumber(current) == blkno
|
||||
&& ItemPointerGetOffsetNumber(current) >= offno) {
|
||||
_bt_step(scan, &buf, BackwardScanDirection);
|
||||
so->btso_curbuf = buf;
|
||||
}
|
||||
|
||||
current = &(scan->currentMarkData);
|
||||
if (ItemPointerIsValid(current)
|
||||
&& ItemPointerGetBlockNumber(current) == blkno
|
||||
&& ItemPointerGetOffsetNumber(current) >= offno) {
|
||||
ItemPointerData tmp;
|
||||
tmp = *current;
|
||||
*current = scan->currentItemData;
|
||||
scan->currentItemData = tmp;
|
||||
_bt_step(scan, &buf, BackwardScanDirection);
|
||||
so->btso_mrkbuf = buf;
|
||||
tmp = *current;
|
||||
*current = scan->currentItemData;
|
||||
scan->currentItemData = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
_bt_scantouched(IndexScanDesc scan, BlockNumber blkno, OffsetNumber offno)
|
||||
{
|
||||
ItemPointer current;
|
||||
|
||||
current = &(scan->currentItemData);
|
||||
if (ItemPointerIsValid(current)
|
||||
&& ItemPointerGetBlockNumber(current) == blkno
|
||||
&& ItemPointerGetOffsetNumber(current) >= offno)
|
||||
return (true);
|
||||
|
||||
current = &(scan->currentMarkData);
|
||||
if (ItemPointerIsValid(current)
|
||||
&& ItemPointerGetBlockNumber(current) == blkno
|
||||
&& ItemPointerGetOffsetNumber(current) >= offno)
|
||||
return (true);
|
||||
|
||||
return (false);
|
||||
}
|
Reference in New Issue
Block a user