mirror of
https://github.com/postgres/postgres.git
synced 2025-07-18 17:42:25 +03:00
pgindent run.
This commit is contained in:
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.84 2003/07/21 20:29:37 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.85 2003/08/04 00:43:11 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* The old interface functions have been converted to macros
|
||||
@ -617,7 +617,7 @@ heap_formtuple(TupleDesc tupleDescriptor,
|
||||
td->t_natts = numberOfAttributes;
|
||||
td->t_hoff = hoff;
|
||||
|
||||
if (tupleDescriptor->tdhasoid) /* else leave infomask = 0 */
|
||||
if (tupleDescriptor->tdhasoid) /* else leave infomask = 0 */
|
||||
td->t_infomask = HEAP_HASOID;
|
||||
|
||||
DataFill((char *) td + hoff,
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.65 2003/07/21 20:29:37 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.66 2003/08/04 00:43:11 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -162,9 +162,9 @@ index_formtuple(TupleDesc tupleDescriptor,
|
||||
if ((size & INDEX_SIZE_MASK) != size)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||
errmsg("index tuple requires %lu bytes, maximum size is %lu",
|
||||
(unsigned long) size,
|
||||
(unsigned long) INDEX_SIZE_MASK)));
|
||||
errmsg("index tuple requires %lu bytes, maximum size is %lu",
|
||||
(unsigned long) size,
|
||||
(unsigned long) INDEX_SIZE_MASK)));
|
||||
|
||||
infomask |= size;
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.75 2003/07/21 20:29:38 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.76 2003/08/04 00:43:12 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -24,13 +24,13 @@
|
||||
|
||||
|
||||
static void printtup_startup(DestReceiver *self, int operation,
|
||||
TupleDesc typeinfo);
|
||||
TupleDesc typeinfo);
|
||||
static void printtup(HeapTuple tuple, TupleDesc typeinfo,
|
||||
DestReceiver *self);
|
||||
DestReceiver *self);
|
||||
static void printtup_20(HeapTuple tuple, TupleDesc typeinfo,
|
||||
DestReceiver *self);
|
||||
DestReceiver *self);
|
||||
static void printtup_internal_20(HeapTuple tuple, TupleDesc typeinfo,
|
||||
DestReceiver *self);
|
||||
DestReceiver *self);
|
||||
static void printtup_shutdown(DestReceiver *self);
|
||||
static void printtup_destroy(DestReceiver *self);
|
||||
|
||||
@ -81,8 +81,8 @@ printtup_create_DR(CommandDest dest, Portal portal)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* In protocol 2.0 the Bind message does not exist, so there is
|
||||
* no way for the columns to have different print formats; it's
|
||||
* In protocol 2.0 the Bind message does not exist, so there is no
|
||||
* way for the columns to have different print formats; it's
|
||||
* sufficient to look at the first one.
|
||||
*/
|
||||
if (portal->formats && portal->formats[0] != 0)
|
||||
@ -111,12 +111,13 @@ static void
|
||||
printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
|
||||
{
|
||||
DR_printtup *myState = (DR_printtup *) self;
|
||||
Portal portal = myState->portal;
|
||||
Portal portal = myState->portal;
|
||||
|
||||
if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
|
||||
{
|
||||
/*
|
||||
* Send portal name to frontend (obsolete cruft, gone in proto 3.0)
|
||||
* Send portal name to frontend (obsolete cruft, gone in proto
|
||||
* 3.0)
|
||||
*
|
||||
* If portal name not specified, use "blank" portal.
|
||||
*/
|
||||
@ -129,8 +130,8 @@ printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is a retrieve, and we are supposed to emit row descriptions,
|
||||
* then we send back the tuple descriptor of the tuples.
|
||||
* If this is a retrieve, and we are supposed to emit row
|
||||
* descriptions, then we send back the tuple descriptor of the tuples.
|
||||
*/
|
||||
if (operation == CMD_SELECT && myState->sendDescrip)
|
||||
{
|
||||
@ -163,7 +164,7 @@ printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
|
||||
* or some similar function; it does not contain a full set of fields.
|
||||
* The targetlist will be NIL when executing a utility function that does
|
||||
* not have a plan. If the targetlist isn't NIL then it is a Query node's
|
||||
* targetlist; it is up to us to ignore resjunk columns in it. The formats[]
|
||||
* targetlist; it is up to us to ignore resjunk columns in it. The formats[]
|
||||
* array pointer might be NULL (if we are doing Describe on a prepared stmt);
|
||||
* send zeroes for the format codes in that case.
|
||||
*/
|
||||
@ -176,14 +177,14 @@ SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist, int16 *formats)
|
||||
int i;
|
||||
StringInfoData buf;
|
||||
|
||||
pq_beginmessage(&buf, 'T'); /* tuple descriptor message type */
|
||||
pq_sendint(&buf, natts, 2); /* # of attrs in tuples */
|
||||
pq_beginmessage(&buf, 'T'); /* tuple descriptor message type */
|
||||
pq_sendint(&buf, natts, 2); /* # of attrs in tuples */
|
||||
|
||||
for (i = 0; i < natts; ++i)
|
||||
{
|
||||
Oid atttypid = attrs[i]->atttypid;
|
||||
int32 atttypmod = attrs[i]->atttypmod;
|
||||
Oid basetype;
|
||||
Oid atttypid = attrs[i]->atttypid;
|
||||
int32 atttypmod = attrs[i]->atttypmod;
|
||||
Oid basetype;
|
||||
|
||||
pq_sendstring(&buf, NameStr(attrs[i]->attname));
|
||||
/* column ID info appears in protocol 3.0 and up */
|
||||
@ -320,8 +321,8 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have a toasted datum, forcibly detoast it here to
|
||||
* avoid memory leakage inside the type's output routine.
|
||||
* If we have a toasted datum, forcibly detoast it here to avoid
|
||||
* memory leakage inside the type's output routine.
|
||||
*/
|
||||
if (thisState->typisvarlena)
|
||||
attr = PointerGetDatum(PG_DETOAST_DATUM(origattr));
|
||||
@ -347,7 +348,7 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
|
||||
|
||||
outputbytes = DatumGetByteaP(FunctionCall2(&thisState->finfo,
|
||||
attr,
|
||||
ObjectIdGetDatum(thisState->typelem)));
|
||||
ObjectIdGetDatum(thisState->typelem)));
|
||||
/* We assume the result will not have been toasted */
|
||||
pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4);
|
||||
pq_sendbytes(&buf, VARDATA(outputbytes),
|
||||
@ -424,8 +425,8 @@ printtup_20(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
|
||||
Assert(thisState->format == 0);
|
||||
|
||||
/*
|
||||
* If we have a toasted datum, forcibly detoast it here to
|
||||
* avoid memory leakage inside the type's output routine.
|
||||
* If we have a toasted datum, forcibly detoast it here to avoid
|
||||
* memory leakage inside the type's output routine.
|
||||
*/
|
||||
if (thisState->typisvarlena)
|
||||
attr = PointerGetDatum(PG_DETOAST_DATUM(origattr));
|
||||
@ -536,9 +537,10 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
|
||||
continue;
|
||||
getTypeOutputInfo(typeinfo->attrs[i]->atttypid,
|
||||
&typoutput, &typelem, &typisvarlena);
|
||||
|
||||
/*
|
||||
* If we have a toasted datum, forcibly detoast it here to
|
||||
* avoid memory leakage inside the type's output routine.
|
||||
* If we have a toasted datum, forcibly detoast it here to avoid
|
||||
* memory leakage inside the type's output routine.
|
||||
*/
|
||||
if (typisvarlena)
|
||||
attr = PointerGetDatum(PG_DETOAST_DATUM(origattr));
|
||||
@ -547,7 +549,7 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
|
||||
|
||||
value = DatumGetCString(OidFunctionCall3(typoutput,
|
||||
attr,
|
||||
ObjectIdGetDatum(typelem),
|
||||
ObjectIdGetDatum(typelem),
|
||||
Int32GetDatum(typeinfo->attrs[i]->atttypmod)));
|
||||
|
||||
printatt((unsigned) i + 1, typeinfo->attrs[i], value);
|
||||
@ -627,8 +629,8 @@ printtup_internal_20(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
|
||||
Assert(thisState->format == 1);
|
||||
|
||||
/*
|
||||
* If we have a toasted datum, forcibly detoast it here to
|
||||
* avoid memory leakage inside the type's output routine.
|
||||
* If we have a toasted datum, forcibly detoast it here to avoid
|
||||
* memory leakage inside the type's output routine.
|
||||
*/
|
||||
if (thisState->typisvarlena)
|
||||
attr = PointerGetDatum(PG_DETOAST_DATUM(origattr));
|
||||
@ -637,7 +639,7 @@ printtup_internal_20(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
|
||||
|
||||
outputbytes = DatumGetByteaP(FunctionCall2(&thisState->finfo,
|
||||
attr,
|
||||
ObjectIdGetDatum(thisState->typelem)));
|
||||
ObjectIdGetDatum(thisState->typelem)));
|
||||
/* We assume the result will not have been toasted */
|
||||
pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4);
|
||||
pq_sendbytes(&buf, VARDATA(outputbytes),
|
||||
|
@ -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.45 2003/07/28 00:09:14 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.46 2003/08/04 00:43:12 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -104,11 +104,12 @@ gistrescan(PG_FUNCTION_ARGS)
|
||||
memmove(s->keyData,
|
||||
key,
|
||||
s->numberOfKeys * sizeof(ScanKeyData));
|
||||
|
||||
/*
|
||||
* Play games here with the scan key to use the Consistent
|
||||
* function for all comparisons: 1) the sk_procedure field
|
||||
* will now be used to hold the strategy number 2) the
|
||||
* sk_func field will point to the Consistent function
|
||||
* function for all comparisons: 1) the sk_procedure field will
|
||||
* now be used to hold the strategy number 2) the sk_func field
|
||||
* will point to the Consistent function
|
||||
*/
|
||||
for (i = 0; i < s->numberOfKeys; i++)
|
||||
{
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/hash/hashfunc.c,v 1.36 2003/06/22 22:04:54 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/hash/hashfunc.c,v 1.37 2003/08/04 00:43:12 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* These functions are stored in pg_amproc. For each operator class
|
||||
@ -60,9 +60,9 @@ hashfloat4(PG_FUNCTION_ARGS)
|
||||
float4 key = PG_GETARG_FLOAT4(0);
|
||||
|
||||
/*
|
||||
* On IEEE-float machines, minus zero and zero have different bit patterns
|
||||
* but should compare as equal. We must ensure that they have the same
|
||||
* hash value, which is most easily done this way:
|
||||
* On IEEE-float machines, minus zero and zero have different bit
|
||||
* patterns but should compare as equal. We must ensure that they
|
||||
* have the same hash value, which is most easily done this way:
|
||||
*/
|
||||
if (key == (float4) 0)
|
||||
PG_RETURN_UINT32(0);
|
||||
@ -76,9 +76,9 @@ hashfloat8(PG_FUNCTION_ARGS)
|
||||
float8 key = PG_GETARG_FLOAT8(0);
|
||||
|
||||
/*
|
||||
* On IEEE-float machines, minus zero and zero have different bit patterns
|
||||
* but should compare as equal. We must ensure that they have the same
|
||||
* hash value, which is most easily done this way:
|
||||
* On IEEE-float machines, minus zero and zero have different bit
|
||||
* patterns but should compare as equal. We must ensure that they
|
||||
* have the same hash value, which is most easily done this way:
|
||||
*/
|
||||
if (key == (float8) 0)
|
||||
PG_RETURN_UINT32(0);
|
||||
@ -121,9 +121,9 @@ hashtext(PG_FUNCTION_ARGS)
|
||||
Datum result;
|
||||
|
||||
/*
|
||||
* Note: this is currently identical in behavior to hashvarlena,
|
||||
* but it seems likely that we may need to do something different
|
||||
* in non-C locales. (See also hashbpchar, if so.)
|
||||
* Note: this is currently identical in behavior to hashvarlena, but
|
||||
* it seems likely that we may need to do something different in non-C
|
||||
* locales. (See also hashbpchar, if so.)
|
||||
*/
|
||||
result = hash_any((unsigned char *) VARDATA(key),
|
||||
VARSIZE(key) - VARHDRSZ);
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/hash/hashovfl.c,v 1.35 2003/07/21 20:29:38 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/hash/hashovfl.c,v 1.36 2003/08/04 00:43:12 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Overflow pages look like ordinary relation pages.
|
||||
@ -205,8 +205,8 @@ _hash_getovfladdr(Relation rel, Buffer *metabufp)
|
||||
if (++splitnum >= NCACHED)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||
errmsg("out of overflow pages in hash index \"%s\"",
|
||||
RelationGetRelationName(rel))));
|
||||
errmsg("out of overflow pages in hash index \"%s\"",
|
||||
RelationGetRelationName(rel))));
|
||||
metap->hashm_ovflpoint = splitnum;
|
||||
metap->hashm_spares[splitnum] = metap->hashm_spares[splitnum - 1];
|
||||
metap->hashm_spares[splitnum - 1]--;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.152 2003/07/21 20:29:38 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.153 2003/08/04 00:43:14 momjian Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@ -1132,6 +1132,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid)
|
||||
xlhdr.t_natts = tup->t_data->t_natts;
|
||||
xlhdr.t_infomask = tup->t_data->t_infomask;
|
||||
xlhdr.t_hoff = tup->t_data->t_hoff;
|
||||
|
||||
/*
|
||||
* note we mark rdata[1] as belonging to buffer; if XLogInsert
|
||||
* decides to write the whole page to the xlog, we don't need to
|
||||
@ -1149,9 +1150,9 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid)
|
||||
rdata[2].next = NULL;
|
||||
|
||||
/*
|
||||
* If this is the single and first tuple on page, we can reinit the
|
||||
* page instead of restoring the whole thing. Set flag, and hide
|
||||
* buffer references from XLogInsert.
|
||||
* If this is the single and first tuple on page, we can reinit
|
||||
* the page instead of restoring the whole thing. Set flag, and
|
||||
* hide buffer references from XLogInsert.
|
||||
*/
|
||||
if (ItemPointerGetOffsetNumber(&(tup->t_self)) == FirstOffsetNumber &&
|
||||
PageGetMaxOffsetNumber(page) == FirstOffsetNumber)
|
||||
@ -1912,7 +1913,7 @@ log_heap_clean(Relation reln, Buffer buffer, OffsetNumber *unused, int uncnt)
|
||||
|
||||
/*
|
||||
* The unused-offsets array is not actually in the buffer, but pretend
|
||||
* that it is. When XLogInsert stores the whole buffer, the offsets
|
||||
* that it is. When XLogInsert stores the whole buffer, the offsets
|
||||
* array need not be stored too.
|
||||
*/
|
||||
rdata[1].buffer = buffer;
|
||||
@ -1991,9 +1992,10 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from,
|
||||
2 * sizeof(TransactionId));
|
||||
hsize += 2 * sizeof(TransactionId);
|
||||
}
|
||||
|
||||
/*
|
||||
* As with insert records, we need not store the rdata[2] segment
|
||||
* if we decide to store the whole buffer instead.
|
||||
* As with insert records, we need not store the rdata[2] segment if
|
||||
* we decide to store the whole buffer instead.
|
||||
*/
|
||||
rdata[2].buffer = newbuf;
|
||||
rdata[2].data = (char *) &xlhdr;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.67 2003/07/21 20:29:39 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.68 2003/08/04 00:43:15 momjian Exp $
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
* index_open - open an index relation by relation OID
|
||||
@ -300,7 +300,7 @@ index_beginscan(Relation heapRelation,
|
||||
* index_rescan - (re)start a scan of an index
|
||||
*
|
||||
* The caller may specify a new set of scankeys (but the number of keys
|
||||
* cannot change). To restart the scan without changing keys, pass NULL
|
||||
* cannot change). To restart the scan without changing keys, pass NULL
|
||||
* for the key array.
|
||||
*
|
||||
* Note that this is also called when first starting an indexscan;
|
||||
@ -394,8 +394,8 @@ index_restrpos(IndexScanDesc scan)
|
||||
|
||||
/*
|
||||
* We do not reset got_tuple; so if the scan is actually being
|
||||
* short-circuited by index_getnext, the effective position restoration
|
||||
* is done by restoring unique_tuple_pos.
|
||||
* short-circuited by index_getnext, the effective position
|
||||
* restoration is done by restoring unique_tuple_pos.
|
||||
*/
|
||||
scan->unique_tuple_pos = scan->unique_tuple_mark;
|
||||
|
||||
@ -427,24 +427,24 @@ index_getnext(IndexScanDesc scan, ScanDirection direction)
|
||||
}
|
||||
|
||||
/*
|
||||
* If we already got a tuple and it must be unique, there's no need
|
||||
* to make the index AM look through any additional tuples. (This can
|
||||
* If we already got a tuple and it must be unique, there's no need to
|
||||
* make the index AM look through any additional tuples. (This can
|
||||
* save a useful amount of work in scenarios where there are many dead
|
||||
* tuples due to heavy update activity.)
|
||||
*
|
||||
* To do this we must keep track of the logical scan position
|
||||
* (before/on/after tuple). Also, we have to be sure to release scan
|
||||
* resources before returning NULL; if we fail to do so then a multi-index
|
||||
* scan can easily run the system out of free buffers. We can release
|
||||
* index-level resources fairly cheaply by calling index_rescan. This
|
||||
* means there are two persistent states as far as the index AM is
|
||||
* concerned: on-tuple and rescanned. If we are actually asked to
|
||||
* re-fetch the single tuple, we have to go through a fresh indexscan
|
||||
* startup, which penalizes that (infrequent) case.
|
||||
* resources before returning NULL; if we fail to do so then a
|
||||
* multi-index scan can easily run the system out of free buffers. We
|
||||
* can release index-level resources fairly cheaply by calling
|
||||
* index_rescan. This means there are two persistent states as far as
|
||||
* the index AM is concerned: on-tuple and rescanned. If we are
|
||||
* actually asked to re-fetch the single tuple, we have to go through
|
||||
* a fresh indexscan startup, which penalizes that (infrequent) case.
|
||||
*/
|
||||
if (scan->keys_are_unique && scan->got_tuple)
|
||||
{
|
||||
int new_tuple_pos = scan->unique_tuple_pos;
|
||||
int new_tuple_pos = scan->unique_tuple_pos;
|
||||
|
||||
if (ScanDirectionIsForward(direction))
|
||||
{
|
||||
@ -459,22 +459,23 @@ index_getnext(IndexScanDesc scan, ScanDirection direction)
|
||||
if (new_tuple_pos == 0)
|
||||
{
|
||||
/*
|
||||
* We are moving onto the unique tuple from having been off it.
|
||||
* We just fall through and let the index AM do the work. Note
|
||||
* we should get the right answer regardless of scan direction.
|
||||
* We are moving onto the unique tuple from having been off
|
||||
* it. We just fall through and let the index AM do the work.
|
||||
* Note we should get the right answer regardless of scan
|
||||
* direction.
|
||||
*/
|
||||
scan->unique_tuple_pos = 0; /* need to update position */
|
||||
scan->unique_tuple_pos = 0; /* need to update position */
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Moving off the tuple; must do amrescan to release index-level
|
||||
* pins before we return NULL. Since index_rescan will reset
|
||||
* my state, must save and restore...
|
||||
* Moving off the tuple; must do amrescan to release
|
||||
* index-level pins before we return NULL. Since index_rescan
|
||||
* will reset my state, must save and restore...
|
||||
*/
|
||||
int unique_tuple_mark = scan->unique_tuple_mark;
|
||||
int unique_tuple_mark = scan->unique_tuple_mark;
|
||||
|
||||
index_rescan(scan, NULL /* no change to key */);
|
||||
index_rescan(scan, NULL /* no change to key */ );
|
||||
|
||||
scan->keys_are_unique = true;
|
||||
scan->got_tuple = true;
|
||||
@ -631,7 +632,7 @@ index_bulk_delete(Relation indexRelation,
|
||||
*/
|
||||
IndexBulkDeleteResult *
|
||||
index_vacuum_cleanup(Relation indexRelation,
|
||||
IndexVacuumCleanupInfo *info,
|
||||
IndexVacuumCleanupInfo * info,
|
||||
IndexBulkDeleteResult *stats)
|
||||
{
|
||||
RegProcedure procedure;
|
||||
@ -649,7 +650,7 @@ index_vacuum_cleanup(Relation indexRelation,
|
||||
DatumGetPointer(OidFunctionCall3(procedure,
|
||||
PointerGetDatum(indexRelation),
|
||||
PointerGetDatum((Pointer) info),
|
||||
PointerGetDatum((Pointer) stats)));
|
||||
PointerGetDatum((Pointer) stats)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.102 2003/07/28 00:09:14 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.103 2003/08/04 00:43:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -432,9 +432,9 @@ _bt_insertonpg(Relation rel,
|
||||
*
|
||||
* must write-lock that page before releasing write lock on
|
||||
* current page; else someone else's _bt_check_unique scan
|
||||
* could fail to see our insertion. write locks on intermediate
|
||||
* dead pages won't do because we don't know when they will get
|
||||
* de-linked from the tree.
|
||||
* could fail to see our insertion. write locks on
|
||||
* intermediate dead pages won't do because we don't know when
|
||||
* they will get de-linked from the tree.
|
||||
*/
|
||||
Buffer rbuf = InvalidBuffer;
|
||||
|
||||
@ -523,9 +523,10 @@ _bt_insertonpg(Relation rel,
|
||||
/*
|
||||
* If we are doing this insert because we split a page that was
|
||||
* the only one on its tree level, but was not the root, it may
|
||||
* have been the "fast root". We need to ensure that the fast root
|
||||
* link points at or above the current page. We can safely acquire
|
||||
* a lock on the metapage here --- see comments for _bt_newroot().
|
||||
* have been the "fast root". We need to ensure that the fast
|
||||
* root link points at or above the current page. We can safely
|
||||
* acquire a lock on the metapage here --- see comments for
|
||||
* _bt_newroot().
|
||||
*/
|
||||
if (split_only_page)
|
||||
{
|
||||
@ -1135,7 +1136,7 @@ _bt_checksplitloc(FindSplitData *state, OffsetNumber firstright,
|
||||
*
|
||||
* On entry, buf and rbuf are the left and right split pages, which we
|
||||
* still hold write locks on per the L&Y algorithm. We release the
|
||||
* write locks once we have write lock on the parent page. (Any sooner,
|
||||
* write locks once we have write lock on the parent page. (Any sooner,
|
||||
* and it'd be possible for some other process to try to split or delete
|
||||
* one of these pages, and get confused because it cannot find the downlink.)
|
||||
*
|
||||
@ -1155,19 +1156,19 @@ _bt_insert_parent(Relation rel,
|
||||
bool is_only)
|
||||
{
|
||||
/*
|
||||
* Here we have to do something Lehman and Yao don't talk about:
|
||||
* deal with a root split and construction of a new root. If our
|
||||
* stack is empty then we have just split a node on what had been
|
||||
* the root level when we descended the tree. If it was still the
|
||||
* root then we perform a new-root construction. If it *wasn't*
|
||||
* the root anymore, search to find the next higher level that
|
||||
* someone constructed meanwhile, and find the right place to insert
|
||||
* as for the normal case.
|
||||
* Here we have to do something Lehman and Yao don't talk about: deal
|
||||
* with a root split and construction of a new root. If our stack is
|
||||
* empty then we have just split a node on what had been the root
|
||||
* level when we descended the tree. If it was still the root then we
|
||||
* perform a new-root construction. If it *wasn't* the root anymore,
|
||||
* search to find the next higher level that someone constructed
|
||||
* meanwhile, and find the right place to insert as for the normal
|
||||
* case.
|
||||
*
|
||||
* If we have to search for the parent level, we do so by
|
||||
* re-descending from the root. This is not super-efficient,
|
||||
* but it's rare enough not to matter. (This path is also taken
|
||||
* when called from WAL recovery --- we have no stack in that case.)
|
||||
* If we have to search for the parent level, we do so by re-descending
|
||||
* from the root. This is not super-efficient, but it's rare enough
|
||||
* not to matter. (This path is also taken when called from WAL
|
||||
* recovery --- we have no stack in that case.)
|
||||
*/
|
||||
if (is_root)
|
||||
{
|
||||
@ -1222,9 +1223,9 @@ _bt_insert_parent(Relation rel,
|
||||
/*
|
||||
* Find the parent buffer and get the parent page.
|
||||
*
|
||||
* Oops - if we were moved right then we need to change stack
|
||||
* item! We want to find parent pointing to where we are,
|
||||
* right ? - vadim 05/27/97
|
||||
* Oops - if we were moved right then we need to change stack item!
|
||||
* We want to find parent pointing to where we are, right ? -
|
||||
* vadim 05/27/97
|
||||
*/
|
||||
ItemPointerSet(&(stack->bts_btitem.bti_itup.t_tid),
|
||||
bknum, P_HIKEY);
|
||||
@ -1296,16 +1297,16 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access)
|
||||
|
||||
/*
|
||||
* start = InvalidOffsetNumber means "search the whole page".
|
||||
* We need this test anyway due to possibility that
|
||||
* page has a high key now when it didn't before.
|
||||
* We need this test anyway due to possibility that page has a
|
||||
* high key now when it didn't before.
|
||||
*/
|
||||
if (start < minoff)
|
||||
start = minoff;
|
||||
|
||||
/*
|
||||
* These loops will check every item on the page --- but in an
|
||||
* order that's attuned to the probability of where it actually
|
||||
* is. Scan to the right first, then to the left.
|
||||
* order that's attuned to the probability of where it
|
||||
* actually is. Scan to the right first, then to the left.
|
||||
*/
|
||||
for (offnum = start;
|
||||
offnum <= maxoff;
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.66 2003/07/21 20:29:39 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.67 2003/08/04 00:43:15 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Postgres btree pages look like ordinary relation pages. The opaque
|
||||
@ -181,8 +181,8 @@ _bt_getroot(Relation rel, int access)
|
||||
/*
|
||||
* Metadata initialized by someone else. In order to
|
||||
* guarantee no deadlocks, we have to release the metadata
|
||||
* page and start all over again. (Is that really true?
|
||||
* But it's hardly worth trying to optimize this case.)
|
||||
* page and start all over again. (Is that really true? But
|
||||
* it's hardly worth trying to optimize this case.)
|
||||
*/
|
||||
_bt_relbuf(rel, metabuf);
|
||||
return _bt_getroot(rel, access);
|
||||
@ -190,8 +190,8 @@ _bt_getroot(Relation rel, int access)
|
||||
|
||||
/*
|
||||
* Get, initialize, write, and leave a lock of the appropriate
|
||||
* type on the new root page. Since this is the first page in
|
||||
* the tree, it's a leaf as well as the root.
|
||||
* type on the new root page. Since this is the first page in the
|
||||
* tree, it's a leaf as well as the root.
|
||||
*/
|
||||
rootbuf = _bt_getbuf(rel, P_NEW, BT_WRITE);
|
||||
rootblkno = BufferGetBlockNumber(rootbuf);
|
||||
@ -240,7 +240,7 @@ _bt_getroot(Relation rel, int access)
|
||||
_bt_wrtnorelbuf(rel, rootbuf);
|
||||
|
||||
/*
|
||||
* swap root write lock for read lock. There is no danger of
|
||||
* swap root write lock for read lock. There is no danger of
|
||||
* anyone else accessing the new root page while it's unlocked,
|
||||
* since no one else knows where it is yet.
|
||||
*/
|
||||
@ -284,8 +284,8 @@ _bt_getroot(Relation rel, int access)
|
||||
}
|
||||
|
||||
/*
|
||||
* By here, we have a pin and read lock on the root page, and no
|
||||
* lock set on the metadata page. Return the root page's buffer.
|
||||
* By here, we have a pin and read lock on the root page, and no lock
|
||||
* set on the metadata page. Return the root page's buffer.
|
||||
*/
|
||||
return rootbuf;
|
||||
}
|
||||
@ -299,7 +299,7 @@ _bt_getroot(Relation rel, int access)
|
||||
* By the time we acquire lock on the root page, it might have been split and
|
||||
* not be the true root anymore. This is okay for the present uses of this
|
||||
* routine; we only really need to be able to move up at least one tree level
|
||||
* from whatever non-root page we were at. If we ever do need to lock the
|
||||
* from whatever non-root page we were at. If we ever do need to lock the
|
||||
* one true root page, we could loop here, re-reading the metapage on each
|
||||
* failure. (Note that it wouldn't do to hold the lock on the metapage while
|
||||
* moving to the root --- that'd deadlock against any concurrent root split.)
|
||||
@ -406,9 +406,9 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access)
|
||||
* First see if the FSM knows of any free pages.
|
||||
*
|
||||
* We can't trust the FSM's report unreservedly; we have to check
|
||||
* that the page is still free. (For example, an already-free page
|
||||
* could have been re-used between the time the last VACUUM scanned
|
||||
* it and the time the VACUUM made its FSM updates.)
|
||||
* that the page is still free. (For example, an already-free
|
||||
* page could have been re-used between the time the last VACUUM
|
||||
* scanned it and the time the VACUUM made its FSM updates.)
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
@ -431,10 +431,10 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access)
|
||||
/*
|
||||
* Extend the relation by one page.
|
||||
*
|
||||
* We have to use a lock to ensure no one else is extending the rel at
|
||||
* the same time, else we will both try to initialize the same new
|
||||
* page. We can skip locking for new or temp relations, however,
|
||||
* since no one else could be accessing them.
|
||||
* We have to use a lock to ensure no one else is extending the rel
|
||||
* at the same time, else we will both try to initialize the same
|
||||
* new page. We can skip locking for new or temp relations,
|
||||
* however, since no one else could be accessing them.
|
||||
*/
|
||||
needLock = !(rel->rd_isnew || rel->rd_istemp);
|
||||
|
||||
@ -444,8 +444,8 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access)
|
||||
buf = ReadBuffer(rel, P_NEW);
|
||||
|
||||
/*
|
||||
* Release the file-extension lock; it's now OK for someone else to
|
||||
* extend the relation some more.
|
||||
* Release the file-extension lock; it's now OK for someone else
|
||||
* to extend the relation some more.
|
||||
*/
|
||||
if (needLock)
|
||||
UnlockPage(rel, 0, ExclusiveLock);
|
||||
@ -484,7 +484,7 @@ _bt_relbuf(Relation rel, Buffer buf)
|
||||
* and a pin on the buffer.
|
||||
*
|
||||
* NOTE: actually, the buffer manager just marks the shared buffer page
|
||||
* dirty here; the real I/O happens later. This is okay since we are not
|
||||
* dirty here; the real I/O happens later. This is okay since we are not
|
||||
* relying on write ordering anyway. The WAL mechanism is responsible for
|
||||
* guaranteeing correctness after a crash.
|
||||
*/
|
||||
@ -534,13 +534,14 @@ _bt_page_recyclable(Page page)
|
||||
BTPageOpaque opaque;
|
||||
|
||||
/*
|
||||
* It's possible to find an all-zeroes page in an index --- for example,
|
||||
* a backend might successfully extend the relation one page and then
|
||||
* crash before it is able to make a WAL entry for adding the page.
|
||||
* If we find a zeroed page then reclaim it.
|
||||
* It's possible to find an all-zeroes page in an index --- for
|
||||
* example, a backend might successfully extend the relation one page
|
||||
* and then crash before it is able to make a WAL entry for adding the
|
||||
* page. If we find a zeroed page then reclaim it.
|
||||
*/
|
||||
if (PageIsNew(page))
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Otherwise, recycle if deleted and too old to have any processes
|
||||
* interested in it.
|
||||
@ -565,7 +566,7 @@ _bt_page_recyclable(Page page)
|
||||
* mistake. On exit, metapage data is correct and we no longer have
|
||||
* a pin or lock on the metapage.
|
||||
*
|
||||
* Actually this is not used for splitting on-the-fly anymore. It's only used
|
||||
* Actually this is not used for splitting on-the-fly anymore. It's only used
|
||||
* in nbtsort.c at the completion of btree building, where we know we have
|
||||
* sole access to the index anyway.
|
||||
*/
|
||||
@ -623,7 +624,7 @@ _bt_metaproot(Relation rel, BlockNumber rootbknum, uint32 level)
|
||||
/*
|
||||
* Delete item(s) from a btree page.
|
||||
*
|
||||
* This must only be used for deleting leaf items. Deleting an item on a
|
||||
* This must only be used for deleting leaf items. Deleting an item on a
|
||||
* non-leaf page has to be done as part of an atomic action that includes
|
||||
* deleting the page it points to.
|
||||
*
|
||||
@ -646,9 +647,7 @@ _bt_delitems(Relation rel, Buffer buf,
|
||||
* adjusting item numbers for previous deletions.
|
||||
*/
|
||||
for (i = nitems - 1; i >= 0; i--)
|
||||
{
|
||||
PageIndexTupleDelete(page, itemnos[i]);
|
||||
}
|
||||
|
||||
/* XLOG stuff */
|
||||
if (!rel->rd_istemp)
|
||||
@ -666,8 +665,8 @@ _bt_delitems(Relation rel, Buffer buf,
|
||||
rdata[0].next = &(rdata[1]);
|
||||
|
||||
/*
|
||||
* The target-offsets array is not in the buffer, but pretend
|
||||
* that it is. When XLogInsert stores the whole buffer, the offsets
|
||||
* The target-offsets array is not in the buffer, but pretend that
|
||||
* it is. When XLogInsert stores the whole buffer, the offsets
|
||||
* array need not be stored too.
|
||||
*/
|
||||
rdata[1].buffer = buf;
|
||||
@ -701,7 +700,7 @@ _bt_delitems(Relation rel, Buffer buf,
|
||||
* may currently be trying to follow links leading to the page; they have to
|
||||
* be allowed to use its right-link to recover. See nbtree/README.
|
||||
*
|
||||
* On entry, the target buffer must be pinned and read-locked. This lock and
|
||||
* On entry, the target buffer must be pinned and read-locked. This lock and
|
||||
* pin will be dropped before exiting.
|
||||
*
|
||||
* Returns the number of pages successfully deleted (zero on failure; could
|
||||
@ -714,7 +713,7 @@ _bt_delitems(Relation rel, Buffer buf,
|
||||
int
|
||||
_bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
|
||||
{
|
||||
BlockNumber target,
|
||||
BlockNumber target,
|
||||
leftsib,
|
||||
rightsib,
|
||||
parent;
|
||||
@ -740,17 +739,18 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
|
||||
BTPageOpaque opaque;
|
||||
|
||||
/*
|
||||
* We can never delete rightmost pages nor root pages. While at it,
|
||||
* We can never delete rightmost pages nor root pages. While at it,
|
||||
* check that page is not already deleted and is empty.
|
||||
*/
|
||||
page = BufferGetPage(buf);
|
||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
if (P_RIGHTMOST(opaque) || P_ISROOT(opaque) || P_ISDELETED(opaque) ||
|
||||
P_FIRSTDATAKEY(opaque) <= PageGetMaxOffsetNumber(page))
|
||||
P_FIRSTDATAKEY(opaque) <= PageGetMaxOffsetNumber(page))
|
||||
{
|
||||
_bt_relbuf(rel, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save info about page, including a copy of its high key (it must
|
||||
* have one, being non-rightmost).
|
||||
@ -760,12 +760,13 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
|
||||
leftsib = opaque->btpo_prev;
|
||||
itemid = PageGetItemId(page, P_HIKEY);
|
||||
targetkey = CopyBTItem((BTItem) PageGetItem(page, itemid));
|
||||
|
||||
/*
|
||||
* We need to get an approximate pointer to the page's parent page.
|
||||
* Use the standard search mechanism to search for the page's high key;
|
||||
* this will give us a link to either the current parent or someplace
|
||||
* to its left (if there are multiple equal high keys). To avoid
|
||||
* deadlocks, we'd better drop the target page lock first.
|
||||
* Use the standard search mechanism to search for the page's high
|
||||
* key; this will give us a link to either the current parent or
|
||||
* someplace to its left (if there are multiple equal high keys). To
|
||||
* avoid deadlocks, we'd better drop the target page lock first.
|
||||
*/
|
||||
_bt_relbuf(rel, buf);
|
||||
/* we need a scan key to do our search, so build one */
|
||||
@ -775,9 +776,11 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
|
||||
&lbuf, BT_READ);
|
||||
/* don't need a pin on that either */
|
||||
_bt_relbuf(rel, lbuf);
|
||||
|
||||
/*
|
||||
* If we are trying to delete an interior page, _bt_search did more
|
||||
* than we needed. Locate the stack item pointing to our parent level.
|
||||
* than we needed. Locate the stack item pointing to our parent
|
||||
* level.
|
||||
*/
|
||||
ilevel = 0;
|
||||
for (;;)
|
||||
@ -789,10 +792,12 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
|
||||
stack = stack->bts_parent;
|
||||
ilevel++;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have to lock the pages we need to modify in the standard order:
|
||||
* moving right, then up. Else we will deadlock against other writers.
|
||||
*
|
||||
* moving right, then up. Else we will deadlock against other
|
||||
* writers.
|
||||
*
|
||||
* So, we need to find and write-lock the current left sibling of the
|
||||
* target page. The sibling that was current a moment ago could have
|
||||
* split, so we may have to move right. This search could fail if
|
||||
@ -823,21 +828,24 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
|
||||
}
|
||||
else
|
||||
lbuf = InvalidBuffer;
|
||||
|
||||
/*
|
||||
* Next write-lock the target page itself. It should be okay to take just
|
||||
* a write lock not a superexclusive lock, since no scans would stop on an
|
||||
* empty page.
|
||||
* Next write-lock the target page itself. It should be okay to take
|
||||
* just a write lock not a superexclusive lock, since no scans would
|
||||
* stop on an empty page.
|
||||
*/
|
||||
buf = _bt_getbuf(rel, target, BT_WRITE);
|
||||
page = BufferGetPage(buf);
|
||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
|
||||
/*
|
||||
* Check page is still empty etc, else abandon deletion. The empty check
|
||||
* is necessary since someone else might have inserted into it while
|
||||
* we didn't have it locked; the others are just for paranoia's sake.
|
||||
* Check page is still empty etc, else abandon deletion. The empty
|
||||
* check is necessary since someone else might have inserted into it
|
||||
* while we didn't have it locked; the others are just for paranoia's
|
||||
* sake.
|
||||
*/
|
||||
if (P_RIGHTMOST(opaque) || P_ISROOT(opaque) || P_ISDELETED(opaque) ||
|
||||
P_FIRSTDATAKEY(opaque) <= PageGetMaxOffsetNumber(page))
|
||||
P_FIRSTDATAKEY(opaque) <= PageGetMaxOffsetNumber(page))
|
||||
{
|
||||
_bt_relbuf(rel, buf);
|
||||
if (BufferIsValid(lbuf))
|
||||
@ -846,14 +854,17 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
|
||||
}
|
||||
if (opaque->btpo_prev != leftsib)
|
||||
elog(ERROR, "left link changed unexpectedly");
|
||||
|
||||
/*
|
||||
* And next write-lock the (current) right sibling.
|
||||
*/
|
||||
rightsib = opaque->btpo_next;
|
||||
rbuf = _bt_getbuf(rel, rightsib, BT_WRITE);
|
||||
|
||||
/*
|
||||
* Next find and write-lock the current parent of the target page.
|
||||
* This is essentially the same as the corresponding step of splitting.
|
||||
* This is essentially the same as the corresponding step of
|
||||
* splitting.
|
||||
*/
|
||||
ItemPointerSet(&(stack->bts_btitem.bti_itup.t_tid),
|
||||
target, P_HIKEY);
|
||||
@ -863,10 +874,11 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
|
||||
RelationGetRelationName(rel));
|
||||
parent = stack->bts_blkno;
|
||||
poffset = stack->bts_offset;
|
||||
|
||||
/*
|
||||
* If the target is the rightmost child of its parent, then we can't
|
||||
* delete, unless it's also the only child --- in which case the parent
|
||||
* changes to half-dead status.
|
||||
* delete, unless it's also the only child --- in which case the
|
||||
* parent changes to half-dead status.
|
||||
*/
|
||||
page = BufferGetPage(pbuf);
|
||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
@ -893,12 +905,13 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
|
||||
if (OffsetNumberNext(P_FIRSTDATAKEY(opaque)) == maxoff)
|
||||
parent_one_child = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are deleting the next-to-last page on the target's level,
|
||||
* then the rightsib is a candidate to become the new fast root.
|
||||
* (In theory, it might be possible to push the fast root even further
|
||||
* down, but the odds of doing so are slim, and the locking considerations
|
||||
* daunting.)
|
||||
* then the rightsib is a candidate to become the new fast root. (In
|
||||
* theory, it might be possible to push the fast root even further
|
||||
* down, but the odds of doing so are slim, and the locking
|
||||
* considerations daunting.)
|
||||
*
|
||||
* We can safely acquire a lock on the metapage here --- see comments for
|
||||
* _bt_newroot().
|
||||
@ -914,12 +927,13 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
|
||||
metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_WRITE);
|
||||
metapg = BufferGetPage(metabuf);
|
||||
metad = BTPageGetMeta(metapg);
|
||||
|
||||
/*
|
||||
* The expected case here is btm_fastlevel == targetlevel+1;
|
||||
* if the fastlevel is <= targetlevel, something is wrong, and we
|
||||
* choose to overwrite it to fix it.
|
||||
* if the fastlevel is <= targetlevel, something is wrong, and
|
||||
* we choose to overwrite it to fix it.
|
||||
*/
|
||||
if (metad->btm_fastlevel > targetlevel+1)
|
||||
if (metad->btm_fastlevel > targetlevel + 1)
|
||||
{
|
||||
/* no update wanted */
|
||||
_bt_relbuf(rel, metabuf);
|
||||
@ -937,9 +951,9 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
|
||||
|
||||
/*
|
||||
* Update parent. The normal case is a tad tricky because we want to
|
||||
* delete the target's downlink and the *following* key. Easiest way is
|
||||
* to copy the right sibling's downlink over the target downlink, and then
|
||||
* delete the following item.
|
||||
* delete the target's downlink and the *following* key. Easiest way
|
||||
* is to copy the right sibling's downlink over the target downlink,
|
||||
* and then delete the following item.
|
||||
*/
|
||||
page = BufferGetPage(pbuf);
|
||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
@ -950,7 +964,7 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
|
||||
}
|
||||
else
|
||||
{
|
||||
OffsetNumber nextoffset;
|
||||
OffsetNumber nextoffset;
|
||||
|
||||
itemid = PageGetItemId(page, poffset);
|
||||
btitem = (BTItem) PageGetItem(page, itemid);
|
||||
@ -968,8 +982,8 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
|
||||
}
|
||||
|
||||
/*
|
||||
* Update siblings' side-links. Note the target page's side-links will
|
||||
* continue to point to the siblings.
|
||||
* Update siblings' side-links. Note the target page's side-links
|
||||
* will continue to point to the siblings.
|
||||
*/
|
||||
if (BufferIsValid(lbuf))
|
||||
{
|
||||
@ -1096,10 +1110,11 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
|
||||
_bt_wrtbuf(rel, lbuf);
|
||||
|
||||
/*
|
||||
* If parent became half dead, recurse to try to delete it. Otherwise,
|
||||
* if right sibling is empty and is now the last child of the parent,
|
||||
* recurse to try to delete it. (These cases cannot apply at the same
|
||||
* time, though the second case might itself recurse to the first.)
|
||||
* If parent became half dead, recurse to try to delete it.
|
||||
* Otherwise, if right sibling is empty and is now the last child of
|
||||
* the parent, recurse to try to delete it. (These cases cannot apply
|
||||
* at the same time, though the second case might itself recurse to
|
||||
* the first.)
|
||||
*/
|
||||
if (parent_half_dead)
|
||||
{
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.103 2003/07/21 20:29:39 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.104 2003/08/04 00:43:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -580,19 +580,20 @@ btbulkdelete(PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* The outer loop iterates over index leaf pages, the inner over items
|
||||
* on a leaf page. We issue just one _bt_delitems() call per page,
|
||||
* so as to minimize WAL traffic.
|
||||
* on a leaf page. We issue just one _bt_delitems() call per page, so
|
||||
* as to minimize WAL traffic.
|
||||
*
|
||||
* Note that we exclusive-lock every leaf page containing data items,
|
||||
* in sequence left to right. It sounds attractive to only exclusive-lock
|
||||
* those containing items we need to delete, but unfortunately that
|
||||
* is not safe: we could then pass a stopped indexscan, which could
|
||||
* in rare cases lead to deleting the item it needs to find when it
|
||||
* resumes. (See _bt_restscan --- this could only happen if an indexscan
|
||||
* stops on a deletable item and then a page split moves that item
|
||||
* into a page further to its right, which the indexscan will have no
|
||||
* pin on.) We can skip obtaining exclusive lock on empty pages
|
||||
* though, since no indexscan could be stopped on those.
|
||||
* Note that we exclusive-lock every leaf page containing data items, in
|
||||
* sequence left to right. It sounds attractive to only
|
||||
* exclusive-lock those containing items we need to delete, but
|
||||
* unfortunately that is not safe: we could then pass a stopped
|
||||
* indexscan, which could in rare cases lead to deleting the item it
|
||||
* needs to find when it resumes. (See _bt_restscan --- this could
|
||||
* only happen if an indexscan stops on a deletable item and then a
|
||||
* page split moves that item into a page further to its right, which
|
||||
* the indexscan will have no pin on.) We can skip obtaining
|
||||
* exclusive lock on empty pages though, since no indexscan could be
|
||||
* stopped on those.
|
||||
*/
|
||||
buf = _bt_get_endpoint(rel, 0, false);
|
||||
if (BufferIsValid(buf)) /* check for empty index */
|
||||
@ -604,7 +605,7 @@ btbulkdelete(PG_FUNCTION_ARGS)
|
||||
OffsetNumber offnum,
|
||||
minoff,
|
||||
maxoff;
|
||||
BlockNumber nextpage;
|
||||
BlockNumber nextpage;
|
||||
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
|
||||
@ -622,12 +623,14 @@ btbulkdelete(PG_FUNCTION_ARGS)
|
||||
*/
|
||||
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
|
||||
LockBufferForCleanup(buf);
|
||||
|
||||
/*
|
||||
* Recompute minoff/maxoff, both of which could have changed
|
||||
* while we weren't holding the lock.
|
||||
* Recompute minoff/maxoff, both of which could have
|
||||
* changed while we weren't holding the lock.
|
||||
*/
|
||||
minoff = P_FIRSTDATAKEY(opaque);
|
||||
maxoff = PageGetMaxOffsetNumber(page);
|
||||
|
||||
/*
|
||||
* Scan over all items to see which ones need deleted
|
||||
* according to the callback function.
|
||||
@ -640,7 +643,7 @@ btbulkdelete(PG_FUNCTION_ARGS)
|
||||
ItemPointer htup;
|
||||
|
||||
btitem = (BTItem) PageGetItem(page,
|
||||
PageGetItemId(page, offnum));
|
||||
PageGetItemId(page, offnum));
|
||||
htup = &(btitem->bti_itup.t_tid);
|
||||
if (callback(htup, callback_state))
|
||||
{
|
||||
@ -651,6 +654,7 @@ btbulkdelete(PG_FUNCTION_ARGS)
|
||||
num_index_tuples += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we need to delete anything, do it and write the buffer;
|
||||
* else just release the buffer.
|
||||
@ -662,9 +666,7 @@ btbulkdelete(PG_FUNCTION_ARGS)
|
||||
_bt_wrtbuf(rel, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
_bt_relbuf(rel, buf);
|
||||
}
|
||||
/* And advance to next page, if any */
|
||||
if (nextpage == P_NONE)
|
||||
break;
|
||||
@ -712,7 +714,7 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
|
||||
/* No point in remembering more than MaxFSMPages pages */
|
||||
maxFreePages = MaxFSMPages;
|
||||
if ((BlockNumber) maxFreePages > num_pages)
|
||||
maxFreePages = (int) num_pages + 1; /* +1 to avoid palloc(0) */
|
||||
maxFreePages = (int) num_pages + 1; /* +1 to avoid palloc(0) */
|
||||
freePages = (BlockNumber *) palloc(maxFreePages * sizeof(BlockNumber));
|
||||
nFreePages = 0;
|
||||
|
||||
@ -728,10 +730,10 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
|
||||
* after we start the scan will not be examined; this should be fine,
|
||||
* since they can't possibly be empty.)
|
||||
*/
|
||||
for (blkno = BTREE_METAPAGE+1; blkno < num_pages; blkno++)
|
||||
for (blkno = BTREE_METAPAGE + 1; blkno < num_pages; blkno++)
|
||||
{
|
||||
Buffer buf;
|
||||
Page page;
|
||||
Buffer buf;
|
||||
Page page;
|
||||
BTPageOpaque opaque;
|
||||
|
||||
buf = _bt_getbuf(rel, blkno, BT_READ);
|
||||
@ -753,7 +755,7 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
|
||||
P_FIRSTDATAKEY(opaque) > PageGetMaxOffsetNumber(page))
|
||||
{
|
||||
/* Empty, try to delete */
|
||||
int ndel;
|
||||
int ndel;
|
||||
|
||||
/* Run pagedel in a temp context to avoid memory leakage */
|
||||
MemoryContextReset(mycontext);
|
||||
@ -768,7 +770,7 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* During VACUUM FULL it's okay to recycle deleted pages
|
||||
* immediately, since there can be no other transactions
|
||||
* scanning the index. Note that we will only recycle the
|
||||
* scanning the index. Note that we will only recycle the
|
||||
* current page and not any parent pages that _bt_pagedel
|
||||
* might have recursed to; this seems reasonable in the name
|
||||
* of simplicity. (Trying to do otherwise would mean we'd
|
||||
@ -787,16 +789,16 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* During VACUUM FULL, we truncate off any recyclable pages at the
|
||||
* end of the index. In a normal vacuum it'd be unsafe to do this
|
||||
* except by acquiring exclusive lock on the index and then rechecking
|
||||
* all the pages; doesn't seem worth it.
|
||||
* During VACUUM FULL, we truncate off any recyclable pages at the end
|
||||
* of the index. In a normal vacuum it'd be unsafe to do this except
|
||||
* by acquiring exclusive lock on the index and then rechecking all
|
||||
* the pages; doesn't seem worth it.
|
||||
*/
|
||||
if (info->vacuum_full && nFreePages > 0)
|
||||
{
|
||||
BlockNumber new_pages = num_pages;
|
||||
BlockNumber new_pages = num_pages;
|
||||
|
||||
while (nFreePages > 0 && freePages[nFreePages-1] == new_pages-1)
|
||||
while (nFreePages > 0 && freePages[nFreePages - 1] == new_pages - 1)
|
||||
{
|
||||
new_pages--;
|
||||
pages_deleted--;
|
||||
@ -810,9 +812,10 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
|
||||
* Okay to truncate.
|
||||
*
|
||||
* First, flush any shared buffers for the blocks we intend to
|
||||
* delete. FlushRelationBuffers is a bit more than we need for
|
||||
* this, since it will also write out dirty buffers for blocks we
|
||||
* aren't deleting, but it's the closest thing in bufmgr's API.
|
||||
* delete. FlushRelationBuffers is a bit more than we need
|
||||
* for this, since it will also write out dirty buffers for
|
||||
* blocks we aren't deleting, but it's the closest thing in
|
||||
* bufmgr's API.
|
||||
*/
|
||||
i = FlushRelationBuffers(rel, new_pages);
|
||||
if (i < 0)
|
||||
@ -822,7 +825,8 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
|
||||
* Do the physical truncation.
|
||||
*/
|
||||
new_pages = smgrtruncate(DEFAULT_SMGR, rel, new_pages);
|
||||
rel->rd_nblocks = new_pages; /* update relcache immediately */
|
||||
rel->rd_nblocks = new_pages; /* update relcache
|
||||
* immediately */
|
||||
rel->rd_targblock = InvalidBlockNumber;
|
||||
num_pages = new_pages;
|
||||
}
|
||||
@ -856,7 +860,7 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
|
||||
* and so no deletion can have occurred on that page.
|
||||
*
|
||||
* On entry, we have a pin but no read lock on the buffer that contained
|
||||
* the index tuple we stopped the scan on. On exit, we have pin and read
|
||||
* the index tuple we stopped the scan on. On exit, we have pin and read
|
||||
* lock on the buffer that now contains that index tuple, and the scandesc's
|
||||
* current position is updated to point at it.
|
||||
*/
|
||||
@ -877,8 +881,8 @@ _bt_restscan(IndexScanDesc scan)
|
||||
BlockNumber blkno;
|
||||
|
||||
/*
|
||||
* Reacquire read lock on the buffer. (We should still have
|
||||
* a reference-count pin on it, so need not get that.)
|
||||
* Reacquire read lock on the buffer. (We should still have a
|
||||
* reference-count pin on it, so need not get that.)
|
||||
*/
|
||||
LockBuffer(buf, BT_READ);
|
||||
|
||||
@ -921,11 +925,11 @@ _bt_restscan(IndexScanDesc scan)
|
||||
|
||||
/*
|
||||
* The item we're looking for moved right at least one page, so
|
||||
* move right. We are careful here to pin and read-lock the next
|
||||
* non-dead page before releasing the current one. This ensures that
|
||||
* a concurrent btbulkdelete scan cannot pass our position --- if it
|
||||
* did, it might be able to reach and delete our target item before
|
||||
* we can find it again.
|
||||
* move right. We are careful here to pin and read-lock the next
|
||||
* non-dead page before releasing the current one. This ensures
|
||||
* that a concurrent btbulkdelete scan cannot pass our position
|
||||
* --- if it did, it might be able to reach and delete our target
|
||||
* item before we can find it again.
|
||||
*/
|
||||
if (P_RIGHTMOST(opaque))
|
||||
elog(ERROR, "failed to re-find previous key in \"%s\"",
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.77 2003/07/29 22:18:38 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.78 2003/08/04 00:43:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -64,8 +64,8 @@ _bt_search(Relation rel, int keysz, ScanKey scankey,
|
||||
|
||||
/*
|
||||
* Race -- the page we just grabbed may have split since we read
|
||||
* its pointer in the parent (or metapage). If it has, we may need
|
||||
* to move right to its new sibling. Do that.
|
||||
* its pointer in the parent (or metapage). If it has, we may
|
||||
* need to move right to its new sibling. Do that.
|
||||
*/
|
||||
*bufP = _bt_moveright(rel, *bufP, keysz, scankey, BT_READ);
|
||||
|
||||
@ -87,14 +87,14 @@ _bt_search(Relation rel, int keysz, ScanKey scankey,
|
||||
par_blkno = BufferGetBlockNumber(*bufP);
|
||||
|
||||
/*
|
||||
* We need to save the location of the index entry we chose in
|
||||
* the parent page on a stack. In case we split the tree, we'll
|
||||
* use the stack to work back up to the parent page. We also save
|
||||
* the actual downlink (TID) to uniquely identify the index entry,
|
||||
* in case it moves right while we're working lower in the
|
||||
* tree. See the paper by Lehman and Yao for how this is detected
|
||||
* and handled. (We use the child link to disambiguate duplicate
|
||||
* keys in the index -- Lehman and Yao disallow duplicate keys.)
|
||||
* We need to save the location of the index entry we chose in the
|
||||
* parent page on a stack. In case we split the tree, we'll use
|
||||
* the stack to work back up to the parent page. We also save the
|
||||
* actual downlink (TID) to uniquely identify the index entry, in
|
||||
* case it moves right while we're working lower in the tree. See
|
||||
* the paper by Lehman and Yao for how this is detected and
|
||||
* handled. (We use the child link to disambiguate duplicate keys
|
||||
* in the index -- Lehman and Yao disallow duplicate keys.)
|
||||
*/
|
||||
new_stack = (BTStack) palloc(sizeof(BTStackData));
|
||||
new_stack->bts_blkno = par_blkno;
|
||||
@ -151,8 +151,8 @@ _bt_moveright(Relation rel,
|
||||
* might not need to move right; have to scan the page first anyway.)
|
||||
* It could even have split more than once, so scan as far as needed.
|
||||
*
|
||||
* We also have to move right if we followed a link that brought us to
|
||||
* a dead page.
|
||||
* We also have to move right if we followed a link that brought us to a
|
||||
* dead page.
|
||||
*/
|
||||
while (!P_RIGHTMOST(opaque) &&
|
||||
(P_IGNORE(opaque) ||
|
||||
@ -599,8 +599,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
||||
/*
|
||||
* At this point we are positioned at the first item >= scan key, or
|
||||
* possibly at the end of a page on which all the existing items are
|
||||
* less than the scan key and we know that everything on later
|
||||
* pages is greater than or equal to scan key.
|
||||
* less than the scan key and we know that everything on later pages
|
||||
* is greater than or equal to scan key.
|
||||
*
|
||||
* We could step forward in the latter case, but that'd be a waste of
|
||||
* time if we want to scan backwards. So, it's now time to examine
|
||||
@ -851,7 +851,8 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* backwards scan */
|
||||
else
|
||||
/* backwards scan */
|
||||
{
|
||||
if (offnum > P_FIRSTDATAKEY(opaque))
|
||||
offnum = OffsetNumberPrev(offnum);
|
||||
@ -860,9 +861,9 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
|
||||
/*
|
||||
* Walk left to the next page with data. This is much more
|
||||
* complex than the walk-right case because of the possibility
|
||||
* that the page to our left splits while we are in flight to it,
|
||||
* plus the possibility that the page we were on gets deleted
|
||||
* after we leave it. See nbtree/README for details.
|
||||
* that the page to our left splits while we are in flight to
|
||||
* it, plus the possibility that the page we were on gets
|
||||
* deleted after we leave it. See nbtree/README for details.
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
@ -877,10 +878,11 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
|
||||
}
|
||||
page = BufferGetPage(*bufP);
|
||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
|
||||
/*
|
||||
* Okay, we managed to move left to a non-deleted page.
|
||||
* Done if it's not half-dead and not empty. Else loop back
|
||||
* and do it all again.
|
||||
* Done if it's not half-dead and not empty. Else loop
|
||||
* back and do it all again.
|
||||
*/
|
||||
if (!P_IGNORE(opaque))
|
||||
{
|
||||
@ -946,17 +948,18 @@ _bt_walk_left(Relation rel, Buffer buf)
|
||||
buf = _bt_getbuf(rel, blkno, BT_READ);
|
||||
page = BufferGetPage(buf);
|
||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
|
||||
/*
|
||||
* If this isn't the page we want, walk right till we find
|
||||
* what we want --- but go no more than four hops (an
|
||||
* arbitrary limit). If we don't find the correct page by then,
|
||||
* the most likely bet is that the original page got deleted
|
||||
* and isn't in the sibling chain at all anymore, not that its
|
||||
* left sibling got split more than four times.
|
||||
* If this isn't the page we want, walk right till we find what we
|
||||
* want --- but go no more than four hops (an arbitrary limit).
|
||||
* If we don't find the correct page by then, the most likely bet
|
||||
* is that the original page got deleted and isn't in the sibling
|
||||
* chain at all anymore, not that its left sibling got split more
|
||||
* than four times.
|
||||
*
|
||||
* Note that it is correct to test P_ISDELETED not P_IGNORE
|
||||
* here, because half-dead pages are still in the sibling
|
||||
* chain. Caller must reject half-dead pages if wanted.
|
||||
* Note that it is correct to test P_ISDELETED not P_IGNORE here,
|
||||
* because half-dead pages are still in the sibling chain. Caller
|
||||
* must reject half-dead pages if wanted.
|
||||
*/
|
||||
tries = 0;
|
||||
for (;;)
|
||||
@ -983,8 +986,8 @@ _bt_walk_left(Relation rel, Buffer buf)
|
||||
if (P_ISDELETED(opaque))
|
||||
{
|
||||
/*
|
||||
* It was deleted. Move right to first nondeleted page
|
||||
* (there must be one); that is the page that has acquired the
|
||||
* It was deleted. Move right to first nondeleted page (there
|
||||
* must be one); that is the page that has acquired the
|
||||
* deleted one's keyspace, so stepping left from it will take
|
||||
* us where we want to be.
|
||||
*/
|
||||
@ -1001,18 +1004,18 @@ _bt_walk_left(Relation rel, Buffer buf)
|
||||
if (!P_ISDELETED(opaque))
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now return to top of loop, resetting obknum to
|
||||
* point to this nondeleted page, and try again.
|
||||
* Now return to top of loop, resetting obknum to point to
|
||||
* this nondeleted page, and try again.
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* It wasn't deleted; the explanation had better be
|
||||
* that the page to the left got split or deleted.
|
||||
* Without this check, we'd go into an infinite loop
|
||||
* if there's anything wrong.
|
||||
* It wasn't deleted; the explanation had better be that the
|
||||
* page to the left got split or deleted. Without this check,
|
||||
* we'd go into an infinite loop if there's anything wrong.
|
||||
*/
|
||||
if (opaque->btpo_prev == lblkno)
|
||||
elog(ERROR, "could not find left sibling in \"%s\"",
|
||||
@ -1028,7 +1031,7 @@ _bt_walk_left(Relation rel, Buffer buf)
|
||||
* _bt_get_endpoint() -- Find the first or last page on a given tree level
|
||||
*
|
||||
* If the index is empty, we will return InvalidBuffer; any other failure
|
||||
* condition causes ereport(). We will not return a dead page.
|
||||
* condition causes ereport(). We will not return a dead page.
|
||||
*
|
||||
* The returned buffer is pinned and read-locked.
|
||||
*/
|
||||
@ -1045,8 +1048,8 @@ _bt_get_endpoint(Relation rel, uint32 level, bool rightmost)
|
||||
|
||||
/*
|
||||
* If we are looking for a leaf page, okay to descend from fast root;
|
||||
* otherwise better descend from true root. (There is no point in being
|
||||
* smarter about intermediate levels.)
|
||||
* otherwise better descend from true root. (There is no point in
|
||||
* being smarter about intermediate levels.)
|
||||
*/
|
||||
if (level == 0)
|
||||
buf = _bt_getroot(rel, BT_READ);
|
||||
@ -1066,9 +1069,9 @@ _bt_get_endpoint(Relation rel, uint32 level, bool rightmost)
|
||||
{
|
||||
/*
|
||||
* If we landed on a deleted page, step right to find a live page
|
||||
* (there must be one). Also, if we want the rightmost page,
|
||||
* step right if needed to get to it (this could happen if the
|
||||
* page split since we obtained a pointer to it).
|
||||
* (there must be one). Also, if we want the rightmost page, step
|
||||
* right if needed to get to it (this could happen if the page
|
||||
* split since we obtained a pointer to it).
|
||||
*/
|
||||
while (P_IGNORE(opaque) ||
|
||||
(rightmost && !P_RIGHTMOST(opaque)))
|
||||
|
@ -36,7 +36,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.73 2003/07/21 20:29:39 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.74 2003/08/04 00:43:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -93,7 +93,7 @@ typedef struct BTPageState
|
||||
|
||||
|
||||
static void _bt_blnewpage(Relation index, Buffer *buf, Page *page,
|
||||
uint32 level);
|
||||
uint32 level);
|
||||
static BTPageState *_bt_pagestate(Relation index, uint32 level);
|
||||
static void _bt_slideleft(Relation index, Buffer buf, Page page);
|
||||
static void _bt_sortaddtup(Page page, Size itemsize,
|
||||
@ -469,7 +469,7 @@ _bt_buildadd(Relation index, BTPageState *state, BTItem bti)
|
||||
|
||||
oopaque->btpo_next = BufferGetBlockNumber(nbuf);
|
||||
nopaque->btpo_prev = BufferGetBlockNumber(obuf);
|
||||
nopaque->btpo_next = P_NONE; /* redundant */
|
||||
nopaque->btpo_next = P_NONE; /* redundant */
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.3 2003/02/23 22:43:08 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.4 2003/08/04 00:43:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -29,10 +29,10 @@
|
||||
typedef struct bt_incomplete_split
|
||||
{
|
||||
RelFileNode node; /* the index */
|
||||
BlockNumber leftblk; /* left half of split */
|
||||
BlockNumber rightblk; /* right half of split */
|
||||
BlockNumber leftblk; /* left half of split */
|
||||
BlockNumber rightblk; /* right half of split */
|
||||
bool is_root; /* we split the root */
|
||||
} bt_incomplete_split;
|
||||
} bt_incomplete_split;
|
||||
|
||||
static List *incomplete_splits;
|
||||
|
||||
@ -107,7 +107,7 @@ _bt_restore_page(Page page, char *from, int len)
|
||||
}
|
||||
|
||||
static void
|
||||
_bt_restore_meta(Relation reln, XLogRecPtr lsn,
|
||||
_bt_restore_meta(Relation reln, XLogRecPtr lsn,
|
||||
BlockNumber root, uint32 level,
|
||||
BlockNumber fastroot, uint32 fastlevel)
|
||||
{
|
||||
@ -172,7 +172,7 @@ btree_xlog_insert(bool redo, bool isleaf, bool ismeta,
|
||||
if (!redo || !(record->xl_info & XLR_BKP_BLOCK_1))
|
||||
{
|
||||
buffer = XLogReadBuffer(false, reln,
|
||||
ItemPointerGetBlockNumber(&(xlrec->target.tid)));
|
||||
ItemPointerGetBlockNumber(&(xlrec->target.tid)));
|
||||
if (!BufferIsValid(buffer))
|
||||
elog(PANIC, "btree_insert_%sdo: block unfound", (redo) ? "re" : "un");
|
||||
page = (Page) BufferGetPage(buffer);
|
||||
@ -183,13 +183,11 @@ btree_xlog_insert(bool redo, bool isleaf, bool ismeta,
|
||||
if (redo)
|
||||
{
|
||||
if (XLByteLE(lsn, PageGetLSN(page)))
|
||||
{
|
||||
UnlockAndReleaseBuffer(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PageAddItem(page, (Item) datapos, datalen,
|
||||
ItemPointerGetOffsetNumber(&(xlrec->target.tid)),
|
||||
ItemPointerGetOffsetNumber(&(xlrec->target.tid)),
|
||||
LP_USED) == InvalidOffsetNumber)
|
||||
elog(PANIC, "btree_insert_redo: failed to add item");
|
||||
|
||||
@ -204,13 +202,9 @@ btree_xlog_insert(bool redo, bool isleaf, bool ismeta,
|
||||
elog(PANIC, "btree_insert_undo: bad page LSN");
|
||||
|
||||
if (!P_ISLEAF(pageop))
|
||||
{
|
||||
UnlockAndReleaseBuffer(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
elog(PANIC, "btree_insert_undo: unimplemented");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,8 +220,8 @@ btree_xlog_insert(bool redo, bool isleaf, bool ismeta,
|
||||
if (redo && !isleaf && incomplete_splits != NIL)
|
||||
{
|
||||
forget_matching_split(reln, xlrec->target.node,
|
||||
ItemPointerGetBlockNumber(&(xlrec->target.tid)),
|
||||
ItemPointerGetOffsetNumber(&(xlrec->target.tid)),
|
||||
ItemPointerGetBlockNumber(&(xlrec->target.tid)),
|
||||
ItemPointerGetOffsetNumber(&(xlrec->target.tid)),
|
||||
false);
|
||||
}
|
||||
}
|
||||
@ -238,9 +232,9 @@ btree_xlog_split(bool redo, bool onleft, bool isroot,
|
||||
{
|
||||
xl_btree_split *xlrec = (xl_btree_split *) XLogRecGetData(record);
|
||||
Relation reln;
|
||||
BlockNumber targetblk;
|
||||
BlockNumber leftsib;
|
||||
BlockNumber rightsib;
|
||||
BlockNumber targetblk;
|
||||
BlockNumber leftsib;
|
||||
BlockNumber rightsib;
|
||||
Buffer buffer;
|
||||
Page page;
|
||||
BTPageOpaque pageop;
|
||||
@ -338,9 +332,7 @@ btree_xlog_split(bool redo, bool onleft, bool isroot,
|
||||
elog(PANIC, "btree_split_redo: uninitialized next right page");
|
||||
|
||||
if (XLByteLE(lsn, PageGetLSN(page)))
|
||||
{
|
||||
UnlockAndReleaseBuffer(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
pageop = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
@ -357,8 +349,8 @@ btree_xlog_split(bool redo, bool onleft, bool isroot,
|
||||
if (redo && xlrec->level > 0 && incomplete_splits != NIL)
|
||||
{
|
||||
forget_matching_split(reln, xlrec->target.node,
|
||||
ItemPointerGetBlockNumber(&(xlrec->target.tid)),
|
||||
ItemPointerGetOffsetNumber(&(xlrec->target.tid)),
|
||||
ItemPointerGetBlockNumber(&(xlrec->target.tid)),
|
||||
ItemPointerGetOffsetNumber(&(xlrec->target.tid)),
|
||||
false);
|
||||
}
|
||||
|
||||
@ -422,10 +414,10 @@ btree_xlog_delete_page(bool redo, bool ismeta,
|
||||
{
|
||||
xl_btree_delete_page *xlrec = (xl_btree_delete_page *) XLogRecGetData(record);
|
||||
Relation reln;
|
||||
BlockNumber parent;
|
||||
BlockNumber target;
|
||||
BlockNumber leftsib;
|
||||
BlockNumber rightsib;
|
||||
BlockNumber parent;
|
||||
BlockNumber target;
|
||||
BlockNumber leftsib;
|
||||
BlockNumber rightsib;
|
||||
Buffer buffer;
|
||||
Page page;
|
||||
BTPageOpaque pageop;
|
||||
@ -451,9 +443,7 @@ btree_xlog_delete_page(bool redo, bool ismeta,
|
||||
if (PageIsNew((PageHeader) page))
|
||||
elog(PANIC, "btree_delete_page_redo: uninitialized parent page");
|
||||
if (XLByteLE(lsn, PageGetLSN(page)))
|
||||
{
|
||||
UnlockAndReleaseBuffer(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
OffsetNumber poffset;
|
||||
@ -469,7 +459,7 @@ btree_xlog_delete_page(bool redo, bool ismeta,
|
||||
{
|
||||
ItemId itemid;
|
||||
BTItem btitem;
|
||||
OffsetNumber nextoffset;
|
||||
OffsetNumber nextoffset;
|
||||
|
||||
itemid = PageGetItemId(page, poffset);
|
||||
btitem = (BTItem) PageGetItem(page, itemid);
|
||||
@ -494,9 +484,7 @@ btree_xlog_delete_page(bool redo, bool ismeta,
|
||||
if (PageIsNew((PageHeader) page))
|
||||
elog(PANIC, "btree_delete_page_redo: uninitialized right sibling");
|
||||
if (XLByteLE(lsn, PageGetLSN(page)))
|
||||
{
|
||||
UnlockAndReleaseBuffer(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
pageop = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
@ -520,9 +508,7 @@ btree_xlog_delete_page(bool redo, bool ismeta,
|
||||
if (PageIsNew((PageHeader) page))
|
||||
elog(PANIC, "btree_delete_page_redo: uninitialized left sibling");
|
||||
if (XLByteLE(lsn, PageGetLSN(page)))
|
||||
{
|
||||
UnlockAndReleaseBuffer(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
pageop = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
@ -799,116 +785,116 @@ btree_desc(char *buf, uint8 xl_info, char *rec)
|
||||
switch (info)
|
||||
{
|
||||
case XLOG_BTREE_INSERT_LEAF:
|
||||
{
|
||||
xl_btree_insert *xlrec = (xl_btree_insert *) rec;
|
||||
{
|
||||
xl_btree_insert *xlrec = (xl_btree_insert *) rec;
|
||||
|
||||
strcat(buf, "insert: ");
|
||||
out_target(buf, &(xlrec->target));
|
||||
break;
|
||||
}
|
||||
strcat(buf, "insert: ");
|
||||
out_target(buf, &(xlrec->target));
|
||||
break;
|
||||
}
|
||||
case XLOG_BTREE_INSERT_UPPER:
|
||||
{
|
||||
xl_btree_insert *xlrec = (xl_btree_insert *) rec;
|
||||
{
|
||||
xl_btree_insert *xlrec = (xl_btree_insert *) rec;
|
||||
|
||||
strcat(buf, "insert_upper: ");
|
||||
out_target(buf, &(xlrec->target));
|
||||
break;
|
||||
}
|
||||
strcat(buf, "insert_upper: ");
|
||||
out_target(buf, &(xlrec->target));
|
||||
break;
|
||||
}
|
||||
case XLOG_BTREE_INSERT_META:
|
||||
{
|
||||
xl_btree_insert *xlrec = (xl_btree_insert *) rec;
|
||||
{
|
||||
xl_btree_insert *xlrec = (xl_btree_insert *) rec;
|
||||
|
||||
strcat(buf, "insert_meta: ");
|
||||
out_target(buf, &(xlrec->target));
|
||||
break;
|
||||
}
|
||||
strcat(buf, "insert_meta: ");
|
||||
out_target(buf, &(xlrec->target));
|
||||
break;
|
||||
}
|
||||
case XLOG_BTREE_SPLIT_L:
|
||||
{
|
||||
xl_btree_split *xlrec = (xl_btree_split *) rec;
|
||||
{
|
||||
xl_btree_split *xlrec = (xl_btree_split *) rec;
|
||||
|
||||
strcat(buf, "split_l: ");
|
||||
out_target(buf, &(xlrec->target));
|
||||
sprintf(buf + strlen(buf), "; oth %u; rgh %u",
|
||||
xlrec->otherblk, xlrec->rightblk);
|
||||
break;
|
||||
}
|
||||
strcat(buf, "split_l: ");
|
||||
out_target(buf, &(xlrec->target));
|
||||
sprintf(buf + strlen(buf), "; oth %u; rgh %u",
|
||||
xlrec->otherblk, xlrec->rightblk);
|
||||
break;
|
||||
}
|
||||
case XLOG_BTREE_SPLIT_R:
|
||||
{
|
||||
xl_btree_split *xlrec = (xl_btree_split *) rec;
|
||||
{
|
||||
xl_btree_split *xlrec = (xl_btree_split *) rec;
|
||||
|
||||
strcat(buf, "split_r: ");
|
||||
out_target(buf, &(xlrec->target));
|
||||
sprintf(buf + strlen(buf), "; oth %u; rgh %u",
|
||||
xlrec->otherblk, xlrec->rightblk);
|
||||
break;
|
||||
}
|
||||
strcat(buf, "split_r: ");
|
||||
out_target(buf, &(xlrec->target));
|
||||
sprintf(buf + strlen(buf), "; oth %u; rgh %u",
|
||||
xlrec->otherblk, xlrec->rightblk);
|
||||
break;
|
||||
}
|
||||
case XLOG_BTREE_SPLIT_L_ROOT:
|
||||
{
|
||||
xl_btree_split *xlrec = (xl_btree_split *) rec;
|
||||
{
|
||||
xl_btree_split *xlrec = (xl_btree_split *) rec;
|
||||
|
||||
strcat(buf, "split_l_root: ");
|
||||
out_target(buf, &(xlrec->target));
|
||||
sprintf(buf + strlen(buf), "; oth %u; rgh %u",
|
||||
xlrec->otherblk, xlrec->rightblk);
|
||||
break;
|
||||
}
|
||||
strcat(buf, "split_l_root: ");
|
||||
out_target(buf, &(xlrec->target));
|
||||
sprintf(buf + strlen(buf), "; oth %u; rgh %u",
|
||||
xlrec->otherblk, xlrec->rightblk);
|
||||
break;
|
||||
}
|
||||
case XLOG_BTREE_SPLIT_R_ROOT:
|
||||
{
|
||||
xl_btree_split *xlrec = (xl_btree_split *) rec;
|
||||
{
|
||||
xl_btree_split *xlrec = (xl_btree_split *) rec;
|
||||
|
||||
strcat(buf, "split_r_root: ");
|
||||
out_target(buf, &(xlrec->target));
|
||||
sprintf(buf + strlen(buf), "; oth %u; rgh %u",
|
||||
xlrec->otherblk, xlrec->rightblk);
|
||||
break;
|
||||
}
|
||||
strcat(buf, "split_r_root: ");
|
||||
out_target(buf, &(xlrec->target));
|
||||
sprintf(buf + strlen(buf), "; oth %u; rgh %u",
|
||||
xlrec->otherblk, xlrec->rightblk);
|
||||
break;
|
||||
}
|
||||
case XLOG_BTREE_DELETE:
|
||||
{
|
||||
xl_btree_delete *xlrec = (xl_btree_delete *) rec;
|
||||
{
|
||||
xl_btree_delete *xlrec = (xl_btree_delete *) rec;
|
||||
|
||||
sprintf(buf + strlen(buf), "delete: node %u/%u; blk %u",
|
||||
xlrec->node.tblNode, xlrec->node.relNode, xlrec->block);
|
||||
break;
|
||||
}
|
||||
sprintf(buf + strlen(buf), "delete: node %u/%u; blk %u",
|
||||
xlrec->node.tblNode, xlrec->node.relNode, xlrec->block);
|
||||
break;
|
||||
}
|
||||
case XLOG_BTREE_DELETE_PAGE:
|
||||
case XLOG_BTREE_DELETE_PAGE_META:
|
||||
{
|
||||
xl_btree_delete_page *xlrec = (xl_btree_delete_page *) rec;
|
||||
{
|
||||
xl_btree_delete_page *xlrec = (xl_btree_delete_page *) rec;
|
||||
|
||||
strcat(buf, "delete_page: ");
|
||||
out_target(buf, &(xlrec->target));
|
||||
sprintf(buf + strlen(buf), "; dead %u; left %u; right %u",
|
||||
xlrec->deadblk, xlrec->leftblk, xlrec->rightblk);
|
||||
break;
|
||||
}
|
||||
strcat(buf, "delete_page: ");
|
||||
out_target(buf, &(xlrec->target));
|
||||
sprintf(buf + strlen(buf), "; dead %u; left %u; right %u",
|
||||
xlrec->deadblk, xlrec->leftblk, xlrec->rightblk);
|
||||
break;
|
||||
}
|
||||
case XLOG_BTREE_NEWROOT:
|
||||
{
|
||||
xl_btree_newroot *xlrec = (xl_btree_newroot *) rec;
|
||||
{
|
||||
xl_btree_newroot *xlrec = (xl_btree_newroot *) rec;
|
||||
|
||||
sprintf(buf + strlen(buf), "newroot: node %u/%u; root %u lev %u",
|
||||
xlrec->node.tblNode, xlrec->node.relNode,
|
||||
xlrec->rootblk, xlrec->level);
|
||||
break;
|
||||
}
|
||||
sprintf(buf + strlen(buf), "newroot: node %u/%u; root %u lev %u",
|
||||
xlrec->node.tblNode, xlrec->node.relNode,
|
||||
xlrec->rootblk, xlrec->level);
|
||||
break;
|
||||
}
|
||||
case XLOG_BTREE_NEWMETA:
|
||||
{
|
||||
xl_btree_newmeta *xlrec = (xl_btree_newmeta *) rec;
|
||||
{
|
||||
xl_btree_newmeta *xlrec = (xl_btree_newmeta *) rec;
|
||||
|
||||
sprintf(buf + strlen(buf), "newmeta: node %u/%u; root %u lev %u fast %u lev %u",
|
||||
xlrec->node.tblNode, xlrec->node.relNode,
|
||||
xlrec->meta.root, xlrec->meta.level,
|
||||
xlrec->meta.fastroot, xlrec->meta.fastlevel);
|
||||
break;
|
||||
}
|
||||
sprintf(buf + strlen(buf), "newmeta: node %u/%u; root %u lev %u fast %u lev %u",
|
||||
xlrec->node.tblNode, xlrec->node.relNode,
|
||||
xlrec->meta.root, xlrec->meta.level,
|
||||
xlrec->meta.fastroot, xlrec->meta.fastlevel);
|
||||
break;
|
||||
}
|
||||
case XLOG_BTREE_NEWPAGE:
|
||||
{
|
||||
xl_btree_newpage *xlrec = (xl_btree_newpage *) rec;
|
||||
{
|
||||
xl_btree_newpage *xlrec = (xl_btree_newpage *) rec;
|
||||
|
||||
sprintf(buf + strlen(buf), "newpage: node %u/%u; page %u",
|
||||
xlrec->node.tblNode, xlrec->node.relNode,
|
||||
xlrec->blkno);
|
||||
break;
|
||||
}
|
||||
sprintf(buf + strlen(buf), "newpage: node %u/%u; page %u",
|
||||
xlrec->node.tblNode, xlrec->node.relNode,
|
||||
xlrec->blkno);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
strcat(buf, "UNKNOWN");
|
||||
break;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.45 2003/07/28 00:09:14 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.46 2003/08/04 00:43:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -109,10 +109,10 @@ rtrescan(PG_FUNCTION_ARGS)
|
||||
s->numberOfKeys * sizeof(ScanKeyData));
|
||||
|
||||
/*
|
||||
* Scans on internal pages use different operators than they
|
||||
* do on leaf pages. For example, if the user wants all boxes
|
||||
* that exactly match (x1,y1,x2,y2), then on internal pages we
|
||||
* need to find all boxes that contain (x1,y1,x2,y2).
|
||||
* Scans on internal pages use different operators than they do on
|
||||
* leaf pages. For example, if the user wants all boxes that
|
||||
* exactly match (x1,y1,x2,y2), then on internal pages we need to
|
||||
* find all boxes that contain (x1,y1,x2,y2).
|
||||
*/
|
||||
for (i = 0; i < s->numberOfKeys; i++)
|
||||
{
|
||||
|
@ -13,7 +13,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/clog.c,v 1.16 2003/06/11 22:37:45 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/clog.c,v 1.17 2003/08/04 00:43:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -73,7 +73,7 @@
|
||||
|
||||
static SlruCtlData ClogCtlData;
|
||||
static SlruCtl ClogCtl = &ClogCtlData;
|
||||
|
||||
|
||||
|
||||
static int ZeroCLOGPage(int pageno, bool writeXlog);
|
||||
static bool CLOGPagePrecedes(int page1, int page2);
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Resource managers definition
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/rmgr.c,v 1.10 2003/02/21 00:06:22 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/rmgr.c,v 1.11 2003/08/04 00:43:15 momjian Exp $
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
#include "commands/sequence.h"
|
||||
|
||||
|
||||
RmgrData RmgrTable[RM_MAX_ID+1] = {
|
||||
RmgrData RmgrTable[RM_MAX_ID + 1] = {
|
||||
{"XLOG", xlog_redo, xlog_undo, xlog_desc, NULL, NULL},
|
||||
{"Transaction", xact_redo, xact_undo, xact_desc, NULL, NULL},
|
||||
{"Storage", smgr_redo, smgr_undo, smgr_desc, NULL, NULL},
|
||||
@ -32,7 +32,7 @@ RmgrData RmgrTable[RM_MAX_ID+1] = {
|
||||
{"Reserved 9", NULL, NULL, NULL, NULL, NULL},
|
||||
{"Heap", heap_redo, heap_undo, heap_desc, NULL, NULL},
|
||||
{"Btree", btree_redo, btree_undo, btree_desc,
|
||||
btree_xlog_startup, btree_xlog_cleanup},
|
||||
btree_xlog_startup, btree_xlog_cleanup},
|
||||
{"Hash", hash_redo, hash_undo, hash_desc, NULL, NULL},
|
||||
{"Rtree", rtree_redo, rtree_undo, rtree_desc, NULL, NULL},
|
||||
{"Gist", gist_redo, gist_undo, gist_desc, NULL, NULL},
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/slru.c,v 1.3 2003/07/28 00:09:14 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/slru.c,v 1.4 2003/08/04 00:43:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -93,7 +93,7 @@ typedef enum
|
||||
SLRU_PAGE_CLEAN, /* page is valid and not dirty */
|
||||
SLRU_PAGE_DIRTY, /* page is valid but needs write */
|
||||
SLRU_PAGE_WRITE_IN_PROGRESS /* page is being written out */
|
||||
} SlruPageStatus;
|
||||
} SlruPageStatus;
|
||||
|
||||
/*
|
||||
* Shared-memory state
|
||||
@ -117,7 +117,7 @@ typedef struct SlruSharedData
|
||||
* swapping out the latest page.
|
||||
*/
|
||||
int latest_page_number;
|
||||
} SlruSharedData;
|
||||
} SlruSharedData;
|
||||
typedef SlruSharedData *SlruShared;
|
||||
|
||||
|
||||
@ -145,7 +145,7 @@ typedef enum
|
||||
SLRU_SEEK_FAILED,
|
||||
SLRU_READ_FAILED,
|
||||
SLRU_WRITE_FAILED
|
||||
} SlruErrorCause;
|
||||
} SlruErrorCause;
|
||||
static SlruErrorCause slru_errcause;
|
||||
static int slru_errno;
|
||||
|
||||
@ -166,9 +166,9 @@ SimpleLruShmemSize(void)
|
||||
{
|
||||
return MAXALIGN(sizeof(SlruSharedData)) + BLCKSZ * NUM_CLOG_BUFFERS
|
||||
#ifdef EXEC_BACKEND
|
||||
+ MAXALIGN(sizeof(SlruLockData))
|
||||
+ MAXALIGN(sizeof(SlruLockData))
|
||||
#endif
|
||||
;
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
@ -183,12 +183,14 @@ SimpleLruInit(SlruCtl ctl, const char *name, const char *subdir)
|
||||
shared = (SlruShared) ptr;
|
||||
|
||||
#ifdef EXEC_BACKEND
|
||||
|
||||
/*
|
||||
* Locks are in shared memory
|
||||
*/
|
||||
locks = (SlruLock)(ptr + MAXALIGN(sizeof(SlruSharedData)) +
|
||||
BLCKSZ * NUM_CLOG_BUFFERS);
|
||||
locks = (SlruLock) (ptr + MAXALIGN(sizeof(SlruSharedData)) +
|
||||
BLCKSZ * NUM_CLOG_BUFFERS);
|
||||
#else
|
||||
|
||||
/*
|
||||
* Locks are in private memory
|
||||
*/
|
||||
@ -199,7 +201,7 @@ SimpleLruInit(SlruCtl ctl, const char *name, const char *subdir)
|
||||
|
||||
|
||||
if (!IsUnderPostmaster)
|
||||
/* Initialize locks and shared memory area */
|
||||
/* Initialize locks and shared memory area */
|
||||
{
|
||||
char *bufptr;
|
||||
int slotno;
|
||||
@ -210,8 +212,8 @@ SimpleLruInit(SlruCtl ctl, const char *name, const char *subdir)
|
||||
|
||||
memset(shared, 0, sizeof(SlruSharedData));
|
||||
|
||||
bufptr = (char *)shared + MAXALIGN(sizeof(SlruSharedData));
|
||||
|
||||
bufptr = (char *) shared + MAXALIGN(sizeof(SlruSharedData));
|
||||
|
||||
for (slotno = 0; slotno < NUM_CLOG_BUFFERS; slotno++)
|
||||
{
|
||||
locks->BufferLocks[slotno] = LWLockAssign();
|
||||
@ -247,7 +249,7 @@ int
|
||||
SimpleLruZeroPage(SlruCtl ctl, int pageno)
|
||||
{
|
||||
int slotno;
|
||||
SlruShared shared = (SlruShared) ctl->shared;
|
||||
SlruShared shared = (SlruShared) ctl->shared;
|
||||
|
||||
/* Find a suitable buffer slot for the page */
|
||||
slotno = SlruSelectLRUPage(ctl, pageno);
|
||||
@ -285,7 +287,7 @@ SimpleLruZeroPage(SlruCtl ctl, int pageno)
|
||||
char *
|
||||
SimpleLruReadPage(SlruCtl ctl, int pageno, TransactionId xid, bool forwrite)
|
||||
{
|
||||
SlruShared shared = (SlruShared) ctl->shared;
|
||||
SlruShared shared = (SlruShared) ctl->shared;
|
||||
|
||||
/* Outer loop handles restart if we lose the buffer to someone else */
|
||||
for (;;)
|
||||
@ -383,7 +385,7 @@ SimpleLruWritePage(SlruCtl ctl, int slotno)
|
||||
{
|
||||
int pageno;
|
||||
bool ok;
|
||||
SlruShared shared = (SlruShared) ctl->shared;
|
||||
SlruShared shared = (SlruShared) ctl->shared;
|
||||
|
||||
/* Do nothing if page does not need writing */
|
||||
if (shared->page_status[slotno] != SLRU_PAGE_DIRTY &&
|
||||
@ -539,13 +541,13 @@ SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno)
|
||||
* possible for this to need to happen when writing a page that's not
|
||||
* first in its segment; we assume the OS can cope with that. (Note:
|
||||
* it might seem that it'd be okay to create files only when
|
||||
* SimpleLruZeroPage is called for the first page of a segment. However,
|
||||
* if after a crash and restart the REDO logic elects to replay the
|
||||
* log from a checkpoint before the latest one, then it's possible
|
||||
* that we will get commands to set transaction status of transactions
|
||||
* that have already been truncated from the commit log. Easiest way
|
||||
* to deal with that is to accept references to nonexistent files here
|
||||
* and in SlruPhysicalReadPage.)
|
||||
* SimpleLruZeroPage is called for the first page of a segment.
|
||||
* However, if after a crash and restart the REDO logic elects to
|
||||
* replay the log from a checkpoint before the latest one, then it's
|
||||
* possible that we will get commands to set transaction status of
|
||||
* transactions that have already been truncated from the commit log.
|
||||
* Easiest way to deal with that is to accept references to
|
||||
* nonexistent files here and in SlruPhysicalReadPage.)
|
||||
*/
|
||||
fd = BasicOpenFile(path, O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR);
|
||||
if (fd < 0)
|
||||
@ -608,37 +610,37 @@ SlruReportIOError(SlruCtl ctl, int pageno, TransactionId xid)
|
||||
case SLRU_OPEN_FAILED:
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not access status of transaction %u", xid),
|
||||
errmsg("could not access status of transaction %u", xid),
|
||||
errdetail("open of file \"%s\" failed: %m",
|
||||
path)));
|
||||
break;
|
||||
case SLRU_CREATE_FAILED:
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not access status of transaction %u", xid),
|
||||
errmsg("could not access status of transaction %u", xid),
|
||||
errdetail("creation of file \"%s\" failed: %m",
|
||||
path)));
|
||||
break;
|
||||
case SLRU_SEEK_FAILED:
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not access status of transaction %u", xid),
|
||||
errdetail("lseek of file \"%s\", offset %u failed: %m",
|
||||
path, offset)));
|
||||
errmsg("could not access status of transaction %u", xid),
|
||||
errdetail("lseek of file \"%s\", offset %u failed: %m",
|
||||
path, offset)));
|
||||
break;
|
||||
case SLRU_READ_FAILED:
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not access status of transaction %u", xid),
|
||||
errdetail("read of file \"%s\", offset %u failed: %m",
|
||||
path, offset)));
|
||||
errmsg("could not access status of transaction %u", xid),
|
||||
errdetail("read of file \"%s\", offset %u failed: %m",
|
||||
path, offset)));
|
||||
break;
|
||||
case SLRU_WRITE_FAILED:
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not access status of transaction %u", xid),
|
||||
errdetail("write of file \"%s\", offset %u failed: %m",
|
||||
path, offset)));
|
||||
errmsg("could not access status of transaction %u", xid),
|
||||
errdetail("write of file \"%s\", offset %u failed: %m",
|
||||
path, offset)));
|
||||
break;
|
||||
default:
|
||||
/* can't get here, we trust */
|
||||
@ -665,6 +667,7 @@ static int
|
||||
SlruSelectLRUPage(SlruCtl ctl, int pageno)
|
||||
{
|
||||
SlruShared shared = (SlruShared) ctl->shared;
|
||||
|
||||
/* Outer loop handles restart after I/O */
|
||||
for (;;)
|
||||
{
|
||||
@ -689,7 +692,7 @@ SlruSelectLRUPage(SlruCtl ctl, int pageno)
|
||||
if (shared->page_status[slotno] == SLRU_PAGE_EMPTY)
|
||||
return slotno;
|
||||
if (shared->page_lru_count[slotno] > bestcount &&
|
||||
shared->page_number[slotno] != shared->latest_page_number)
|
||||
shared->page_number[slotno] != shared->latest_page_number)
|
||||
{
|
||||
bestslot = slotno;
|
||||
bestcount = shared->page_lru_count[slotno];
|
||||
@ -705,12 +708,12 @@ SlruSelectLRUPage(SlruCtl ctl, int pageno)
|
||||
/*
|
||||
* We need to do I/O. Normal case is that we have to write it
|
||||
* out, but it's possible in the worst case to have selected a
|
||||
* read-busy page. In that case we use SimpleLruReadPage to wait for
|
||||
* the read to complete.
|
||||
* read-busy page. In that case we use SimpleLruReadPage to wait
|
||||
* for the read to complete.
|
||||
*/
|
||||
if (shared->page_status[bestslot] == SLRU_PAGE_READ_IN_PROGRESS)
|
||||
(void) SimpleLruReadPage(ctl, shared->page_number[bestslot],
|
||||
InvalidTransactionId, false);
|
||||
InvalidTransactionId, false);
|
||||
else
|
||||
SimpleLruWritePage(ctl, bestslot);
|
||||
|
||||
@ -747,10 +750,11 @@ SimpleLruFlush(SlruCtl ctl, bool checkpoint)
|
||||
for (slotno = 0; slotno < NUM_CLOG_BUFFERS; slotno++)
|
||||
{
|
||||
SimpleLruWritePage(ctl, slotno);
|
||||
|
||||
/*
|
||||
* When called during a checkpoint,
|
||||
* we cannot assert that the slot is clean now, since another
|
||||
* process might have re-dirtied it already. That's okay.
|
||||
* When called during a checkpoint, we cannot assert that the slot
|
||||
* is clean now, since another process might have re-dirtied it
|
||||
* already. That's okay.
|
||||
*/
|
||||
Assert(checkpoint ||
|
||||
shared->page_status[slotno] == SLRU_PAGE_EMPTY ||
|
||||
@ -792,10 +796,10 @@ SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
|
||||
CreateCheckPoint(false, true);
|
||||
|
||||
/*
|
||||
* Scan shared memory and remove any pages preceding the cutoff
|
||||
* page, to ensure we won't rewrite them later. (Any dirty pages
|
||||
* should have been flushed already during the checkpoint, we're just
|
||||
* being extra careful here.)
|
||||
* Scan shared memory and remove any pages preceding the cutoff page,
|
||||
* to ensure we won't rewrite them later. (Any dirty pages should
|
||||
* have been flushed already during the checkpoint, we're just being
|
||||
* extra careful here.)
|
||||
*/
|
||||
LWLockAcquire(ctl->locks->ControlLock, LW_EXCLUSIVE);
|
||||
|
||||
@ -870,7 +874,7 @@ SlruScanDirectory(SlruCtl ctl, int cutoffPage, bool doDeletions)
|
||||
if (cldir == NULL)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not open directory \"%s\": %m", ctl->Dir)));
|
||||
errmsg("could not open directory \"%s\": %m", ctl->Dir)));
|
||||
|
||||
errno = 0;
|
||||
while ((clde = readdir(cldir)) != NULL)
|
||||
@ -898,7 +902,7 @@ SlruScanDirectory(SlruCtl ctl, int cutoffPage, bool doDeletions)
|
||||
if (errno)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not read directory \"%s\": %m", ctl->Dir)));
|
||||
errmsg("could not read directory \"%s\": %m", ctl->Dir)));
|
||||
closedir(cldir);
|
||||
|
||||
return found;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.149 2003/07/21 20:29:39 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.150 2003/08/04 00:43:15 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Transaction aborts can now occur two ways:
|
||||
@ -92,7 +92,7 @@
|
||||
* AbortTransactionBlock
|
||||
*
|
||||
* These are invoked only in response to a user "BEGIN WORK", "COMMIT",
|
||||
* or "ROLLBACK" command. The tricky part about these functions
|
||||
* or "ROLLBACK" command. The tricky part about these functions
|
||||
* is that they are called within the postgres main loop, in between
|
||||
* the StartTransactionCommand() and CommitTransactionCommand().
|
||||
*
|
||||
@ -197,8 +197,8 @@ static TransactionStateData CurrentTransactionStateData = {
|
||||
0, /* scan command id */
|
||||
0x0, /* start time */
|
||||
TRANS_DEFAULT, /* transaction state */
|
||||
TBLOCK_DEFAULT /* transaction block state from
|
||||
the client perspective */
|
||||
TBLOCK_DEFAULT /* transaction block state from the client
|
||||
* perspective */
|
||||
};
|
||||
|
||||
TransactionState CurrentTransactionState = &CurrentTransactionStateData;
|
||||
@ -359,7 +359,7 @@ GetCurrentTransactionStartTimeUsec(int *msec)
|
||||
* TransactionIdIsCurrentTransactionId
|
||||
*
|
||||
* During bootstrap, we cheat and say "it's not my transaction ID" even though
|
||||
* it is. Along with transam.c's cheat to say that the bootstrap XID is
|
||||
* it is. Along with transam.c's cheat to say that the bootstrap XID is
|
||||
* already committed, this causes the tqual.c routines to see previously
|
||||
* inserted tuples as committed, which is what we need during bootstrap.
|
||||
*/
|
||||
@ -561,13 +561,13 @@ RecordTransactionCommit(void)
|
||||
|
||||
/*
|
||||
* We must mark the transaction committed in clog if its XID
|
||||
* appears either in permanent rels or in local temporary rels.
|
||||
* We test this by seeing if we made transaction-controlled
|
||||
* entries *OR* local-rel tuple updates. Note that if we made
|
||||
* only the latter, we have not emitted an XLOG record for our
|
||||
* commit, and so in the event of a crash the clog update might be
|
||||
* lost. This is okay because no one else will ever care whether
|
||||
* we committed.
|
||||
* appears either in permanent rels or in local temporary rels. We
|
||||
* test this by seeing if we made transaction-controlled entries
|
||||
* *OR* local-rel tuple updates. Note that if we made only the
|
||||
* latter, we have not emitted an XLOG record for our commit, and
|
||||
* so in the event of a crash the clog update might be lost. This
|
||||
* is okay because no one else will ever care whether we
|
||||
* committed.
|
||||
*/
|
||||
if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
|
||||
TransactionIdCommit(xid);
|
||||
@ -755,9 +755,9 @@ AtAbort_Memory(void)
|
||||
{
|
||||
/*
|
||||
* Make sure we are in a valid context (not a child of
|
||||
* TopTransactionContext...). Note that it is possible for this
|
||||
* code to be called when we aren't in a transaction at all; go
|
||||
* directly to TopMemoryContext in that case.
|
||||
* TopTransactionContext...). Note that it is possible for this code
|
||||
* to be called when we aren't in a transaction at all; go directly to
|
||||
* TopMemoryContext in that case.
|
||||
*/
|
||||
if (TopTransactionContext != NULL)
|
||||
{
|
||||
@ -891,8 +891,8 @@ CommitTransaction(void)
|
||||
DeferredTriggerEndXact();
|
||||
|
||||
/*
|
||||
* Similarly, let ON COMMIT management do its thing before we start
|
||||
* to commit.
|
||||
* Similarly, let ON COMMIT management do its thing before we start to
|
||||
* commit.
|
||||
*/
|
||||
PreCommit_on_commit_actions();
|
||||
|
||||
@ -953,10 +953,10 @@ CommitTransaction(void)
|
||||
* noncritical resource releasing.
|
||||
*
|
||||
* The ordering of operations is not entirely random. The idea is:
|
||||
* release resources visible to other backends (eg, files, buffer pins);
|
||||
* then release locks; then release backend-local resources. We want
|
||||
* to release locks at the point where any backend waiting for us will
|
||||
* see our transaction as being fully cleaned up.
|
||||
* release resources visible to other backends (eg, files, buffer
|
||||
* pins); then release locks; then release backend-local resources.
|
||||
* We want to release locks at the point where any backend waiting for
|
||||
* us will see our transaction as being fully cleaned up.
|
||||
*/
|
||||
|
||||
smgrDoPendingDeletes(true);
|
||||
@ -1064,7 +1064,7 @@ AbortTransaction(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Post-abort cleanup. See notes in CommitTransaction() concerning
|
||||
* Post-abort cleanup. See notes in CommitTransaction() concerning
|
||||
* ordering.
|
||||
*/
|
||||
|
||||
@ -1194,8 +1194,8 @@ StartTransactionCommand(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* We must switch to TopTransactionContext before returning. This
|
||||
* is already done if we called StartTransaction, otherwise not.
|
||||
* We must switch to TopTransactionContext before returning. This is
|
||||
* already done if we called StartTransaction, otherwise not.
|
||||
*/
|
||||
Assert(TopTransactionContext != NULL);
|
||||
MemoryContextSwitchTo(TopTransactionContext);
|
||||
@ -1370,9 +1370,10 @@ PreventTransactionChain(void *stmtNode, const char *stmtType)
|
||||
if (IsTransactionBlock())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
|
||||
/* translator: %s represents an SQL statement name */
|
||||
/* translator: %s represents an SQL statement name */
|
||||
errmsg("%s cannot run inside a transaction block",
|
||||
stmtType)));
|
||||
|
||||
/*
|
||||
* Are we inside a function call? If the statement's parameter block
|
||||
* was allocated in QueryContext, assume it is an interactive command.
|
||||
@ -1381,8 +1382,8 @@ PreventTransactionChain(void *stmtNode, const char *stmtType)
|
||||
if (!MemoryContextContains(QueryContext, stmtNode))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
|
||||
/* translator: %s represents an SQL statement name */
|
||||
errmsg("%s cannot be executed from a function", stmtType)));
|
||||
/* translator: %s represents an SQL statement name */
|
||||
errmsg("%s cannot be executed from a function", stmtType)));
|
||||
/* If we got past IsTransactionBlock test, should be in default state */
|
||||
if (CurrentTransactionState->blockState != TBLOCK_DEFAULT)
|
||||
elog(ERROR, "cannot prevent transaction chain");
|
||||
@ -1414,6 +1415,7 @@ RequireTransactionChain(void *stmtNode, const char *stmtType)
|
||||
*/
|
||||
if (IsTransactionBlock())
|
||||
return;
|
||||
|
||||
/*
|
||||
* Are we inside a function call? If the statement's parameter block
|
||||
* was allocated in QueryContext, assume it is an interactive command.
|
||||
@ -1423,7 +1425,7 @@ RequireTransactionChain(void *stmtNode, const char *stmtType)
|
||||
return;
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
|
||||
/* translator: %s represents an SQL statement name */
|
||||
/* translator: %s represents an SQL statement name */
|
||||
errmsg("%s may only be used in BEGIN/END transaction blocks",
|
||||
stmtType)));
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.120 2003/07/28 00:09:14 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.121 2003/08/04 00:43:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1046,8 +1046,8 @@ XLogWrite(XLogwrtRqst WriteRqst)
|
||||
if (close(openLogFile) != 0)
|
||||
ereport(PANIC,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("close of log file %u, segment %u failed: %m",
|
||||
openLogId, openLogSeg)));
|
||||
errmsg("close of log file %u, segment %u failed: %m",
|
||||
openLogId, openLogSeg)));
|
||||
openLogFile = -1;
|
||||
}
|
||||
XLByteToPrevSeg(LogwrtResult.Write, openLogId, openLogSeg);
|
||||
@ -1162,8 +1162,8 @@ XLogWrite(XLogwrtRqst WriteRqst)
|
||||
if (close(openLogFile) != 0)
|
||||
ereport(PANIC,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("close of log file %u, segment %u failed: %m",
|
||||
openLogId, openLogSeg)));
|
||||
errmsg("close of log file %u, segment %u failed: %m",
|
||||
openLogId, openLogSeg)));
|
||||
openLogFile = -1;
|
||||
}
|
||||
if (openLogFile < 0)
|
||||
@ -1266,7 +1266,7 @@ XLogFlush(XLogRecPtr record)
|
||||
XLogCtlInsert *Insert = &XLogCtl->Insert;
|
||||
uint32 freespace = INSERT_FREESPACE(Insert);
|
||||
|
||||
if (freespace < SizeOfXLogRecord) /* buffer is full */
|
||||
if (freespace < SizeOfXLogRecord) /* buffer is full */
|
||||
WriteRqstPtr = XLogCtl->xlblocks[Insert->curridx];
|
||||
else
|
||||
{
|
||||
@ -1449,8 +1449,8 @@ XLogFileInit(uint32 log, uint32 seg,
|
||||
if (fd < 0)
|
||||
ereport(PANIC,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("open of \"%s\" (log file %u, segment %u) failed: %m",
|
||||
path, log, seg)));
|
||||
errmsg("open of \"%s\" (log file %u, segment %u) failed: %m",
|
||||
path, log, seg)));
|
||||
|
||||
return (fd);
|
||||
}
|
||||
@ -1563,14 +1563,14 @@ XLogFileOpen(uint32 log, uint32 seg, bool econt)
|
||||
{
|
||||
ereport(LOG,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("open of \"%s\" (log file %u, segment %u) failed: %m",
|
||||
path, log, seg)));
|
||||
errmsg("open of \"%s\" (log file %u, segment %u) failed: %m",
|
||||
path, log, seg)));
|
||||
return (fd);
|
||||
}
|
||||
ereport(PANIC,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("open of \"%s\" (log file %u, segment %u) failed: %m",
|
||||
path, log, seg)));
|
||||
errmsg("open of \"%s\" (log file %u, segment %u) failed: %m",
|
||||
path, log, seg)));
|
||||
}
|
||||
|
||||
return (fd);
|
||||
@ -1621,8 +1621,8 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr)
|
||||
if (xldir == NULL)
|
||||
ereport(PANIC,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not open transaction log directory \"%s\": %m",
|
||||
XLogDir)));
|
||||
errmsg("could not open transaction log directory \"%s\": %m",
|
||||
XLogDir)));
|
||||
|
||||
sprintf(lastoff, "%08X%08X", log, seg);
|
||||
|
||||
@ -1654,15 +1654,15 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr)
|
||||
true))
|
||||
{
|
||||
ereport(LOG,
|
||||
(errmsg("recycled transaction log file \"%s\"",
|
||||
xlde->d_name)));
|
||||
(errmsg("recycled transaction log file \"%s\"",
|
||||
xlde->d_name)));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No need for any more future segments... */
|
||||
ereport(LOG,
|
||||
(errmsg("removing transaction log file \"%s\"",
|
||||
xlde->d_name)));
|
||||
(errmsg("removing transaction log file \"%s\"",
|
||||
xlde->d_name)));
|
||||
unlink(path);
|
||||
}
|
||||
}
|
||||
@ -1672,8 +1672,8 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr)
|
||||
if (errno)
|
||||
ereport(PANIC,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not read transaction log directory \"%s\": %m",
|
||||
XLogDir)));
|
||||
errmsg("could not read transaction log directory \"%s\": %m",
|
||||
XLogDir)));
|
||||
closedir(xldir);
|
||||
}
|
||||
|
||||
@ -1746,8 +1746,8 @@ RecordIsValid(XLogRecord *record, XLogRecPtr recptr, int emode)
|
||||
if (!EQ_CRC64(record->xl_crc, crc))
|
||||
{
|
||||
ereport(emode,
|
||||
(errmsg("bad resource manager data checksum in record at %X/%X",
|
||||
recptr.xlogid, recptr.xrecoff)));
|
||||
(errmsg("bad resource manager data checksum in record at %X/%X",
|
||||
recptr.xlogid, recptr.xrecoff)));
|
||||
return (false);
|
||||
}
|
||||
|
||||
@ -1769,8 +1769,8 @@ RecordIsValid(XLogRecord *record, XLogRecPtr recptr, int emode)
|
||||
if (!EQ_CRC64(cbuf, crc))
|
||||
{
|
||||
ereport(emode,
|
||||
(errmsg("bad checksum of backup block %d in record at %X/%X",
|
||||
i + 1, recptr.xlogid, recptr.xrecoff)));
|
||||
(errmsg("bad checksum of backup block %d in record at %X/%X",
|
||||
i + 1, recptr.xlogid, recptr.xrecoff)));
|
||||
return (false);
|
||||
}
|
||||
blk += sizeof(BkpBlock) + BLCKSZ;
|
||||
@ -1931,7 +1931,7 @@ got_record:;
|
||||
{
|
||||
ereport(emode,
|
||||
(errmsg("invalid resource manager id %u at %X/%X",
|
||||
record->xl_rmid, RecPtr->xlogid, RecPtr->xrecoff)));
|
||||
record->xl_rmid, RecPtr->xlogid, RecPtr->xrecoff)));
|
||||
goto next_record_is_invalid;
|
||||
}
|
||||
nextRecord = NULL;
|
||||
@ -2063,7 +2063,7 @@ ValidXLOGHeader(XLogPageHeader hdr, int emode, bool checkSUI)
|
||||
{
|
||||
ereport(emode,
|
||||
(errmsg("unexpected pageaddr %X/%X in log file %u, segment %u, offset %u",
|
||||
hdr->xlp_pageaddr.xlogid, hdr->xlp_pageaddr.xrecoff,
|
||||
hdr->xlp_pageaddr.xlogid, hdr->xlp_pageaddr.xrecoff,
|
||||
readId, readSeg, readOff)));
|
||||
return false;
|
||||
}
|
||||
@ -2084,7 +2084,7 @@ ValidXLOGHeader(XLogPageHeader hdr, int emode, bool checkSUI)
|
||||
hdr->xlp_sui > lastReadSUI + 512)
|
||||
{
|
||||
ereport(emode,
|
||||
/* translator: SUI = startup id */
|
||||
/* translator: SUI = startup id */
|
||||
(errmsg("out-of-sequence SUI %u (after %u) in log file %u, segment %u, offset %u",
|
||||
hdr->xlp_sui, lastReadSUI,
|
||||
readId, readSeg, readOff)));
|
||||
@ -2235,8 +2235,8 @@ ReadControlFile(void)
|
||||
ereport(FATAL,
|
||||
(errmsg("database files are incompatible with server"),
|
||||
errdetail("The database cluster was initialized with PG_CONTROL_VERSION %d,"
|
||||
" but the server was compiled with PG_CONTROL_VERSION %d.",
|
||||
ControlFile->pg_control_version, PG_CONTROL_VERSION),
|
||||
" but the server was compiled with PG_CONTROL_VERSION %d.",
|
||||
ControlFile->pg_control_version, PG_CONTROL_VERSION),
|
||||
errhint("It looks like you need to initdb.")));
|
||||
/* Now check the CRC. */
|
||||
INIT_CRC64(crc);
|
||||
@ -2265,75 +2265,75 @@ ReadControlFile(void)
|
||||
ereport(FATAL,
|
||||
(errmsg("database files are incompatible with server"),
|
||||
errdetail("The database cluster was initialized with CATALOG_VERSION_NO %d,"
|
||||
" but the server was compiled with CATALOG_VERSION_NO %d.",
|
||||
ControlFile->catalog_version_no, CATALOG_VERSION_NO),
|
||||
" but the server was compiled with CATALOG_VERSION_NO %d.",
|
||||
ControlFile->catalog_version_no, CATALOG_VERSION_NO),
|
||||
errhint("It looks like you need to initdb.")));
|
||||
if (ControlFile->blcksz != BLCKSZ)
|
||||
ereport(FATAL,
|
||||
(errmsg("database files are incompatible with server"),
|
||||
errdetail("The database cluster was initialized with BLCKSZ %d,"
|
||||
" but the server was compiled with BLCKSZ %d.",
|
||||
ControlFile->blcksz, BLCKSZ),
|
||||
errhint("It looks like you need to recompile or initdb.")));
|
||||
errdetail("The database cluster was initialized with BLCKSZ %d,"
|
||||
" but the server was compiled with BLCKSZ %d.",
|
||||
ControlFile->blcksz, BLCKSZ),
|
||||
errhint("It looks like you need to recompile or initdb.")));
|
||||
if (ControlFile->relseg_size != RELSEG_SIZE)
|
||||
ereport(FATAL,
|
||||
(errmsg("database files are incompatible with server"),
|
||||
errdetail("The database cluster was initialized with RELSEG_SIZE %d,"
|
||||
" but the server was compiled with RELSEG_SIZE %d.",
|
||||
" but the server was compiled with RELSEG_SIZE %d.",
|
||||
ControlFile->relseg_size, RELSEG_SIZE),
|
||||
errhint("It looks like you need to recompile or initdb.")));
|
||||
errhint("It looks like you need to recompile or initdb.")));
|
||||
if (ControlFile->nameDataLen != NAMEDATALEN)
|
||||
ereport(FATAL,
|
||||
(errmsg("database files are incompatible with server"),
|
||||
errdetail("The database cluster was initialized with NAMEDATALEN %d,"
|
||||
" but the server was compiled with NAMEDATALEN %d.",
|
||||
" but the server was compiled with NAMEDATALEN %d.",
|
||||
ControlFile->nameDataLen, NAMEDATALEN),
|
||||
errhint("It looks like you need to recompile or initdb.")));
|
||||
errhint("It looks like you need to recompile or initdb.")));
|
||||
if (ControlFile->funcMaxArgs != FUNC_MAX_ARGS)
|
||||
ereport(FATAL,
|
||||
(errmsg("database files are incompatible with server"),
|
||||
errdetail("The database cluster was initialized with FUNC_MAX_ARGS %d,"
|
||||
" but the server was compiled with FUNC_MAX_ARGS %d.",
|
||||
" but the server was compiled with FUNC_MAX_ARGS %d.",
|
||||
ControlFile->funcMaxArgs, FUNC_MAX_ARGS),
|
||||
errhint("It looks like you need to recompile or initdb.")));
|
||||
errhint("It looks like you need to recompile or initdb.")));
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
if (ControlFile->enableIntTimes != TRUE)
|
||||
ereport(FATAL,
|
||||
(errmsg("database files are incompatible with server"),
|
||||
errdetail("The database cluster was initialized without HAVE_INT64_TIMESTAMP"
|
||||
" but the server was compiled with HAVE_INT64_TIMESTAMP."),
|
||||
errhint("It looks like you need to recompile or initdb.")));
|
||||
" but the server was compiled with HAVE_INT64_TIMESTAMP."),
|
||||
errhint("It looks like you need to recompile or initdb.")));
|
||||
#else
|
||||
if (ControlFile->enableIntTimes != FALSE)
|
||||
ereport(FATAL,
|
||||
(errmsg("database files are incompatible with server"),
|
||||
errdetail("The database cluster was initialized with HAVE_INT64_TIMESTAMP"
|
||||
" but the server was compiled without HAVE_INT64_TIMESTAMP."),
|
||||
errhint("It looks like you need to recompile or initdb.")));
|
||||
" but the server was compiled without HAVE_INT64_TIMESTAMP."),
|
||||
errhint("It looks like you need to recompile or initdb.")));
|
||||
#endif
|
||||
|
||||
if (ControlFile->localeBuflen != LOCALE_NAME_BUFLEN)
|
||||
ereport(FATAL,
|
||||
(errmsg("database files are incompatible with server"),
|
||||
errdetail("The database cluster was initialized with LOCALE_NAME_BUFLEN %d,"
|
||||
" but the server was compiled with LOCALE_NAME_BUFLEN %d.",
|
||||
" but the server was compiled with LOCALE_NAME_BUFLEN %d.",
|
||||
ControlFile->localeBuflen, LOCALE_NAME_BUFLEN),
|
||||
errhint("It looks like you need to recompile or initdb.")));
|
||||
errhint("It looks like you need to recompile or initdb.")));
|
||||
if (setlocale(LC_COLLATE, ControlFile->lc_collate) == NULL)
|
||||
ereport(FATAL,
|
||||
(errmsg("database files are incompatible with operating system"),
|
||||
errdetail("The database cluster was initialized with LC_COLLATE \"%s\","
|
||||
" which is not recognized by setlocale().",
|
||||
ControlFile->lc_collate),
|
||||
errhint("It looks like you need to initdb or install locale support.")));
|
||||
(errmsg("database files are incompatible with operating system"),
|
||||
errdetail("The database cluster was initialized with LC_COLLATE \"%s\","
|
||||
" which is not recognized by setlocale().",
|
||||
ControlFile->lc_collate),
|
||||
errhint("It looks like you need to initdb or install locale support.")));
|
||||
if (setlocale(LC_CTYPE, ControlFile->lc_ctype) == NULL)
|
||||
ereport(FATAL,
|
||||
(errmsg("database files are incompatible with operating system"),
|
||||
errdetail("The database cluster was initialized with LC_CTYPE \"%s\","
|
||||
" which is not recognized by setlocale().",
|
||||
ControlFile->lc_ctype),
|
||||
errhint("It looks like you need to initdb or install locale support.")));
|
||||
(errmsg("database files are incompatible with operating system"),
|
||||
errdetail("The database cluster was initialized with LC_CTYPE \"%s\","
|
||||
" which is not recognized by setlocale().",
|
||||
ControlFile->lc_ctype),
|
||||
errhint("It looks like you need to initdb or install locale support.")));
|
||||
|
||||
/* Make the fixed locale settings visible as GUC variables, too */
|
||||
SetConfigOption("lc_collate", ControlFile->lc_collate,
|
||||
@ -2602,10 +2602,10 @@ StartupXLOG(void)
|
||||
str_time(ControlFile->time))));
|
||||
else if (ControlFile->state == DB_IN_RECOVERY)
|
||||
ereport(LOG,
|
||||
(errmsg("database system was interrupted while in recovery at %s",
|
||||
str_time(ControlFile->time)),
|
||||
errhint("This probably means that some data is corrupted and"
|
||||
" you will have to use the last backup for recovery.")));
|
||||
(errmsg("database system was interrupted while in recovery at %s",
|
||||
str_time(ControlFile->time)),
|
||||
errhint("This probably means that some data is corrupted and"
|
||||
" you will have to use the last backup for recovery.")));
|
||||
else if (ControlFile->state == DB_IN_PRODUCTION)
|
||||
ereport(LOG,
|
||||
(errmsg("database system was interrupted at %s",
|
||||
@ -2637,12 +2637,12 @@ StartupXLOG(void)
|
||||
checkPointLoc = ControlFile->prevCheckPoint;
|
||||
ereport(LOG,
|
||||
(errmsg("using previous checkpoint record at %X/%X",
|
||||
checkPointLoc.xlogid, checkPointLoc.xrecoff)));
|
||||
checkPointLoc.xlogid, checkPointLoc.xrecoff)));
|
||||
InRecovery = true; /* force recovery even if SHUTDOWNED */
|
||||
}
|
||||
else
|
||||
ereport(PANIC,
|
||||
(errmsg("could not locate a valid checkpoint record")));
|
||||
(errmsg("could not locate a valid checkpoint record")));
|
||||
}
|
||||
LastRec = RecPtr = checkPointLoc;
|
||||
memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
|
||||
@ -2665,11 +2665,12 @@ StartupXLOG(void)
|
||||
ShmemVariableCache->oidCount = 0;
|
||||
|
||||
/*
|
||||
* If it was a shutdown checkpoint, then any following WAL entries were
|
||||
* created under the next StartUpID; if it was a regular checkpoint then
|
||||
* any following WAL entries were created under the same StartUpID.
|
||||
* We must replay WAL entries using the same StartUpID they were created
|
||||
* under, so temporarily adopt that SUI (see also xlog_redo()).
|
||||
* If it was a shutdown checkpoint, then any following WAL entries
|
||||
* were created under the next StartUpID; if it was a regular
|
||||
* checkpoint then any following WAL entries were created under the
|
||||
* same StartUpID. We must replay WAL entries using the same StartUpID
|
||||
* they were created under, so temporarily adopt that SUI (see also
|
||||
* xlog_redo()).
|
||||
*/
|
||||
if (wasShutdown)
|
||||
ThisStartUpID = checkPoint.ThisStartUpID + 1;
|
||||
@ -2690,7 +2691,7 @@ StartupXLOG(void)
|
||||
{
|
||||
if (wasShutdown)
|
||||
ereport(PANIC,
|
||||
(errmsg("invalid redo/undo record in shutdown checkpoint")));
|
||||
(errmsg("invalid redo/undo record in shutdown checkpoint")));
|
||||
InRecovery = true;
|
||||
}
|
||||
else if (ControlFile->state != DB_SHUTDOWNED)
|
||||
@ -2699,7 +2700,7 @@ StartupXLOG(void)
|
||||
/* REDO */
|
||||
if (InRecovery)
|
||||
{
|
||||
int rmid;
|
||||
int rmid;
|
||||
|
||||
ereport(LOG,
|
||||
(errmsg("database system was not properly shut down; "
|
||||
@ -2791,8 +2792,8 @@ StartupXLOG(void)
|
||||
|
||||
/*
|
||||
* Tricky point here: readBuf contains the *last* block that the
|
||||
* LastRec record spans, not the one it starts in. The last block
|
||||
* is indeed the one we want to use.
|
||||
* LastRec record spans, not the one it starts in. The last block is
|
||||
* indeed the one we want to use.
|
||||
*/
|
||||
Assert(readOff == (XLogCtl->xlblocks[0].xrecoff - BLCKSZ) % XLogSegSize);
|
||||
memcpy((char *) Insert->currpage, readBuf, BLCKSZ);
|
||||
@ -2818,11 +2819,12 @@ StartupXLOG(void)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Whenever Write.LogwrtResult points to exactly the end of a page,
|
||||
* Write.curridx must point to the *next* page (see XLogWrite()).
|
||||
* Whenever Write.LogwrtResult points to exactly the end of a
|
||||
* page, Write.curridx must point to the *next* page (see
|
||||
* XLogWrite()).
|
||||
*
|
||||
* Note: it might seem we should do AdvanceXLInsertBuffer() here,
|
||||
* but we can't since we haven't yet determined the correct StartUpID
|
||||
* Note: it might seem we should do AdvanceXLInsertBuffer() here, but
|
||||
* we can't since we haven't yet determined the correct StartUpID
|
||||
* to put into the new page's header. The first actual attempt to
|
||||
* insert a log record will advance the insert state.
|
||||
*/
|
||||
@ -2859,7 +2861,7 @@ StartupXLOG(void)
|
||||
|
||||
if (InRecovery)
|
||||
{
|
||||
int rmid;
|
||||
int rmid;
|
||||
|
||||
/*
|
||||
* Allow resource managers to do any required cleanup.
|
||||
@ -2885,14 +2887,15 @@ StartupXLOG(void)
|
||||
ThisStartUpID = ControlFile->checkPointCopy.ThisStartUpID;
|
||||
|
||||
/*
|
||||
* Perform a new checkpoint to update our recovery activity to disk.
|
||||
* Perform a new checkpoint to update our recovery activity to
|
||||
* disk.
|
||||
*
|
||||
* Note that we write a shutdown checkpoint. This is correct since
|
||||
* the records following it will use SUI one more than what is shown
|
||||
* in the checkpoint's ThisStartUpID.
|
||||
* the records following it will use SUI one more than what is
|
||||
* shown in the checkpoint's ThisStartUpID.
|
||||
*
|
||||
* In case we had to use the secondary checkpoint, make sure that
|
||||
* it will still be shown as the secondary checkpoint after this
|
||||
* In case we had to use the secondary checkpoint, make sure that it
|
||||
* will still be shown as the secondary checkpoint after this
|
||||
* CreateCheckPoint operation; we don't want the broken primary
|
||||
* checkpoint to become prevCheckPoint...
|
||||
*/
|
||||
@ -2907,10 +2910,10 @@ StartupXLOG(void)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If we are not doing recovery, then we saw a checkpoint with nothing
|
||||
* after it, and we can safely use StartUpID equal to one more than
|
||||
* the checkpoint's SUI. But just for paranoia's sake, check against
|
||||
* pg_control too.
|
||||
* If we are not doing recovery, then we saw a checkpoint with
|
||||
* nothing after it, and we can safely use StartUpID equal to one
|
||||
* more than the checkpoint's SUI. But just for paranoia's sake,
|
||||
* check against pg_control too.
|
||||
*/
|
||||
ThisStartUpID = checkPoint.ThisStartUpID;
|
||||
if (ThisStartUpID < ControlFile->checkPointCopy.ThisStartUpID)
|
||||
@ -2923,7 +2926,8 @@ StartupXLOG(void)
|
||||
PreallocXlogFiles(EndOfLog);
|
||||
|
||||
/*
|
||||
* Advance StartUpID to one more than the highest value used previously.
|
||||
* Advance StartUpID to one more than the highest value used
|
||||
* previously.
|
||||
*/
|
||||
ThisStartUpID++;
|
||||
XLogCtl->ThisStartUpID = ThisStartUpID;
|
||||
@ -2973,9 +2977,9 @@ ReadCheckpointRecord(XLogRecPtr RecPtr,
|
||||
if (!XRecOffIsValid(RecPtr.xrecoff))
|
||||
{
|
||||
ereport(LOG,
|
||||
/* translator: %s is "primary" or "secondary" */
|
||||
/* translator: %s is "primary" or "secondary" */
|
||||
(errmsg("invalid %s checkpoint link in control file",
|
||||
(whichChkpt == 1) ? gettext("primary") : gettext("secondary"))));
|
||||
(whichChkpt == 1) ? gettext("primary") : gettext("secondary"))));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -2984,34 +2988,34 @@ ReadCheckpointRecord(XLogRecPtr RecPtr,
|
||||
if (record == NULL)
|
||||
{
|
||||
ereport(LOG,
|
||||
/* translator: %s is "primary" or "secondary" */
|
||||
/* translator: %s is "primary" or "secondary" */
|
||||
(errmsg("invalid %s checkpoint record",
|
||||
(whichChkpt == 1) ? gettext("primary") : gettext("secondary"))));
|
||||
(whichChkpt == 1) ? gettext("primary") : gettext("secondary"))));
|
||||
return NULL;
|
||||
}
|
||||
if (record->xl_rmid != RM_XLOG_ID)
|
||||
{
|
||||
ereport(LOG,
|
||||
/* translator: %s is "primary" or "secondary" */
|
||||
(errmsg("invalid resource manager id in %s checkpoint record",
|
||||
(whichChkpt == 1) ? gettext("primary") : gettext("secondary"))));
|
||||
/* translator: %s is "primary" or "secondary" */
|
||||
(errmsg("invalid resource manager id in %s checkpoint record",
|
||||
(whichChkpt == 1) ? gettext("primary") : gettext("secondary"))));
|
||||
return NULL;
|
||||
}
|
||||
if (record->xl_info != XLOG_CHECKPOINT_SHUTDOWN &&
|
||||
record->xl_info != XLOG_CHECKPOINT_ONLINE)
|
||||
{
|
||||
ereport(LOG,
|
||||
/* translator: %s is "primary" or "secondary" */
|
||||
/* translator: %s is "primary" or "secondary" */
|
||||
(errmsg("invalid xl_info in %s checkpoint record",
|
||||
(whichChkpt == 1) ? gettext("primary") : gettext("secondary"))));
|
||||
(whichChkpt == 1) ? gettext("primary") : gettext("secondary"))));
|
||||
return NULL;
|
||||
}
|
||||
if (record->xl_len != sizeof(CheckPoint))
|
||||
{
|
||||
ereport(LOG,
|
||||
/* translator: %s is "primary" or "secondary" */
|
||||
/* translator: %s is "primary" or "secondary" */
|
||||
(errmsg("invalid length of %s checkpoint record",
|
||||
(whichChkpt == 1) ? gettext("primary") : gettext("secondary"))));
|
||||
(whichChkpt == 1) ? gettext("primary") : gettext("secondary"))));
|
||||
return NULL;
|
||||
}
|
||||
return record;
|
||||
@ -3112,10 +3116,11 @@ CreateCheckPoint(bool shutdown, bool force)
|
||||
if (MyXactMadeXLogEntry)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
|
||||
errmsg("checkpoint cannot be made inside transaction block")));
|
||||
errmsg("checkpoint cannot be made inside transaction block")));
|
||||
|
||||
/*
|
||||
* Acquire CheckpointLock to ensure only one checkpoint happens at a time.
|
||||
* Acquire CheckpointLock to ensure only one checkpoint happens at a
|
||||
* time.
|
||||
*
|
||||
* The CheckpointLock can be held for quite a while, which is not good
|
||||
* because we won't respond to a cancel/die request while waiting for
|
||||
@ -3149,14 +3154,15 @@ CreateCheckPoint(bool shutdown, bool force)
|
||||
LWLockAcquire(WALInsertLock, LW_EXCLUSIVE);
|
||||
|
||||
/*
|
||||
* If this isn't a shutdown or forced checkpoint, and we have not inserted
|
||||
* any XLOG records since the start of the last checkpoint, skip the
|
||||
* checkpoint. The idea here is to avoid inserting duplicate checkpoints
|
||||
* when the system is idle. That wastes log space, and more importantly it
|
||||
* exposes us to possible loss of both current and previous checkpoint
|
||||
* records if the machine crashes just as we're writing the update.
|
||||
* (Perhaps it'd make even more sense to checkpoint only when the previous
|
||||
* checkpoint record is in a different xlog page?)
|
||||
* If this isn't a shutdown or forced checkpoint, and we have not
|
||||
* inserted any XLOG records since the start of the last checkpoint,
|
||||
* skip the checkpoint. The idea here is to avoid inserting duplicate
|
||||
* checkpoints when the system is idle. That wastes log space, and
|
||||
* more importantly it exposes us to possible loss of both current and
|
||||
* previous checkpoint records if the machine crashes just as we're
|
||||
* writing the update. (Perhaps it'd make even more sense to
|
||||
* checkpoint only when the previous checkpoint record is in a
|
||||
* different xlog page?)
|
||||
*
|
||||
* We have to make two tests to determine that nothing has happened since
|
||||
* the start of the last checkpoint: current insertion point must
|
||||
@ -3204,12 +3210,13 @@ CreateCheckPoint(bool shutdown, bool force)
|
||||
* Here we update the shared RedoRecPtr for future XLogInsert calls;
|
||||
* this must be done while holding the insert lock AND the info_lck.
|
||||
*
|
||||
* Note: if we fail to complete the checkpoint, RedoRecPtr will be
|
||||
* left pointing past where it really needs to point. This is okay;
|
||||
* the only consequence is that XLogInsert might back up whole buffers
|
||||
* that it didn't really need to. We can't postpone advancing RedoRecPtr
|
||||
* because XLogInserts that happen while we are dumping buffers must
|
||||
* assume that their buffer changes are not included in the checkpoint.
|
||||
* Note: if we fail to complete the checkpoint, RedoRecPtr will be left
|
||||
* pointing past where it really needs to point. This is okay; the
|
||||
* only consequence is that XLogInsert might back up whole buffers
|
||||
* that it didn't really need to. We can't postpone advancing
|
||||
* RedoRecPtr because XLogInserts that happen while we are dumping
|
||||
* buffers must assume that their buffer changes are not included in
|
||||
* the checkpoint.
|
||||
*/
|
||||
{
|
||||
/* use volatile pointer to prevent code rearrangement */
|
||||
@ -3538,15 +3545,15 @@ assign_xlog_sync_method(const char *method, bool doit, bool interactive)
|
||||
if (pg_fsync(openLogFile) != 0)
|
||||
ereport(PANIC,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("fsync of log file %u, segment %u failed: %m",
|
||||
openLogId, openLogSeg)));
|
||||
errmsg("fsync of log file %u, segment %u failed: %m",
|
||||
openLogId, openLogSeg)));
|
||||
if (open_sync_bit != new_sync_bit)
|
||||
{
|
||||
if (close(openLogFile) != 0)
|
||||
ereport(PANIC,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("close of log file %u, segment %u failed: %m",
|
||||
openLogId, openLogSeg)));
|
||||
errmsg("close of log file %u, segment %u failed: %m",
|
||||
openLogId, openLogSeg)));
|
||||
openLogFile = -1;
|
||||
}
|
||||
}
|
||||
@ -3570,16 +3577,16 @@ issue_xlog_fsync(void)
|
||||
if (pg_fsync(openLogFile) != 0)
|
||||
ereport(PANIC,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("fsync of log file %u, segment %u failed: %m",
|
||||
openLogId, openLogSeg)));
|
||||
errmsg("fsync of log file %u, segment %u failed: %m",
|
||||
openLogId, openLogSeg)));
|
||||
break;
|
||||
#ifdef HAVE_FDATASYNC
|
||||
case SYNC_METHOD_FDATASYNC:
|
||||
if (pg_fdatasync(openLogFile) != 0)
|
||||
ereport(PANIC,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("fdatasync of log file %u, segment %u failed: %m",
|
||||
openLogId, openLogSeg)));
|
||||
errmsg("fdatasync of log file %u, segment %u failed: %m",
|
||||
openLogId, openLogSeg)));
|
||||
break;
|
||||
#endif
|
||||
case SYNC_METHOD_OPEN:
|
||||
|
Reference in New Issue
Block a user