mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
pgindent run for 9.0
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.32 2010/01/22 16:40:18 rhaas Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.33 2010/02/26 02:00:32 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1210,7 +1210,7 @@ bytea *
|
||||
attribute_reloptions(Datum reloptions, bool validate)
|
||||
{
|
||||
relopt_value *options;
|
||||
AttributeOpts *aopts;
|
||||
AttributeOpts *aopts;
|
||||
int numoptions;
|
||||
static const relopt_parse_elt tab[] = {
|
||||
{"n_distinct", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct)},
|
||||
@@ -1241,7 +1241,7 @@ bytea *
|
||||
tablespace_reloptions(Datum reloptions, bool validate)
|
||||
{
|
||||
relopt_value *options;
|
||||
TableSpaceOpts *tsopts;
|
||||
TableSpaceOpts *tsopts;
|
||||
int numoptions;
|
||||
static const relopt_parse_elt tab[] = {
|
||||
{"random_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, random_page_cost)},
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* These functions provide conversion between rowtypes that are logically
|
||||
* equivalent but might have columns in a different order or different sets
|
||||
* of dropped columns. There is some overlap of functionality with the
|
||||
* of dropped columns. There is some overlap of functionality with the
|
||||
* executor's "junkfilter" routines, but these functions work on bare
|
||||
* HeapTuples rather than TupleTableSlots.
|
||||
*
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/common/tupconvert.c,v 1.3 2010/01/02 16:57:33 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/common/tupconvert.c,v 1.4 2010/02/26 02:00:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -88,7 +88,7 @@ convert_tuples_by_position(TupleDesc indesc,
|
||||
int32 atttypmod;
|
||||
|
||||
if (att->attisdropped)
|
||||
continue; /* attrMap[i] is already 0 */
|
||||
continue; /* attrMap[i] is already 0 */
|
||||
noutcols++;
|
||||
atttypid = att->atttypid;
|
||||
atttypmod = att->atttypmod;
|
||||
@@ -137,22 +137,22 @@ convert_tuples_by_position(TupleDesc indesc,
|
||||
nincols, noutcols)));
|
||||
|
||||
/*
|
||||
* Check to see if the map is one-to-one and the tuple types are the
|
||||
* same. (We check the latter because if they're not, we want to do
|
||||
* conversion to inject the right OID into the tuple datum.)
|
||||
* Check to see if the map is one-to-one and the tuple types are the same.
|
||||
* (We check the latter because if they're not, we want to do conversion
|
||||
* to inject the right OID into the tuple datum.)
|
||||
*/
|
||||
if (indesc->natts == outdesc->natts &&
|
||||
indesc->tdtypeid == outdesc->tdtypeid)
|
||||
{
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (attrMap[i] == (i+1))
|
||||
if (attrMap[i] == (i + 1))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If it's a dropped column and the corresponding input
|
||||
* column is also dropped, we needn't convert. However,
|
||||
* attlen and attalign must agree.
|
||||
* If it's a dropped column and the corresponding input column is
|
||||
* also dropped, we needn't convert. However, attlen and attalign
|
||||
* must agree.
|
||||
*/
|
||||
if (attrMap[i] == 0 &&
|
||||
indesc->attrs[i]->attisdropped &&
|
||||
@@ -182,10 +182,10 @@ convert_tuples_by_position(TupleDesc indesc,
|
||||
/* preallocate workspace for Datum arrays */
|
||||
map->outvalues = (Datum *) palloc(n * sizeof(Datum));
|
||||
map->outisnull = (bool *) palloc(n * sizeof(bool));
|
||||
n = indesc->natts + 1; /* +1 for NULL */
|
||||
n = indesc->natts + 1; /* +1 for NULL */
|
||||
map->invalues = (Datum *) palloc(n * sizeof(Datum));
|
||||
map->inisnull = (bool *) palloc(n * sizeof(bool));
|
||||
map->invalues[0] = (Datum) 0; /* set up the NULL entry */
|
||||
map->invalues[0] = (Datum) 0; /* set up the NULL entry */
|
||||
map->inisnull[0] = true;
|
||||
|
||||
return map;
|
||||
@@ -193,7 +193,7 @@ convert_tuples_by_position(TupleDesc indesc,
|
||||
|
||||
/*
|
||||
* Set up for tuple conversion, matching input and output columns by name.
|
||||
* (Dropped columns are ignored in both input and output.) This is intended
|
||||
* (Dropped columns are ignored in both input and output.) This is intended
|
||||
* for use when the rowtypes are related by inheritance, so we expect an exact
|
||||
* match of both type and typmod. The error messages will be a bit unhelpful
|
||||
* unless both rowtypes are named composite types.
|
||||
@@ -221,7 +221,7 @@ convert_tuples_by_name(TupleDesc indesc,
|
||||
int j;
|
||||
|
||||
if (att->attisdropped)
|
||||
continue; /* attrMap[i] is already 0 */
|
||||
continue; /* attrMap[i] is already 0 */
|
||||
attname = NameStr(att->attname);
|
||||
atttypid = att->atttypid;
|
||||
atttypmod = att->atttypmod;
|
||||
@@ -256,9 +256,9 @@ convert_tuples_by_name(TupleDesc indesc,
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the map is one-to-one and the tuple types are the
|
||||
* same. (We check the latter because if they're not, we want to do
|
||||
* conversion to inject the right OID into the tuple datum.)
|
||||
* Check to see if the map is one-to-one and the tuple types are the same.
|
||||
* (We check the latter because if they're not, we want to do conversion
|
||||
* to inject the right OID into the tuple datum.)
|
||||
*/
|
||||
if (indesc->natts == outdesc->natts &&
|
||||
indesc->tdtypeid == outdesc->tdtypeid)
|
||||
@@ -266,13 +266,13 @@ convert_tuples_by_name(TupleDesc indesc,
|
||||
same = true;
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (attrMap[i] == (i+1))
|
||||
if (attrMap[i] == (i + 1))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If it's a dropped column and the corresponding input
|
||||
* column is also dropped, we needn't convert. However,
|
||||
* attlen and attalign must agree.
|
||||
* If it's a dropped column and the corresponding input column is
|
||||
* also dropped, we needn't convert. However, attlen and attalign
|
||||
* must agree.
|
||||
*/
|
||||
if (attrMap[i] == 0 &&
|
||||
indesc->attrs[i]->attisdropped &&
|
||||
@@ -302,10 +302,10 @@ convert_tuples_by_name(TupleDesc indesc,
|
||||
/* preallocate workspace for Datum arrays */
|
||||
map->outvalues = (Datum *) palloc(n * sizeof(Datum));
|
||||
map->outisnull = (bool *) palloc(n * sizeof(bool));
|
||||
n = indesc->natts + 1; /* +1 for NULL */
|
||||
n = indesc->natts + 1; /* +1 for NULL */
|
||||
map->invalues = (Datum *) palloc(n * sizeof(Datum));
|
||||
map->inisnull = (bool *) palloc(n * sizeof(bool));
|
||||
map->invalues[0] = (Datum) 0; /* set up the NULL entry */
|
||||
map->invalues[0] = (Datum) 0; /* set up the NULL entry */
|
||||
map->inisnull[0] = true;
|
||||
|
||||
return map;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/gin/ginbulk.c,v 1.18 2010/02/11 14:29:50 teodor Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/gin/ginbulk.c,v 1.19 2010/02/26 02:00:33 momjian Exp $
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -22,20 +22,20 @@
|
||||
#define DEF_NENTRY 2048
|
||||
#define DEF_NPTR 4
|
||||
|
||||
static void*
|
||||
static void *
|
||||
ginAppendData(void *old, void *new, void *arg)
|
||||
{
|
||||
EntryAccumulator *eo = (EntryAccumulator*)old,
|
||||
*en = (EntryAccumulator*)new;
|
||||
EntryAccumulator *eo = (EntryAccumulator *) old,
|
||||
*en = (EntryAccumulator *) new;
|
||||
|
||||
BuildAccumulator *accum = (BuildAccumulator*)arg;
|
||||
BuildAccumulator *accum = (BuildAccumulator *) arg;
|
||||
|
||||
if (eo->number >= eo->length)
|
||||
{
|
||||
accum->allocatedMemory -= GetMemoryChunkSpace(eo->list);
|
||||
eo->length *= 2;
|
||||
eo->list = (ItemPointerData *) repalloc(eo->list,
|
||||
sizeof(ItemPointerData) * eo->length);
|
||||
sizeof(ItemPointerData) * eo->length);
|
||||
accum->allocatedMemory += GetMemoryChunkSpace(eo->list);
|
||||
}
|
||||
|
||||
@@ -60,9 +60,9 @@ ginAppendData(void *old, void *new, void *arg)
|
||||
static int
|
||||
cmpEntryAccumulator(const void *a, const void *b, void *arg)
|
||||
{
|
||||
EntryAccumulator *ea = (EntryAccumulator*)a;
|
||||
EntryAccumulator *eb = (EntryAccumulator*)b;
|
||||
BuildAccumulator *accum = (BuildAccumulator*)arg;
|
||||
EntryAccumulator *ea = (EntryAccumulator *) a;
|
||||
EntryAccumulator *eb = (EntryAccumulator *) b;
|
||||
BuildAccumulator *accum = (BuildAccumulator *) arg;
|
||||
|
||||
return compareAttEntries(accum->ginstate, ea->attnum, ea->value,
|
||||
eb->attnum, eb->value);
|
||||
@@ -104,13 +104,13 @@ getDatumCopy(BuildAccumulator *accum, OffsetNumber attnum, Datum value)
|
||||
static void
|
||||
ginInsertEntry(BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum, Datum entry)
|
||||
{
|
||||
EntryAccumulator *key,
|
||||
*ea;
|
||||
EntryAccumulator *key,
|
||||
*ea;
|
||||
|
||||
/*
|
||||
* Allocate memory by rather big chunk to decrease overhead, we don't
|
||||
* keep pointer to previously allocated chunks because they will free
|
||||
* by MemoryContextReset() call.
|
||||
/*
|
||||
* Allocate memory by rather big chunk to decrease overhead, we don't keep
|
||||
* pointer to previously allocated chunks because they will free by
|
||||
* MemoryContextReset() call.
|
||||
*/
|
||||
if (accum->entryallocator == NULL || accum->length >= DEF_NENTRY)
|
||||
{
|
||||
@@ -125,7 +125,7 @@ ginInsertEntry(BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum
|
||||
|
||||
key->attnum = attnum;
|
||||
key->value = entry;
|
||||
/* To prevent multiple palloc/pfree cycles, we reuse array */
|
||||
/* To prevent multiple palloc/pfree cycles, we reuse array */
|
||||
if (accum->tmpList == NULL)
|
||||
accum->tmpList =
|
||||
(ItemPointerData *) palloc(sizeof(ItemPointerData) * DEF_NPTR);
|
||||
@@ -149,8 +149,8 @@ ginInsertEntry(BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum
|
||||
else
|
||||
{
|
||||
/*
|
||||
* The key has been appended, so "free" allocated
|
||||
* key by decrementing chunk's counter.
|
||||
* The key has been appended, so "free" allocated key by decrementing
|
||||
* chunk's counter.
|
||||
*/
|
||||
accum->length--;
|
||||
}
|
||||
@@ -162,7 +162,7 @@ ginInsertEntry(BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum
|
||||
* Since the entries are being inserted into a balanced binary tree, you
|
||||
* might think that the order of insertion wouldn't be critical, but it turns
|
||||
* out that inserting the entries in sorted order results in a lot of
|
||||
* rebalancing operations and is slow. To prevent this, we attempt to insert
|
||||
* rebalancing operations and is slow. To prevent this, we attempt to insert
|
||||
* the nodes in an order that will produce a nearly-balanced tree if the input
|
||||
* is in fact sorted.
|
||||
*
|
||||
@@ -172,11 +172,11 @@ ginInsertEntry(BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum
|
||||
* tree; then, we insert the middles of each half of out virtual array, then
|
||||
* middles of quarters, etc.
|
||||
*/
|
||||
void
|
||||
void
|
||||
ginInsertRecordBA(BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum,
|
||||
Datum *entries, int32 nentry)
|
||||
{
|
||||
uint32 step = nentry;
|
||||
uint32 step = nentry;
|
||||
|
||||
if (nentry <= 0)
|
||||
return;
|
||||
@@ -186,21 +186,22 @@ ginInsertRecordBA(BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber att
|
||||
/*
|
||||
* step will contain largest power of 2 and <= nentry
|
||||
*/
|
||||
step |= (step >> 1);
|
||||
step |= (step >> 2);
|
||||
step |= (step >> 4);
|
||||
step |= (step >> 8);
|
||||
step |= (step >> 1);
|
||||
step |= (step >> 2);
|
||||
step |= (step >> 4);
|
||||
step |= (step >> 8);
|
||||
step |= (step >> 16);
|
||||
step >>= 1;
|
||||
step ++;
|
||||
step++;
|
||||
|
||||
while(step > 0) {
|
||||
int i;
|
||||
while (step > 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = step - 1; i < nentry && i >= 0; i += step << 1 /* *2 */)
|
||||
for (i = step - 1; i < nentry && i >= 0; i += step << 1 /* *2 */ )
|
||||
ginInsertEntry(accum, heapptr, attnum, entries[i]);
|
||||
|
||||
step >>= 1; /* /2 */
|
||||
step >>= 1; /* /2 */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/gin/ginentrypage.c,v 1.23 2010/01/02 16:57:33 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/gin/ginentrypage.c,v 1.24 2010/02/26 02:00:33 momjian Exp $
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -104,7 +104,7 @@ GinFormTuple(Relation index, GinState *ginstate,
|
||||
* Gin tuple without any ItemPointers should be large enough to keep
|
||||
* one ItemPointer, to prevent inconsistency between
|
||||
* ginHeapTupleFastCollect and ginEntryInsert called by
|
||||
* ginHeapTupleInsert. ginHeapTupleFastCollect forms tuple without
|
||||
* ginHeapTupleInsert. ginHeapTupleFastCollect forms tuple without
|
||||
* extra pointer to heap, but ginEntryInsert (called for pending list
|
||||
* cleanup during vacuum) will form the same tuple with one
|
||||
* ItemPointer.
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/gin/ginget.c,v 1.29 2010/01/02 16:57:33 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/gin/ginget.c,v 1.30 2010/02/26 02:00:33 momjian Exp $
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -25,11 +25,11 @@
|
||||
|
||||
typedef struct pendingPosition
|
||||
{
|
||||
Buffer pendingBuffer;
|
||||
OffsetNumber firstOffset;
|
||||
OffsetNumber lastOffset;
|
||||
ItemPointerData item;
|
||||
bool *hasMatchKey;
|
||||
Buffer pendingBuffer;
|
||||
OffsetNumber firstOffset;
|
||||
OffsetNumber lastOffset;
|
||||
ItemPointerData item;
|
||||
bool *hasMatchKey;
|
||||
} pendingPosition;
|
||||
|
||||
|
||||
@@ -877,7 +877,7 @@ matchPartialInPendingList(GinState *ginstate, Page page,
|
||||
static bool
|
||||
hasAllMatchingKeys(GinScanOpaque so, pendingPosition *pos)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < so->nkeys; i++)
|
||||
if (pos->hasMatchKey[i] == false)
|
||||
@@ -912,7 +912,7 @@ collectDatumForItem(IndexScanDesc scan, pendingPosition *pos)
|
||||
|
||||
memset(key->entryRes, FALSE, key->nentries);
|
||||
}
|
||||
memset(pos->hasMatchKey, FALSE, so->nkeys);
|
||||
memset(pos->hasMatchKey, FALSE, so->nkeys);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.84 2010/01/02 16:57:34 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.85 2010/02/26 02:00:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -414,7 +414,8 @@ gistindex_keytest(IndexTuple tuple,
|
||||
/*
|
||||
* On non-leaf page we can't conclude that child hasn't NULL
|
||||
* values because of assumption in GiST: union (VAL, NULL) is VAL.
|
||||
* But if on non-leaf page key IS NULL, then all children are NULL.
|
||||
* But if on non-leaf page key IS NULL, then all children are
|
||||
* NULL.
|
||||
*/
|
||||
if (key->sk_flags & SK_SEARCHNULL)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.20 2010/01/14 16:31:09 teodor Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.21 2010/02/26 02:00:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -889,8 +889,8 @@ gist_point_compress(PG_FUNCTION_ARGS)
|
||||
|
||||
if (entry->leafkey) /* Point, actually */
|
||||
{
|
||||
BOX *box = palloc(sizeof(BOX));
|
||||
Point *point = DatumGetPointP(entry->key);
|
||||
BOX *box = palloc(sizeof(BOX));
|
||||
Point *point = DatumGetPointP(entry->key);
|
||||
GISTENTRY *retval = palloc(sizeof(GISTENTRY));
|
||||
|
||||
box->high = box->low = *point;
|
||||
@@ -906,9 +906,9 @@ gist_point_compress(PG_FUNCTION_ARGS)
|
||||
|
||||
static bool
|
||||
gist_point_consistent_internal(StrategyNumber strategy,
|
||||
bool isLeaf, BOX *key, Point *query)
|
||||
bool isLeaf, BOX *key, Point *query)
|
||||
{
|
||||
bool result = false;
|
||||
bool result = false;
|
||||
|
||||
switch (strategy)
|
||||
{
|
||||
@@ -953,10 +953,10 @@ Datum
|
||||
gist_point_consistent(PG_FUNCTION_ARGS)
|
||||
{
|
||||
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
|
||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||
bool result;
|
||||
bool *recheck = (bool *) PG_GETARG_POINTER(4);
|
||||
StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset;
|
||||
StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset;
|
||||
|
||||
switch (strategyGroup)
|
||||
{
|
||||
@@ -969,22 +969,22 @@ gist_point_consistent(PG_FUNCTION_ARGS)
|
||||
break;
|
||||
case BoxStrategyNumberGroup:
|
||||
result = DatumGetBool(DirectFunctionCall5(
|
||||
gist_box_consistent,
|
||||
PointerGetDatum(entry),
|
||||
PG_GETARG_DATUM(1),
|
||||
Int16GetDatum(RTOverlapStrategyNumber),
|
||||
0, PointerGetDatum(recheck)));
|
||||
gist_box_consistent,
|
||||
PointerGetDatum(entry),
|
||||
PG_GETARG_DATUM(1),
|
||||
Int16GetDatum(RTOverlapStrategyNumber),
|
||||
0, PointerGetDatum(recheck)));
|
||||
break;
|
||||
case PolygonStrategyNumberGroup:
|
||||
{
|
||||
POLYGON *query = PG_GETARG_POLYGON_P(1);
|
||||
|
||||
result = DatumGetBool(DirectFunctionCall5(
|
||||
gist_poly_consistent,
|
||||
PointerGetDatum(entry),
|
||||
PolygonPGetDatum(query),
|
||||
Int16GetDatum(RTOverlapStrategyNumber),
|
||||
0, PointerGetDatum(recheck)));
|
||||
gist_poly_consistent,
|
||||
PointerGetDatum(entry),
|
||||
PolygonPGetDatum(query),
|
||||
Int16GetDatum(RTOverlapStrategyNumber),
|
||||
0, PointerGetDatum(recheck)));
|
||||
|
||||
if (GIST_LEAF(entry) && result)
|
||||
{
|
||||
@@ -992,13 +992,13 @@ gist_point_consistent(PG_FUNCTION_ARGS)
|
||||
* We are on leaf page and quick check shows overlapping
|
||||
* of polygon's bounding box and point
|
||||
*/
|
||||
BOX *box = DatumGetBoxP(entry->key);
|
||||
BOX *box = DatumGetBoxP(entry->key);
|
||||
|
||||
Assert(box->high.x == box->low.x
|
||||
&& box->high.y == box->low.y);
|
||||
&& box->high.y == box->low.y);
|
||||
result = DatumGetBool(DirectFunctionCall2(
|
||||
poly_contain_pt,
|
||||
PolygonPGetDatum(query),
|
||||
poly_contain_pt,
|
||||
PolygonPGetDatum(query),
|
||||
PointPGetDatum(&box->high)));
|
||||
*recheck = false;
|
||||
}
|
||||
@@ -1006,14 +1006,14 @@ gist_point_consistent(PG_FUNCTION_ARGS)
|
||||
break;
|
||||
case CircleStrategyNumberGroup:
|
||||
{
|
||||
CIRCLE *query = PG_GETARG_CIRCLE_P(1);
|
||||
CIRCLE *query = PG_GETARG_CIRCLE_P(1);
|
||||
|
||||
result = DatumGetBool(DirectFunctionCall5(
|
||||
gist_circle_consistent,
|
||||
PointerGetDatum(entry),
|
||||
CirclePGetDatum(query),
|
||||
Int16GetDatum(RTOverlapStrategyNumber),
|
||||
0, PointerGetDatum(recheck)));
|
||||
gist_circle_consistent,
|
||||
PointerGetDatum(entry),
|
||||
CirclePGetDatum(query),
|
||||
Int16GetDatum(RTOverlapStrategyNumber),
|
||||
0, PointerGetDatum(recheck)));
|
||||
|
||||
if (GIST_LEAF(entry) && result)
|
||||
{
|
||||
@@ -1021,20 +1021,20 @@ gist_point_consistent(PG_FUNCTION_ARGS)
|
||||
* We are on leaf page and quick check shows overlapping
|
||||
* of polygon's bounding box and point
|
||||
*/
|
||||
BOX *box = DatumGetBoxP(entry->key);
|
||||
BOX *box = DatumGetBoxP(entry->key);
|
||||
|
||||
Assert(box->high.x == box->low.x
|
||||
&& box->high.y == box->low.y);
|
||||
&& box->high.y == box->low.y);
|
||||
result = DatumGetBool(DirectFunctionCall2(
|
||||
circle_contain_pt,
|
||||
CirclePGetDatum(query),
|
||||
circle_contain_pt,
|
||||
CirclePGetDatum(query),
|
||||
PointPGetDatum(&box->high)));
|
||||
*recheck = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
result = false; /* silence compiler warning */
|
||||
result = false; /* silence compiler warning */
|
||||
elog(ERROR, "unknown strategy number: %d", strategy);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistscan.c,v 1.78 2010/01/02 16:57:34 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistscan.c,v 1.79 2010/02/26 02:00:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -92,8 +92,8 @@ gistrescan(PG_FUNCTION_ARGS)
|
||||
* field.
|
||||
*
|
||||
* Next, if any of keys is a NULL and that key is not marked with
|
||||
* SK_SEARCHNULL/SK_SEARCHNOTNULL then nothing can be found (ie,
|
||||
* we assume all indexable operators are strict).
|
||||
* SK_SEARCHNULL/SK_SEARCHNOTNULL then nothing can be found (ie, we
|
||||
* assume all indexable operators are strict).
|
||||
*/
|
||||
for (i = 0; i < scan->numberOfKeys; i++)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.116 2010/01/02 16:57:34 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.117 2010/02/26 02:00:33 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* This file contains only the public interface routines.
|
||||
@@ -233,7 +233,7 @@ hashgettuple(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* An insertion into the current index page could have happened while
|
||||
* we didn't have read lock on it. Re-find our position by looking
|
||||
* for the TID we previously returned. (Because we hold share lock on
|
||||
* for the TID we previously returned. (Because we hold share lock on
|
||||
* the bucket, no deletions or splits could have occurred; therefore
|
||||
* we can expect that the TID still exists in the current index page,
|
||||
* at an offset >= where we were.)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashovfl.c,v 1.68 2010/01/02 16:57:34 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashovfl.c,v 1.69 2010/02/26 02:00:33 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Overflow pages look like ordinary relation pages.
|
||||
@@ -717,8 +717,8 @@ _hash_squeezebucket(Relation rel,
|
||||
|
||||
/*
|
||||
* If we reach here, there are no live tuples on the "read" page ---
|
||||
* it was empty when we got to it, or we moved them all. So we
|
||||
* can just free the page without bothering with deleting tuples
|
||||
* it was empty when we got to it, or we moved them all. So we can
|
||||
* just free the page without bothering with deleting tuples
|
||||
* individually. Then advance to the previous "read" page.
|
||||
*
|
||||
* Tricky point here: if our read and write pages are adjacent in the
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.82 2010/01/02 16:57:34 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.83 2010/02/26 02:00:33 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Postgres hash pages look like ordinary relation pages. The opaque
|
||||
@@ -799,8 +799,8 @@ _hash_splitbucket(Relation rel,
|
||||
/*
|
||||
* Partition the tuples in the old bucket between the old bucket and the
|
||||
* new bucket, advancing along the old bucket's overflow bucket chain and
|
||||
* adding overflow pages to the new bucket as needed. Outer loop
|
||||
* iterates once per page in old bucket.
|
||||
* adding overflow pages to the new bucket as needed. Outer loop iterates
|
||||
* once per page in old bucket.
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.287 2010/02/14 18:42:12 rhaas Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.288 2010/02/26 02:00:33 momjian Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@@ -79,8 +79,8 @@ static HeapScanDesc heap_beginscan_internal(Relation relation,
|
||||
bool allow_strat, bool allow_sync,
|
||||
bool is_bitmapscan);
|
||||
static XLogRecPtr log_heap_update(Relation reln, Buffer oldbuf,
|
||||
ItemPointerData from, Buffer newbuf, HeapTuple newtup,
|
||||
bool all_visible_cleared, bool new_all_visible_cleared);
|
||||
ItemPointerData from, Buffer newbuf, HeapTuple newtup,
|
||||
bool all_visible_cleared, bool new_all_visible_cleared);
|
||||
static bool HeapSatisfiesHOTUpdate(Relation relation, Bitmapset *hot_attrs,
|
||||
HeapTuple oldtup, HeapTuple newtup);
|
||||
|
||||
@@ -248,8 +248,8 @@ heapgetpage(HeapScanDesc scan, BlockNumber page)
|
||||
|
||||
/*
|
||||
* If the all-visible flag indicates that all tuples on the page are
|
||||
* visible to everyone, we can skip the per-tuple visibility tests.
|
||||
* But not in hot standby mode. A tuple that's already visible to all
|
||||
* visible to everyone, we can skip the per-tuple visibility tests. But
|
||||
* not in hot standby mode. A tuple that's already visible to all
|
||||
* transactions in the master might still be invisible to a read-only
|
||||
* transaction in the standby.
|
||||
*/
|
||||
@@ -3667,8 +3667,8 @@ recheck_xmax:
|
||||
* someone setting xmax. Hence recheck after changing lock, same as for
|
||||
* xmax itself.
|
||||
*
|
||||
* Old-style VACUUM FULL is gone, but we have to keep this code as long
|
||||
* as we support having MOVED_OFF/MOVED_IN tuples in the database.
|
||||
* Old-style VACUUM FULL is gone, but we have to keep this code as long as
|
||||
* we support having MOVED_OFF/MOVED_IN tuples in the database.
|
||||
*/
|
||||
recheck_xvac:
|
||||
if (tuple->t_infomask & HEAP_MOVED)
|
||||
@@ -4099,9 +4099,9 @@ heap_xlog_cleanup_info(XLogRecPtr lsn, XLogRecord *record)
|
||||
ResolveRecoveryConflictWithSnapshot(xlrec->latestRemovedXid, xlrec->node);
|
||||
|
||||
/*
|
||||
* Actual operation is a no-op. Record type exists to provide a means
|
||||
* for conflict processing to occur before we begin index vacuum actions.
|
||||
* see vacuumlazy.c and also comments in btvacuumpage()
|
||||
* Actual operation is a no-op. Record type exists to provide a means for
|
||||
* conflict processing to occur before we begin index vacuum actions. see
|
||||
* vacuumlazy.c and also comments in btvacuumpage()
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -4769,8 +4769,8 @@ heap_redo(XLogRecPtr lsn, XLogRecord *record)
|
||||
uint8 info = record->xl_info & ~XLR_INFO_MASK;
|
||||
|
||||
/*
|
||||
* These operations don't overwrite MVCC data so no conflict
|
||||
* processing is required. The ones in heap2 rmgr do.
|
||||
* These operations don't overwrite MVCC data so no conflict processing is
|
||||
* required. The ones in heap2 rmgr do.
|
||||
*/
|
||||
|
||||
RestoreBkpBlocks(lsn, record, false);
|
||||
@@ -4809,8 +4809,8 @@ heap2_redo(XLogRecPtr lsn, XLogRecord *record)
|
||||
uint8 info = record->xl_info & ~XLR_INFO_MASK;
|
||||
|
||||
/*
|
||||
* Note that RestoreBkpBlocks() is called after conflict processing
|
||||
* within each record type handling function.
|
||||
* Note that RestoreBkpBlocks() is called after conflict processing within
|
||||
* each record type handling function.
|
||||
*/
|
||||
|
||||
switch (info & XLOG_HEAP_OPMASK)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/pruneheap.c,v 1.21 2010/02/08 04:33:53 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/pruneheap.c,v 1.22 2010/02/26 02:00:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -29,8 +29,9 @@
|
||||
typedef struct
|
||||
{
|
||||
TransactionId new_prune_xid; /* new prune hint value for page */
|
||||
TransactionId latestRemovedXid; /* latest xid to be removed by this prune */
|
||||
int nredirected; /* numbers of entries in arrays below */
|
||||
TransactionId latestRemovedXid; /* latest xid to be removed by this
|
||||
* prune */
|
||||
int nredirected; /* numbers of entries in arrays below */
|
||||
int ndead;
|
||||
int nunused;
|
||||
/* arrays that accumulate indexes of items to be changed */
|
||||
@@ -85,8 +86,8 @@ heap_page_prune_opt(Relation relation, Buffer buffer, TransactionId OldestXmin)
|
||||
|
||||
/*
|
||||
* We can't write WAL in recovery mode, so there's no point trying to
|
||||
* clean the page. The master will likely issue a cleaning WAL record
|
||||
* soon anyway, so this is no particular loss.
|
||||
* clean the page. The master will likely issue a cleaning WAL record soon
|
||||
* anyway, so this is no particular loss.
|
||||
*/
|
||||
if (RecoveryInProgress())
|
||||
return;
|
||||
@@ -164,8 +165,8 @@ heap_page_prune(Relation relation, Buffer buffer, TransactionId OldestXmin,
|
||||
*
|
||||
* First, initialize the new pd_prune_xid value to zero (indicating no
|
||||
* prunable tuples). If we find any tuples which may soon become
|
||||
* prunable, we will save the lowest relevant XID in new_prune_xid.
|
||||
* Also initialize the rest of our working state.
|
||||
* prunable, we will save the lowest relevant XID in new_prune_xid. Also
|
||||
* initialize the rest of our working state.
|
||||
*/
|
||||
prstate.new_prune_xid = InvalidTransactionId;
|
||||
prstate.latestRemovedXid = InvalidTransactionId;
|
||||
@@ -370,7 +371,7 @@ heap_prune_chain(Relation relation, Buffer buffer, OffsetNumber rootoffnum,
|
||||
{
|
||||
heap_prune_record_unused(prstate, rootoffnum);
|
||||
HeapTupleHeaderAdvanceLatestRemovedXid(htup,
|
||||
&prstate->latestRemovedXid);
|
||||
&prstate->latestRemovedXid);
|
||||
ndeleted++;
|
||||
}
|
||||
|
||||
@@ -499,7 +500,7 @@ heap_prune_chain(Relation relation, Buffer buffer, OffsetNumber rootoffnum,
|
||||
{
|
||||
latestdead = offnum;
|
||||
HeapTupleHeaderAdvanceLatestRemovedXid(htup,
|
||||
&prstate->latestRemovedXid);
|
||||
&prstate->latestRemovedXid);
|
||||
}
|
||||
else if (!recent_dead)
|
||||
break;
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
* Portions Copyright (c) 1994-5, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/rewriteheap.c,v 1.20 2010/02/03 10:01:29 heikki Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/rewriteheap.c,v 1.21 2010/02/26 02:00:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -281,7 +281,8 @@ end_heap_rewrite(RewriteState state)
|
||||
/* Write an XLOG UNLOGGED record if WAL-logging was skipped */
|
||||
if (!state->rs_use_wal && !state->rs_new_rel->rd_istemp)
|
||||
{
|
||||
char reason[NAMEDATALEN + 30];
|
||||
char reason[NAMEDATALEN + 30];
|
||||
|
||||
snprintf(reason, sizeof(reason), "heap rewrite on \"%s\"",
|
||||
RelationGetRelationName(state->rs_new_rel));
|
||||
XLogReportUnloggedStatement(reason);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.97 2010/02/04 00:09:13 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.98 2010/02/26 02:00:33 momjian Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@@ -796,9 +796,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally we store attributes of type 'm' externally. At this point
|
||||
* we increase the target tuple size, so that 'm' attributes aren't
|
||||
* stored externally unless really necessary.
|
||||
* Finally we store attributes of type 'm' externally. At this point we
|
||||
* increase the target tuple size, so that 'm' attributes aren't stored
|
||||
* externally unless really necessary.
|
||||
*/
|
||||
maxDataLen = TOAST_TUPLE_TARGET_MAIN - hoff;
|
||||
|
||||
@@ -1190,8 +1190,8 @@ toast_save_datum(Relation rel, Datum value, int options)
|
||||
*
|
||||
* Normally this is the actual OID of the target toast table, but during
|
||||
* table-rewriting operations such as CLUSTER, we have to insert the OID
|
||||
* of the table's real permanent toast table instead. rd_toastoid is
|
||||
* set if we have to substitute such an OID.
|
||||
* of the table's real permanent toast table instead. rd_toastoid is set
|
||||
* if we have to substitute such an OID.
|
||||
*/
|
||||
if (OidIsValid(rel->rd_toastoid))
|
||||
toast_pointer.va_toastrelid = rel->rd_toastoid;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/visibilitymap.c,v 1.8 2010/02/09 21:43:29 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/visibilitymap.c,v 1.9 2010/02/26 02:00:33 momjian Exp $
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
* visibilitymap_clear - clear a bit in the visibility map
|
||||
@@ -19,7 +19,7 @@
|
||||
* NOTES
|
||||
*
|
||||
* The visibility map is a bitmap with one bit per heap page. A set bit means
|
||||
* that all tuples on the page are known visible to all transactions, and
|
||||
* that all tuples on the page are known visible to all transactions, and
|
||||
* therefore the page doesn't need to be vacuumed. The map is conservative in
|
||||
* the sense that we make sure that whenever a bit is set, we know the
|
||||
* condition is true, but if a bit is not set, it might or might not be true.
|
||||
@@ -377,11 +377,10 @@ visibilitymap_truncate(Relation rel, BlockNumber nheapblocks)
|
||||
rel->rd_istemp);
|
||||
|
||||
/*
|
||||
* We might as well update the local smgr_vm_nblocks setting.
|
||||
* smgrtruncate sent an smgr cache inval message, which will cause
|
||||
* other backends to invalidate their copy of smgr_vm_nblocks, and
|
||||
* this one too at the next command boundary. But this ensures it
|
||||
* isn't outright wrong until then.
|
||||
* We might as well update the local smgr_vm_nblocks setting. smgrtruncate
|
||||
* sent an smgr cache inval message, which will cause other backends to
|
||||
* invalidate their copy of smgr_vm_nblocks, and this one too at the next
|
||||
* command boundary. But this ensures it isn't outright wrong until then.
|
||||
*/
|
||||
if (rel->rd_smgr)
|
||||
rel->rd_smgr->smgr_vm_nblocks = newnblocks;
|
||||
@@ -411,7 +410,7 @@ vm_readbuf(Relation rel, BlockNumber blkno, bool extend)
|
||||
{
|
||||
if (smgrexists(rel->rd_smgr, VISIBILITYMAP_FORKNUM))
|
||||
rel->rd_smgr->smgr_vm_nblocks = smgrnblocks(rel->rd_smgr,
|
||||
VISIBILITYMAP_FORKNUM);
|
||||
VISIBILITYMAP_FORKNUM);
|
||||
else
|
||||
rel->rd_smgr->smgr_vm_nblocks = 0;
|
||||
}
|
||||
@@ -466,8 +465,8 @@ vm_extend(Relation rel, BlockNumber vm_nblocks)
|
||||
RelationOpenSmgr(rel);
|
||||
|
||||
/*
|
||||
* Create the file first if it doesn't exist. If smgr_vm_nblocks
|
||||
* is positive then it must exist, no need for an smgrexists call.
|
||||
* Create the file first if it doesn't exist. If smgr_vm_nblocks is
|
||||
* positive then it must exist, no need for an smgrexists call.
|
||||
*/
|
||||
if ((rel->rd_smgr->smgr_vm_nblocks == 0 ||
|
||||
rel->rd_smgr->smgr_vm_nblocks == InvalidBlockNumber) &&
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.80 2010/02/07 20:48:09 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.81 2010/02/26 02:00:33 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* many of the old access method routines have been turned into
|
||||
@@ -94,13 +94,13 @@ RelationGetIndexScan(Relation indexRelation,
|
||||
|
||||
/*
|
||||
* During recovery we ignore killed tuples and don't bother to kill them
|
||||
* either. We do this because the xmin on the primary node could easily
|
||||
* be later than the xmin on the standby node, so that what the primary
|
||||
* either. We do this because the xmin on the primary node could easily be
|
||||
* later than the xmin on the standby node, so that what the primary
|
||||
* thinks is killed is supposed to be visible on standby. So for correct
|
||||
* MVCC for queries during recovery we must ignore these hints and check
|
||||
* all tuples. Do *not* set ignore_killed_tuples to true when running
|
||||
* in a transaction that was started during recovery.
|
||||
* xactStartedInRecovery should not be altered by index AMs.
|
||||
* all tuples. Do *not* set ignore_killed_tuples to true when running in a
|
||||
* transaction that was started during recovery. xactStartedInRecovery
|
||||
* should not be altered by index AMs.
|
||||
*/
|
||||
scan->kill_prior_tuple = false;
|
||||
scan->xactStartedInRecovery = TransactionStartedDuringRecovery();
|
||||
@@ -170,24 +170,24 @@ BuildIndexValueDescription(Relation indexRelation,
|
||||
|
||||
for (i = 0; i < natts; i++)
|
||||
{
|
||||
char *val;
|
||||
char *val;
|
||||
|
||||
if (isnull[i])
|
||||
val = "null";
|
||||
else
|
||||
{
|
||||
Oid foutoid;
|
||||
bool typisvarlena;
|
||||
Oid foutoid;
|
||||
bool typisvarlena;
|
||||
|
||||
/*
|
||||
* The provided data is not necessarily of the type stored in
|
||||
* the index; rather it is of the index opclass's input type.
|
||||
* So look at rd_opcintype not the index tupdesc.
|
||||
* The provided data is not necessarily of the type stored in the
|
||||
* index; rather it is of the index opclass's input type. So look
|
||||
* at rd_opcintype not the index tupdesc.
|
||||
*
|
||||
* Note: this is a bit shaky for opclasses that have pseudotype
|
||||
* input types such as ANYARRAY or RECORD. Currently, the
|
||||
* typoutput functions associated with the pseudotypes will
|
||||
* work okay, but we might have to try harder in future.
|
||||
* input types such as ANYARRAY or RECORD. Currently, the
|
||||
* typoutput functions associated with the pseudotypes will work
|
||||
* okay, but we might have to try harder in future.
|
||||
*/
|
||||
getTypeOutputInfo(indexRelation->rd_opcintype[i],
|
||||
&foutoid, &typisvarlena);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.117 2010/01/02 16:57:35 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.118 2010/02/26 02:00:34 momjian Exp $
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
* index_open - open an index relation by relation OID
|
||||
@@ -455,9 +455,9 @@ index_getnext(IndexScanDesc scan, ScanDirection direction)
|
||||
|
||||
/*
|
||||
* If we scanned a whole HOT chain and found only dead tuples,
|
||||
* tell index AM to kill its entry for that TID. We do not do
|
||||
* this when in recovery because it may violate MVCC to do so.
|
||||
* see comments in RelationGetIndexScan().
|
||||
* tell index AM to kill its entry for that TID. We do not do this
|
||||
* when in recovery because it may violate MVCC to do so. see
|
||||
* comments in RelationGetIndexScan().
|
||||
*/
|
||||
if (!scan->xactStartedInRecovery)
|
||||
scan->kill_prior_tuple = scan->xs_hot_dead;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.176 2010/01/02 16:57:35 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.177 2010/02/26 02:00:34 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -88,7 +88,7 @@ static void _bt_vacuum_one_page(Relation rel, Buffer buffer);
|
||||
* and btinsert. By here, itup is filled in, including the TID.
|
||||
*
|
||||
* If checkUnique is UNIQUE_CHECK_NO or UNIQUE_CHECK_PARTIAL, this
|
||||
* will allow duplicates. Otherwise (UNIQUE_CHECK_YES or
|
||||
* will allow duplicates. Otherwise (UNIQUE_CHECK_YES or
|
||||
* UNIQUE_CHECK_EXISTING) it will throw error for a duplicate.
|
||||
* For UNIQUE_CHECK_EXISTING we merely run the duplicate check, and
|
||||
* don't actually insert.
|
||||
@@ -149,9 +149,9 @@ top:
|
||||
* If we must wait for another xact, we release the lock while waiting,
|
||||
* and then must start over completely.
|
||||
*
|
||||
* For a partial uniqueness check, we don't wait for the other xact.
|
||||
* Just let the tuple in and return false for possibly non-unique,
|
||||
* or true for definitely unique.
|
||||
* For a partial uniqueness check, we don't wait for the other xact. Just
|
||||
* let the tuple in and return false for possibly non-unique, or true for
|
||||
* definitely unique.
|
||||
*/
|
||||
if (checkUnique != UNIQUE_CHECK_NO)
|
||||
{
|
||||
@@ -281,7 +281,7 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel,
|
||||
|
||||
/*
|
||||
* If we are doing a recheck, we expect to find the tuple we
|
||||
* are rechecking. It's not a duplicate, but we have to keep
|
||||
* are rechecking. It's not a duplicate, but we have to keep
|
||||
* scanning.
|
||||
*/
|
||||
if (checkUnique == UNIQUE_CHECK_EXISTING &&
|
||||
@@ -302,10 +302,10 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel,
|
||||
|
||||
/*
|
||||
* It is a duplicate. If we are only doing a partial
|
||||
* check, then don't bother checking if the tuple is
|
||||
* being updated in another transaction. Just return
|
||||
* the fact that it is a potential conflict and leave
|
||||
* the full check till later.
|
||||
* check, then don't bother checking if the tuple is being
|
||||
* updated in another transaction. Just return the fact
|
||||
* that it is a potential conflict and leave the full
|
||||
* check till later.
|
||||
*/
|
||||
if (checkUnique == UNIQUE_CHECK_PARTIAL)
|
||||
{
|
||||
@@ -362,20 +362,20 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel,
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a definite conflict. Break the tuple down
|
||||
* into datums and report the error. But first, make
|
||||
* sure we release the buffer locks we're holding ---
|
||||
* This is a definite conflict. Break the tuple down into
|
||||
* datums and report the error. But first, make sure we
|
||||
* release the buffer locks we're holding ---
|
||||
* BuildIndexValueDescription could make catalog accesses,
|
||||
* which in the worst case might touch this same index
|
||||
* and cause deadlocks.
|
||||
* which in the worst case might touch this same index and
|
||||
* cause deadlocks.
|
||||
*/
|
||||
if (nbuf != InvalidBuffer)
|
||||
_bt_relbuf(rel, nbuf);
|
||||
_bt_relbuf(rel, buf);
|
||||
|
||||
{
|
||||
Datum values[INDEX_MAX_KEYS];
|
||||
bool isnull[INDEX_MAX_KEYS];
|
||||
Datum values[INDEX_MAX_KEYS];
|
||||
bool isnull[INDEX_MAX_KEYS];
|
||||
|
||||
index_deform_tuple(itup, RelationGetDescr(rel),
|
||||
values, isnull);
|
||||
@@ -385,7 +385,7 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel,
|
||||
RelationGetRelationName(rel)),
|
||||
errdetail("Key %s already exists.",
|
||||
BuildIndexValueDescription(rel,
|
||||
values, isnull))));
|
||||
values, isnull))));
|
||||
}
|
||||
}
|
||||
else if (all_dead)
|
||||
@@ -438,16 +438,16 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel,
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are doing a recheck then we should have found the tuple we
|
||||
* are checking. Otherwise there's something very wrong --- probably,
|
||||
* the index is on a non-immutable expression.
|
||||
* If we are doing a recheck then we should have found the tuple we are
|
||||
* checking. Otherwise there's something very wrong --- probably, the
|
||||
* index is on a non-immutable expression.
|
||||
*/
|
||||
if (checkUnique == UNIQUE_CHECK_EXISTING && !found)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INTERNAL_ERROR),
|
||||
errmsg("failed to re-find tuple within index \"%s\"",
|
||||
RelationGetRelationName(rel)),
|
||||
errhint("This may be because of a non-immutable index expression.")));
|
||||
errhint("This may be because of a non-immutable index expression.")));
|
||||
|
||||
if (nbuf != InvalidBuffer)
|
||||
_bt_relbuf(rel, nbuf);
|
||||
@@ -518,10 +518,10 @@ _bt_findinsertloc(Relation rel,
|
||||
if (itemsz > BTMaxItemSize(page))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||
errmsg("index row size %lu exceeds maximum %lu for index \"%s\"",
|
||||
(unsigned long) itemsz,
|
||||
(unsigned long) BTMaxItemSize(page),
|
||||
RelationGetRelationName(rel)),
|
||||
errmsg("index row size %lu exceeds maximum %lu for index \"%s\"",
|
||||
(unsigned long) itemsz,
|
||||
(unsigned long) BTMaxItemSize(page),
|
||||
RelationGetRelationName(rel)),
|
||||
errhint("Values larger than 1/3 of a buffer page cannot be indexed.\n"
|
||||
"Consider a function index of an MD5 hash of the value, "
|
||||
"or use full text indexing.")));
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.119 2010/02/13 00:59:58 sriggs Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.120 2010/02/26 02:00:34 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Postgres btree pages look like ordinary relation pages. The opaque
|
||||
@@ -459,8 +459,8 @@ _bt_log_reuse_page(Relation rel, BlockNumber blkno, TransactionId latestRemovedX
|
||||
START_CRIT_SECTION();
|
||||
|
||||
/*
|
||||
* We don't do MarkBufferDirty here because we're about initialise
|
||||
* the page, and nobody else can see it yet.
|
||||
* We don't do MarkBufferDirty here because we're about initialise the
|
||||
* page, and nobody else can see it yet.
|
||||
*/
|
||||
|
||||
/* XLOG stuff */
|
||||
@@ -480,8 +480,8 @@ _bt_log_reuse_page(Relation rel, BlockNumber blkno, TransactionId latestRemovedX
|
||||
recptr = XLogInsert(RM_BTREE_ID, XLOG_BTREE_REUSE_PAGE, rdata);
|
||||
|
||||
/*
|
||||
* We don't do PageSetLSN or PageSetTLI here because
|
||||
* we're about initialise the page, so no need.
|
||||
* We don't do PageSetLSN or PageSetTLI here because we're about
|
||||
* initialise the page, so no need.
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -552,11 +552,11 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access)
|
||||
{
|
||||
page = BufferGetPage(buf);
|
||||
if (_bt_page_recyclable(page))
|
||||
{
|
||||
{
|
||||
/*
|
||||
* If we are generating WAL for Hot Standby then create
|
||||
* a WAL record that will allow us to conflict with
|
||||
* queries running on standby.
|
||||
* If we are generating WAL for Hot Standby then create a
|
||||
* WAL record that will allow us to conflict with queries
|
||||
* running on standby.
|
||||
*/
|
||||
if (XLogStandbyInfoActive())
|
||||
{
|
||||
@@ -762,6 +762,7 @@ _bt_delitems(Relation rel, Buffer buf,
|
||||
if (isVacuum)
|
||||
{
|
||||
xl_btree_vacuum xlrec_vacuum;
|
||||
|
||||
xlrec_vacuum.node = rel->rd_node;
|
||||
xlrec_vacuum.block = BufferGetBlockNumber(buf);
|
||||
|
||||
@@ -772,6 +773,7 @@ _bt_delitems(Relation rel, Buffer buf,
|
||||
else
|
||||
{
|
||||
xl_btree_delete xlrec_delete;
|
||||
|
||||
xlrec_delete.node = rel->rd_node;
|
||||
xlrec_delete.block = BufferGetBlockNumber(buf);
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.175 2010/02/08 04:33:53 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.176 2010/02/26 02:00:34 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -57,8 +57,8 @@ typedef struct
|
||||
IndexBulkDeleteCallback callback;
|
||||
void *callback_state;
|
||||
BTCycleId cycleid;
|
||||
BlockNumber lastBlockVacuumed; /* last blkno reached by Vacuum scan */
|
||||
BlockNumber lastUsedPage; /* blkno of last non-recyclable page */
|
||||
BlockNumber lastBlockVacuumed; /* last blkno reached by Vacuum scan */
|
||||
BlockNumber lastUsedPage; /* blkno of last non-recyclable page */
|
||||
BlockNumber totFreePages; /* true total # of free pages */
|
||||
MemoryContext pagedelcontext;
|
||||
} BTVacState;
|
||||
@@ -630,7 +630,7 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
|
||||
vstate.callback = callback;
|
||||
vstate.callback_state = callback_state;
|
||||
vstate.cycleid = cycleid;
|
||||
vstate.lastBlockVacuumed = BTREE_METAPAGE; /* Initialise at first block */
|
||||
vstate.lastBlockVacuumed = BTREE_METAPAGE; /* Initialise at first block */
|
||||
vstate.lastUsedPage = BTREE_METAPAGE;
|
||||
vstate.totFreePages = 0;
|
||||
|
||||
@@ -702,8 +702,8 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
|
||||
/*
|
||||
* We can't use _bt_getbuf() here because it always applies
|
||||
* _bt_checkpage(), which will barf on an all-zero page. We want to
|
||||
* recycle all-zero pages, not fail. Also, we want to use a nondefault
|
||||
* buffer access strategy.
|
||||
* recycle all-zero pages, not fail. Also, we want to use a
|
||||
* nondefault buffer access strategy.
|
||||
*/
|
||||
buf = ReadBufferExtended(rel, MAIN_FORKNUM, num_pages - 1, RBM_NORMAL,
|
||||
info->strategy);
|
||||
@@ -856,23 +856,25 @@ restart:
|
||||
htup = &(itup->t_tid);
|
||||
|
||||
/*
|
||||
* During Hot Standby we currently assume that XLOG_BTREE_VACUUM
|
||||
* records do not produce conflicts. That is only true as long
|
||||
* as the callback function depends only upon whether the index
|
||||
* tuple refers to heap tuples removed in the initial heap scan.
|
||||
* When vacuum starts it derives a value of OldestXmin. Backends
|
||||
* taking later snapshots could have a RecentGlobalXmin with a
|
||||
* later xid than the vacuum's OldestXmin, so it is possible that
|
||||
* row versions deleted after OldestXmin could be marked as killed
|
||||
* by other backends. The callback function *could* look at the
|
||||
* index tuple state in isolation and decide to delete the index
|
||||
* tuple, though currently it does not. If it ever did, we would
|
||||
* need to reconsider whether XLOG_BTREE_VACUUM records should
|
||||
* cause conflicts. If they did cause conflicts they would be
|
||||
* fairly harsh conflicts, since we haven't yet worked out a way
|
||||
* to pass a useful value for latestRemovedXid on the
|
||||
* XLOG_BTREE_VACUUM records. This applies to *any* type of index
|
||||
* that marks index tuples as killed.
|
||||
* During Hot Standby we currently assume that
|
||||
* XLOG_BTREE_VACUUM records do not produce conflicts. That is
|
||||
* only true as long as the callback function depends only
|
||||
* upon whether the index tuple refers to heap tuples removed
|
||||
* in the initial heap scan. When vacuum starts it derives a
|
||||
* value of OldestXmin. Backends taking later snapshots could
|
||||
* have a RecentGlobalXmin with a later xid than the vacuum's
|
||||
* OldestXmin, so it is possible that row versions deleted
|
||||
* after OldestXmin could be marked as killed by other
|
||||
* backends. The callback function *could* look at the index
|
||||
* tuple state in isolation and decide to delete the index
|
||||
* tuple, though currently it does not. If it ever did, we
|
||||
* would need to reconsider whether XLOG_BTREE_VACUUM records
|
||||
* should cause conflicts. If they did cause conflicts they
|
||||
* would be fairly harsh conflicts, since we haven't yet
|
||||
* worked out a way to pass a useful value for
|
||||
* latestRemovedXid on the XLOG_BTREE_VACUUM records. This
|
||||
* applies to *any* type of index that marks index tuples as
|
||||
* killed.
|
||||
*/
|
||||
if (callback(htup, callback_state))
|
||||
deletable[ndeletable++] = offnum;
|
||||
@@ -885,13 +887,13 @@ restart:
|
||||
*/
|
||||
if (ndeletable > 0)
|
||||
{
|
||||
BlockNumber lastBlockVacuumed = BufferGetBlockNumber(buf);
|
||||
BlockNumber lastBlockVacuumed = BufferGetBlockNumber(buf);
|
||||
|
||||
_bt_delitems(rel, buf, deletable, ndeletable, true, vstate->lastBlockVacuumed);
|
||||
|
||||
/*
|
||||
* Keep track of the block number of the lastBlockVacuumed, so
|
||||
* we can scan those blocks as well during WAL replay. This then
|
||||
* Keep track of the block number of the lastBlockVacuumed, so we
|
||||
* can scan those blocks as well during WAL replay. This then
|
||||
* provides concurrency protection and allows btrees to be used
|
||||
* while in recovery.
|
||||
*/
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.123 2010/01/20 19:43:40 heikki Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.124 2010/02/26 02:00:34 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -216,12 +216,13 @@ _bt_leafbuild(BTSpool *btspool, BTSpool *btspool2)
|
||||
wstate.btws_use_wal = XLogIsNeeded() && !wstate.index->rd_istemp;
|
||||
|
||||
/*
|
||||
* Write an XLOG UNLOGGED record if WAL-logging was skipped because
|
||||
* WAL archiving is not enabled.
|
||||
* Write an XLOG UNLOGGED record if WAL-logging was skipped because WAL
|
||||
* archiving is not enabled.
|
||||
*/
|
||||
if (!wstate.btws_use_wal && !wstate.index->rd_istemp)
|
||||
{
|
||||
char reason[NAMEDATALEN + 20];
|
||||
char reason[NAMEDATALEN + 20];
|
||||
|
||||
snprintf(reason, sizeof(reason), "b-tree build on \"%s\"",
|
||||
RelationGetRelationName(wstate.index));
|
||||
XLogReportUnloggedStatement(reason);
|
||||
@@ -492,10 +493,10 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, IndexTuple itup)
|
||||
if (itupsz > BTMaxItemSize(npage))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||
errmsg("index row size %lu exceeds maximum %lu for index \"%s\"",
|
||||
(unsigned long) itupsz,
|
||||
(unsigned long) BTMaxItemSize(npage),
|
||||
RelationGetRelationName(wstate->index)),
|
||||
errmsg("index row size %lu exceeds maximum %lu for index \"%s\"",
|
||||
(unsigned long) itupsz,
|
||||
(unsigned long) BTMaxItemSize(npage),
|
||||
RelationGetRelationName(wstate->index)),
|
||||
errhint("Values larger than 1/3 of a buffer page cannot be indexed.\n"
|
||||
"Consider a function index of an MD5 hash of the value, "
|
||||
"or use full text indexing.")));
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.97 2010/01/03 05:39:08 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.98 2010/02/26 02:00:34 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -515,7 +515,7 @@ _bt_compare_scankey_args(IndexScanDesc scan, ScanKey op,
|
||||
StrategyNumber strat;
|
||||
|
||||
/*
|
||||
* First, deal with cases where one or both args are NULL. This should
|
||||
* First, deal with cases where one or both args are NULL. This should
|
||||
* only happen when the scankeys represent IS NULL/NOT NULL conditions.
|
||||
*/
|
||||
if ((leftarg->sk_flags | rightarg->sk_flags) & SK_ISNULL)
|
||||
@@ -566,7 +566,7 @@ _bt_compare_scankey_args(IndexScanDesc scan, ScanKey op,
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "unrecognized StrategyNumber: %d", (int) strat);
|
||||
*result = false; /* keep compiler quiet */
|
||||
*result = false; /* keep compiler quiet */
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
@@ -612,8 +612,8 @@ _bt_compare_scankey_args(IndexScanDesc scan, ScanKey op,
|
||||
* indexscan initiated by syscache lookup will use cross-data-type
|
||||
* operators.)
|
||||
*
|
||||
* If the sk_strategy was flipped by _bt_fix_scankey_strategy, we
|
||||
* have to un-flip it to get the correct opfamily member.
|
||||
* If the sk_strategy was flipped by _bt_fix_scankey_strategy, we have to
|
||||
* un-flip it to get the correct opfamily member.
|
||||
*/
|
||||
strat = op->sk_strategy;
|
||||
if (op->sk_flags & SK_BT_DESC)
|
||||
@@ -653,7 +653,7 @@ _bt_compare_scankey_args(IndexScanDesc scan, ScanKey op,
|
||||
*
|
||||
* Lastly, for ordinary scankeys (not IS NULL/NOT NULL), we check for a
|
||||
* NULL comparison value. Since all btree operators are assumed strict,
|
||||
* a NULL means that the qual cannot be satisfied. We return TRUE if the
|
||||
* a NULL means that the qual cannot be satisfied. We return TRUE if the
|
||||
* comparison value isn't NULL, or FALSE if the scan should be abandoned.
|
||||
*
|
||||
* This function is applied to the *input* scankey structure; therefore
|
||||
@@ -682,7 +682,7 @@ _bt_fix_scankey_strategy(ScanKey skey, int16 *indoption)
|
||||
* --- we can treat IS NULL as an equality operator for purposes of search
|
||||
* strategy.
|
||||
*
|
||||
* Likewise, "x IS NOT NULL" is supported. We treat that as either "less
|
||||
* Likewise, "x IS NOT NULL" is supported. We treat that as either "less
|
||||
* than NULL" in a NULLS LAST index, or "greater than NULL" in a NULLS
|
||||
* FIRST index.
|
||||
*/
|
||||
@@ -910,13 +910,13 @@ _bt_checkkeys(IndexScanDesc scan,
|
||||
if (key->sk_flags & SK_SEARCHNULL)
|
||||
{
|
||||
if (isNull)
|
||||
continue; /* tuple satisfies this qual */
|
||||
continue; /* tuple satisfies this qual */
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert(key->sk_flags & SK_SEARCHNOTNULL);
|
||||
if (!isNull)
|
||||
continue; /* tuple satisfies this qual */
|
||||
continue; /* tuple satisfies this qual */
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.61 2010/02/13 00:59:58 sriggs Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.62 2010/02/26 02:00:34 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -473,10 +473,10 @@ btree_xlog_vacuum(XLogRecPtr lsn, XLogRecord *record)
|
||||
xlrec = (xl_btree_vacuum *) XLogRecGetData(record);
|
||||
|
||||
/*
|
||||
* If queries might be active then we need to ensure every block is unpinned
|
||||
* between the lastBlockVacuumed and the current block, if there are any.
|
||||
* This ensures that every block in the index is touched during VACUUM as
|
||||
* required to ensure scans work correctly.
|
||||
* If queries might be active then we need to ensure every block is
|
||||
* unpinned between the lastBlockVacuumed and the current block, if there
|
||||
* are any. This ensures that every block in the index is touched during
|
||||
* VACUUM as required to ensure scans work correctly.
|
||||
*/
|
||||
if (standbyState == STANDBY_SNAPSHOT_READY &&
|
||||
(xlrec->lastBlockVacuumed + 1) != xlrec->block)
|
||||
@@ -486,10 +486,10 @@ btree_xlog_vacuum(XLogRecPtr lsn, XLogRecord *record)
|
||||
for (; blkno < xlrec->block; blkno++)
|
||||
{
|
||||
/*
|
||||
* XXX we don't actually need to read the block, we
|
||||
* just need to confirm it is unpinned. If we had a special call
|
||||
* into the buffer manager we could optimise this so that
|
||||
* if the block is not in shared_buffers we confirm it as unpinned.
|
||||
* XXX we don't actually need to read the block, we just need to
|
||||
* confirm it is unpinned. If we had a special call into the
|
||||
* buffer manager we could optimise this so that if the block is
|
||||
* not in shared_buffers we confirm it as unpinned.
|
||||
*
|
||||
* Another simple optimization would be to check if there's any
|
||||
* backends running; if not, we could just skip this.
|
||||
@@ -505,9 +505,9 @@ btree_xlog_vacuum(XLogRecPtr lsn, XLogRecord *record)
|
||||
|
||||
/*
|
||||
* If the block was restored from a full page image, nothing more to do.
|
||||
* The RestoreBkpBlocks() call already pinned and took cleanup lock on
|
||||
* it. XXX: Perhaps we should call RestoreBkpBlocks() *after* the loop
|
||||
* above, to make the disk access more sequential.
|
||||
* The RestoreBkpBlocks() call already pinned and took cleanup lock on it.
|
||||
* XXX: Perhaps we should call RestoreBkpBlocks() *after* the loop above,
|
||||
* to make the disk access more sequential.
|
||||
*/
|
||||
if (record->xl_info & XLR_BKP_BLOCK_1)
|
||||
return;
|
||||
@@ -567,8 +567,8 @@ btree_xlog_delete(XLogRecPtr lsn, XLogRecord *record)
|
||||
xlrec = (xl_btree_delete *) XLogRecGetData(record);
|
||||
|
||||
/*
|
||||
* We don't need to take a cleanup lock to apply these changes.
|
||||
* See nbtree/README for details.
|
||||
* We don't need to take a cleanup lock to apply these changes. See
|
||||
* nbtree/README for details.
|
||||
*/
|
||||
buffer = XLogReadBuffer(xlrec->node, xlrec->block, false);
|
||||
if (!BufferIsValid(buffer))
|
||||
@@ -819,13 +819,15 @@ btree_redo(XLogRecPtr lsn, XLogRecord *record)
|
||||
switch (info)
|
||||
{
|
||||
case XLOG_BTREE_DELETE:
|
||||
|
||||
/*
|
||||
* Btree delete records can conflict with standby queries. You might
|
||||
* think that vacuum records would conflict as well, but we've handled
|
||||
* that already. XLOG_HEAP2_CLEANUP_INFO records provide the highest xid
|
||||
* cleaned by the vacuum of the heap and so we can resolve any conflicts
|
||||
* just once when that arrives. After that any we know that no conflicts
|
||||
* exist from individual btree vacuum records on that index.
|
||||
* Btree delete records can conflict with standby queries. You
|
||||
* might think that vacuum records would conflict as well, but
|
||||
* we've handled that already. XLOG_HEAP2_CLEANUP_INFO records
|
||||
* provide the highest xid cleaned by the vacuum of the heap
|
||||
* and so we can resolve any conflicts just once when that
|
||||
* arrives. After that any we know that no conflicts exist
|
||||
* from individual btree vacuum records on that index.
|
||||
*/
|
||||
{
|
||||
xl_btree_delete *xlrec = (xl_btree_delete *) XLogRecGetData(record);
|
||||
@@ -842,9 +844,11 @@ btree_redo(XLogRecPtr lsn, XLogRecord *record)
|
||||
break;
|
||||
|
||||
case XLOG_BTREE_REUSE_PAGE:
|
||||
|
||||
/*
|
||||
* Btree reuse page records exist to provide a conflict point when we
|
||||
* reuse pages in the index via the FSM. That's all it does though.
|
||||
* Btree reuse page records exist to provide a conflict point
|
||||
* when we reuse pages in the index via the FSM. That's all it
|
||||
* does though.
|
||||
*/
|
||||
{
|
||||
xl_btree_reuse_page *xlrec = (xl_btree_reuse_page *) XLogRecGetData(record);
|
||||
@@ -859,8 +863,8 @@ btree_redo(XLogRecPtr lsn, XLogRecord *record)
|
||||
}
|
||||
|
||||
/*
|
||||
* Vacuum needs to pin and take cleanup lock on every leaf page,
|
||||
* a regular exclusive lock is enough for all other purposes.
|
||||
* Vacuum needs to pin and take cleanup lock on every leaf page, a regular
|
||||
* exclusive lock is enough for all other purposes.
|
||||
*/
|
||||
RestoreBkpBlocks(lsn, record, (info == XLOG_BTREE_VACUUM));
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/multixact.c,v 1.34 2010/01/02 16:57:35 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/multixact.c,v 1.35 2010/02/26 02:00:34 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1298,11 +1298,11 @@ PostPrepare_MultiXact(TransactionId xid)
|
||||
myOldestMember = OldestMemberMXactId[MyBackendId];
|
||||
if (MultiXactIdIsValid(myOldestMember))
|
||||
{
|
||||
BackendId dummyBackendId = TwoPhaseGetDummyBackendId(xid);
|
||||
BackendId dummyBackendId = TwoPhaseGetDummyBackendId(xid);
|
||||
|
||||
/*
|
||||
* Even though storing MultiXactId is atomic, acquire lock to make sure
|
||||
* others see both changes, not just the reset of the slot of the
|
||||
* Even though storing MultiXactId is atomic, acquire lock to make
|
||||
* sure others see both changes, not just the reset of the slot of the
|
||||
* current backend. Using a volatile pointer might suffice, but this
|
||||
* isn't a hot spot.
|
||||
*/
|
||||
@@ -1316,8 +1316,8 @@ PostPrepare_MultiXact(TransactionId xid)
|
||||
|
||||
/*
|
||||
* We don't need to transfer OldestVisibleMXactId value, because the
|
||||
* transaction is not going to be looking at any more multixacts once
|
||||
* it's prepared.
|
||||
* transaction is not going to be looking at any more multixacts once it's
|
||||
* prepared.
|
||||
*
|
||||
* We assume that storing a MultiXactId is atomic and so we need not take
|
||||
* MultiXactGenLock to do this.
|
||||
@@ -1340,14 +1340,14 @@ multixact_twophase_recover(TransactionId xid, uint16 info,
|
||||
void *recdata, uint32 len)
|
||||
{
|
||||
BackendId dummyBackendId = TwoPhaseGetDummyBackendId(xid);
|
||||
MultiXactId oldestMember;
|
||||
MultiXactId oldestMember;
|
||||
|
||||
/*
|
||||
* Get the oldest member XID from the state file record, and set it in
|
||||
* the OldestMemberMXactId slot reserved for this prepared transaction.
|
||||
* Get the oldest member XID from the state file record, and set it in the
|
||||
* OldestMemberMXactId slot reserved for this prepared transaction.
|
||||
*/
|
||||
Assert(len == sizeof(MultiXactId));
|
||||
oldestMember = *((MultiXactId *)recdata);
|
||||
oldestMember = *((MultiXactId *) recdata);
|
||||
|
||||
OldestMemberMXactId[dummyBackendId] = oldestMember;
|
||||
}
|
||||
@@ -1373,7 +1373,7 @@ multixact_twophase_postcommit(TransactionId xid, uint16 info,
|
||||
*/
|
||||
void
|
||||
multixact_twophase_postabort(TransactionId xid, uint16 info,
|
||||
void *recdata, uint32 len)
|
||||
void *recdata, uint32 len)
|
||||
{
|
||||
multixact_twophase_postcommit(xid, info, recdata, len);
|
||||
}
|
||||
@@ -2031,9 +2031,10 @@ multixact_redo(XLogRecPtr lsn, XLogRecord *record)
|
||||
max_xid = xids[i];
|
||||
}
|
||||
|
||||
/* We don't expect anyone else to modify nextXid, hence startup process
|
||||
* doesn't need to hold a lock while checking this. We still acquire
|
||||
* the lock to modify it, though.
|
||||
/*
|
||||
* We don't expect anyone else to modify nextXid, hence startup
|
||||
* process doesn't need to hold a lock while checking this. We still
|
||||
* acquire the lock to modify it, though.
|
||||
*/
|
||||
if (TransactionIdFollowsOrEquals(max_xid,
|
||||
ShmemVariableCache->nextXid))
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/subtrans.c,v 1.26 2010/01/02 16:57:35 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/subtrans.c,v 1.27 2010/02/26 02:00:34 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -89,7 +89,7 @@ SubTransSetParent(TransactionId xid, TransactionId parent, bool overwriteOK)
|
||||
|
||||
/* Current state should be 0 */
|
||||
Assert(*ptr == InvalidTransactionId ||
|
||||
(*ptr == parent && overwriteOK));
|
||||
(*ptr == parent && overwriteOK));
|
||||
|
||||
*ptr = parent;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.58 2010/01/02 16:57:35 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.59 2010/02/26 02:00:34 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Each global transaction is associated with a global transaction
|
||||
@@ -110,7 +110,7 @@ int max_prepared_xacts = 0;
|
||||
typedef struct GlobalTransactionData
|
||||
{
|
||||
PGPROC proc; /* dummy proc */
|
||||
BackendId dummyBackendId; /* similar to backend id for backends */
|
||||
BackendId dummyBackendId; /* similar to backend id for backends */
|
||||
TimestampTz prepared_at; /* time of preparation */
|
||||
XLogRecPtr prepare_lsn; /* XLOG offset of prepare record */
|
||||
Oid owner; /* ID of user that executed the xact */
|
||||
@@ -209,14 +209,14 @@ TwoPhaseShmemInit(void)
|
||||
/*
|
||||
* Assign a unique ID for each dummy proc, so that the range of
|
||||
* dummy backend IDs immediately follows the range of normal
|
||||
* backend IDs. We don't dare to assign a real backend ID to
|
||||
* dummy procs, because prepared transactions don't take part in
|
||||
* cache invalidation like a real backend ID would imply, but
|
||||
* having a unique ID for them is nevertheless handy. This
|
||||
* arrangement allows you to allocate an array of size
|
||||
* (MaxBackends + max_prepared_xacts + 1), and have a slot for
|
||||
* every backend and prepared transaction. Currently multixact.c
|
||||
* uses that technique.
|
||||
* backend IDs. We don't dare to assign a real backend ID to dummy
|
||||
* procs, because prepared transactions don't take part in cache
|
||||
* invalidation like a real backend ID would imply, but having a
|
||||
* unique ID for them is nevertheless handy. This arrangement
|
||||
* allows you to allocate an array of size (MaxBackends +
|
||||
* max_prepared_xacts + 1), and have a slot for every backend and
|
||||
* prepared transaction. Currently multixact.c uses that
|
||||
* technique.
|
||||
*/
|
||||
gxacts[i].dummyBackendId = MaxBackends + 1 + i;
|
||||
}
|
||||
@@ -677,7 +677,7 @@ pg_prepared_xact(PG_FUNCTION_ARGS)
|
||||
BackendId
|
||||
TwoPhaseGetDummyBackendId(TransactionId xid)
|
||||
{
|
||||
PGPROC *proc = TwoPhaseGetDummyProc(xid);
|
||||
PGPROC *proc = TwoPhaseGetDummyProc(xid);
|
||||
|
||||
return ((GlobalTransaction) proc)->dummyBackendId;
|
||||
}
|
||||
@@ -874,8 +874,8 @@ StartPrepare(GlobalTransaction gxact)
|
||||
save_state_data(&hdr, sizeof(TwoPhaseFileHeader));
|
||||
|
||||
/*
|
||||
* Add the additional info about subxacts, deletable files and
|
||||
* cache invalidation messages.
|
||||
* Add the additional info about subxacts, deletable files and cache
|
||||
* invalidation messages.
|
||||
*/
|
||||
if (hdr.nsubxacts > 0)
|
||||
{
|
||||
@@ -1331,8 +1331,8 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
|
||||
/*
|
||||
* Handle cache invalidation messages.
|
||||
*
|
||||
* Relcache init file invalidation requires processing both
|
||||
* before and after we send the SI messages. See AtEOXact_Inval()
|
||||
* Relcache init file invalidation requires processing both before and
|
||||
* after we send the SI messages. See AtEOXact_Inval()
|
||||
*/
|
||||
if (hdr->initfileinval)
|
||||
RelationCacheInitFileInvalidate(true);
|
||||
@@ -1786,8 +1786,8 @@ RecoverPreparedTransactions(void)
|
||||
bufptr += MAXALIGN(hdr->ninvalmsgs * sizeof(SharedInvalidationMessage));
|
||||
|
||||
/*
|
||||
* It's possible that SubTransSetParent has been set before, if the
|
||||
* prepared transaction generated xid assignment records. Test
|
||||
* It's possible that SubTransSetParent has been set before, if
|
||||
* the prepared transaction generated xid assignment records. Test
|
||||
* here must match one used in AssignTransactionId().
|
||||
*/
|
||||
if (InHotStandby && hdr->nsubxacts >= PGPROC_MAX_CACHED_SUBXIDS)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/twophase_rmgr.c,v 1.13 2010/02/16 22:34:43 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/twophase_rmgr.c,v 1.14 2010/02/26 02:00:34 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -32,8 +32,8 @@ const TwoPhaseCallback twophase_postcommit_callbacks[TWOPHASE_RM_MAX_ID + 1] =
|
||||
{
|
||||
NULL, /* END ID */
|
||||
lock_twophase_postcommit, /* Lock */
|
||||
pgstat_twophase_postcommit, /* pgstat */
|
||||
multixact_twophase_postcommit /* MultiXact */
|
||||
pgstat_twophase_postcommit, /* pgstat */
|
||||
multixact_twophase_postcommit /* MultiXact */
|
||||
};
|
||||
|
||||
const TwoPhaseCallback twophase_postabort_callbacks[TWOPHASE_RM_MAX_ID + 1] =
|
||||
@@ -41,7 +41,7 @@ const TwoPhaseCallback twophase_postabort_callbacks[TWOPHASE_RM_MAX_ID + 1] =
|
||||
NULL, /* END ID */
|
||||
lock_twophase_postabort, /* Lock */
|
||||
pgstat_twophase_postabort, /* pgstat */
|
||||
multixact_twophase_postabort /* MultiXact */
|
||||
multixact_twophase_postabort /* MultiXact */
|
||||
};
|
||||
|
||||
const TwoPhaseCallback twophase_standby_recover_callbacks[TWOPHASE_RM_MAX_ID + 1] =
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* Copyright (c) 2000-2010, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/varsup.c,v 1.90 2010/02/20 21:24:01 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/varsup.c,v 1.91 2010/02/26 02:00:34 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -39,7 +39,7 @@ VariableCache ShmemVariableCache = NULL;
|
||||
*
|
||||
* Note: when this is called, we are actually already inside a valid
|
||||
* transaction, since XIDs are now not allocated until the transaction
|
||||
* does something. So it is safe to do a database lookup if we want to
|
||||
* does something. So it is safe to do a database lookup if we want to
|
||||
* issue a warning about XID wrap.
|
||||
*/
|
||||
TransactionId
|
||||
@@ -83,13 +83,13 @@ GetNewTransactionId(bool isSubXact)
|
||||
* For safety's sake, we release XidGenLock while sending signals,
|
||||
* warnings, etc. This is not so much because we care about
|
||||
* preserving concurrency in this situation, as to avoid any
|
||||
* possibility of deadlock while doing get_database_name().
|
||||
* First, copy all the shared values we'll need in this path.
|
||||
* possibility of deadlock while doing get_database_name(). First,
|
||||
* copy all the shared values we'll need in this path.
|
||||
*/
|
||||
TransactionId xidWarnLimit = ShmemVariableCache->xidWarnLimit;
|
||||
TransactionId xidStopLimit = ShmemVariableCache->xidStopLimit;
|
||||
TransactionId xidWrapLimit = ShmemVariableCache->xidWrapLimit;
|
||||
Oid oldest_datoid = ShmemVariableCache->oldestXidDB;
|
||||
Oid oldest_datoid = ShmemVariableCache->oldestXidDB;
|
||||
|
||||
LWLockRelease(XidGenLock);
|
||||
|
||||
@@ -104,7 +104,7 @@ GetNewTransactionId(bool isSubXact)
|
||||
if (IsUnderPostmaster &&
|
||||
TransactionIdFollowsOrEquals(xid, xidStopLimit))
|
||||
{
|
||||
char *oldest_datname = get_database_name(oldest_datoid);
|
||||
char *oldest_datname = get_database_name(oldest_datoid);
|
||||
|
||||
/* complain even if that DB has disappeared */
|
||||
if (oldest_datname)
|
||||
@@ -124,7 +124,7 @@ GetNewTransactionId(bool isSubXact)
|
||||
}
|
||||
else if (TransactionIdFollowsOrEquals(xid, xidWarnLimit))
|
||||
{
|
||||
char *oldest_datname = get_database_name(oldest_datoid);
|
||||
char *oldest_datname = get_database_name(oldest_datoid);
|
||||
|
||||
/* complain even if that DB has disappeared */
|
||||
if (oldest_datname)
|
||||
@@ -329,8 +329,8 @@ SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
|
||||
|
||||
/* Log the info */
|
||||
ereport(DEBUG1,
|
||||
(errmsg("transaction ID wrap limit is %u, limited by database with OID %u",
|
||||
xidWrapLimit, oldest_datoid)));
|
||||
(errmsg("transaction ID wrap limit is %u, limited by database with OID %u",
|
||||
xidWrapLimit, oldest_datoid)));
|
||||
|
||||
/*
|
||||
* If past the autovacuum force point, immediately signal an autovac
|
||||
@@ -346,7 +346,7 @@ SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
|
||||
/* Give an immediate warning if past the wrap warn point */
|
||||
if (TransactionIdFollowsOrEquals(curXid, xidWarnLimit) && !InRecovery)
|
||||
{
|
||||
char *oldest_datname = get_database_name(oldest_datoid);
|
||||
char *oldest_datname = get_database_name(oldest_datoid);
|
||||
|
||||
/*
|
||||
* Note: it's possible that get_database_name fails and returns NULL,
|
||||
@@ -355,11 +355,11 @@ SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
|
||||
*/
|
||||
if (oldest_datname)
|
||||
ereport(WARNING,
|
||||
(errmsg("database \"%s\" must be vacuumed within %u transactions",
|
||||
oldest_datname,
|
||||
xidWrapLimit - curXid),
|
||||
errhint("To avoid a database shutdown, execute a database-wide VACUUM in that database.\n"
|
||||
"You might also need to commit or roll back old prepared transactions.")));
|
||||
(errmsg("database \"%s\" must be vacuumed within %u transactions",
|
||||
oldest_datname,
|
||||
xidWrapLimit - curXid),
|
||||
errhint("To avoid a database shutdown, execute a database-wide VACUUM in that database.\n"
|
||||
"You might also need to commit or roll back old prepared transactions.")));
|
||||
else
|
||||
ereport(WARNING,
|
||||
(errmsg("database with OID %u must be vacuumed within %u transactions",
|
||||
@@ -377,7 +377,7 @@ SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
|
||||
* We primarily check whether oldestXidDB is valid. The cases we have in
|
||||
* mind are that that database was dropped, or the field was reset to zero
|
||||
* by pg_resetxlog. In either case we should force recalculation of the
|
||||
* wrap limit. Also do it if oldestXid is old enough to be forcing
|
||||
* wrap limit. Also do it if oldestXid is old enough to be forcing
|
||||
* autovacuums or other actions; this ensures we update our state as soon
|
||||
* as possible once extra overhead is being incurred.
|
||||
*/
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.288 2010/02/20 21:24:01 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.289 2010/02/26 02:00:34 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -139,9 +139,9 @@ typedef struct TransactionStateData
|
||||
int nChildXids; /* # of subcommitted child XIDs */
|
||||
int maxChildXids; /* allocated size of childXids[] */
|
||||
Oid prevUser; /* previous CurrentUserId setting */
|
||||
int prevSecContext; /* previous SecurityRestrictionContext */
|
||||
int prevSecContext; /* previous SecurityRestrictionContext */
|
||||
bool prevXactReadOnly; /* entry-time xact r/o state */
|
||||
bool startedInRecovery; /* did we start in recovery? */
|
||||
bool startedInRecovery; /* did we start in recovery? */
|
||||
struct TransactionStateData *parent; /* back link to parent */
|
||||
} TransactionStateData;
|
||||
|
||||
@@ -178,7 +178,7 @@ static TransactionStateData TopTransactionStateData = {
|
||||
* unreportedXids holds XIDs of all subtransactions that have not yet been
|
||||
* reported in a XLOG_XACT_ASSIGNMENT record.
|
||||
*/
|
||||
static int nUnreportedXids;
|
||||
static int nUnreportedXids;
|
||||
static TransactionId unreportedXids[PGPROC_MAX_CACHED_SUBXIDS];
|
||||
|
||||
static TransactionState CurrentTransactionState = &TopTransactionStateData;
|
||||
@@ -452,25 +452,28 @@ AssignTransactionId(TransactionState s)
|
||||
* include the top-level xid and all the subxids that have not yet been
|
||||
* reported using XLOG_XACT_ASSIGNMENT records.
|
||||
*
|
||||
* This is required to limit the amount of shared memory required in a
|
||||
* hot standby server to keep track of in-progress XIDs. See notes for
|
||||
* This is required to limit the amount of shared memory required in a hot
|
||||
* standby server to keep track of in-progress XIDs. See notes for
|
||||
* RecordKnownAssignedTransactionIds().
|
||||
*
|
||||
* We don't keep track of the immediate parent of each subxid,
|
||||
* only the top-level transaction that each subxact belongs to. This
|
||||
* is correct in recovery only because aborted subtransactions are
|
||||
* separately WAL logged.
|
||||
* We don't keep track of the immediate parent of each subxid, only the
|
||||
* top-level transaction that each subxact belongs to. This is correct in
|
||||
* recovery only because aborted subtransactions are separately WAL
|
||||
* logged.
|
||||
*/
|
||||
if (isSubXact && XLogStandbyInfoActive())
|
||||
{
|
||||
unreportedXids[nUnreportedXids] = s->transactionId;
|
||||
nUnreportedXids++;
|
||||
|
||||
/* ensure this test matches similar one in RecoverPreparedTransactions() */
|
||||
/*
|
||||
* ensure this test matches similar one in
|
||||
* RecoverPreparedTransactions()
|
||||
*/
|
||||
if (nUnreportedXids >= PGPROC_MAX_CACHED_SUBXIDS)
|
||||
{
|
||||
XLogRecData rdata[2];
|
||||
xl_xact_assignment xlrec;
|
||||
xl_xact_assignment xlrec;
|
||||
|
||||
/*
|
||||
* xtop is always set by now because we recurse up transaction
|
||||
@@ -899,6 +902,7 @@ RecordTransactionCommit(void)
|
||||
nchildren = xactGetCommittedChildren(&children);
|
||||
nmsgs = xactGetCommittedInvalidationMessages(&invalMessages,
|
||||
&RelcacheInitFileInval);
|
||||
|
||||
/*
|
||||
* If we haven't been assigned an XID yet, we neither can, nor do we want
|
||||
* to write a COMMIT record.
|
||||
@@ -1098,10 +1102,9 @@ static void
|
||||
AtCCI_LocalCache(void)
|
||||
{
|
||||
/*
|
||||
* Make any pending relation map changes visible. We must do this
|
||||
* before processing local sinval messages, so that the map changes
|
||||
* will get reflected into the relcache when relcache invals are
|
||||
* processed.
|
||||
* Make any pending relation map changes visible. We must do this before
|
||||
* processing local sinval messages, so that the map changes will get
|
||||
* reflected into the relcache when relcache invals are processed.
|
||||
*/
|
||||
AtCCI_RelationMap();
|
||||
|
||||
@@ -1227,9 +1230,9 @@ AtSubCommit_childXids(void)
|
||||
*
|
||||
* Note: We rely on the fact that the XID of a child always follows that
|
||||
* of its parent. By copying the XID of this subtransaction before the
|
||||
* XIDs of its children, we ensure that the array stays ordered.
|
||||
* Likewise, all XIDs already in the array belong to subtransactions
|
||||
* started and subcommitted before us, so their XIDs must precede ours.
|
||||
* XIDs of its children, we ensure that the array stays ordered. Likewise,
|
||||
* all XIDs already in the array belong to subtransactions started and
|
||||
* subcommitted before us, so their XIDs must precede ours.
|
||||
*/
|
||||
s->parent->childXids[s->parent->nChildXids] = s->transactionId;
|
||||
|
||||
@@ -1457,10 +1460,10 @@ AtSubAbort_childXids(void)
|
||||
s->maxChildXids = 0;
|
||||
|
||||
/*
|
||||
* We could prune the unreportedXids array here. But we don't bother.
|
||||
* That would potentially reduce number of XLOG_XACT_ASSIGNMENT records
|
||||
* but it would likely introduce more CPU time into the more common
|
||||
* paths, so we choose not to do that.
|
||||
* We could prune the unreportedXids array here. But we don't bother. That
|
||||
* would potentially reduce number of XLOG_XACT_ASSIGNMENT records but it
|
||||
* would likely introduce more CPU time into the more common paths, so we
|
||||
* choose not to do that.
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -2162,7 +2165,7 @@ AbortTransaction(void)
|
||||
/*
|
||||
* do abort processing
|
||||
*/
|
||||
AfterTriggerEndXact(false); /* 'false' means it's abort */
|
||||
AfterTriggerEndXact(false); /* 'false' means it's abort */
|
||||
AtAbort_Portals();
|
||||
AtEOXact_LargeObject(false);
|
||||
AtAbort_Notify();
|
||||
@@ -4362,9 +4365,9 @@ xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid, XLogRecPtr lsn)
|
||||
/*
|
||||
* Make sure nextXid is beyond any XID mentioned in the record.
|
||||
*
|
||||
* We don't expect anyone else to modify nextXid, hence we
|
||||
* don't need to hold a lock while checking this. We still acquire
|
||||
* the lock to modify it, though.
|
||||
* We don't expect anyone else to modify nextXid, hence we don't need to
|
||||
* hold a lock while checking this. We still acquire the lock to modify
|
||||
* it, though.
|
||||
*/
|
||||
if (TransactionIdFollowsOrEquals(max_xid,
|
||||
ShmemVariableCache->nextXid))
|
||||
@@ -4400,8 +4403,8 @@ xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid, XLogRecPtr lsn)
|
||||
* protocol during recovery to provide information on database
|
||||
* consistency for when users try to set hint bits. It is important
|
||||
* that we do not set hint bits until the minRecoveryPoint is past
|
||||
* this commit record. This ensures that if we crash we don't see
|
||||
* hint bits set on changes made by transactions that haven't yet
|
||||
* this commit record. This ensures that if we crash we don't see hint
|
||||
* bits set on changes made by transactions that haven't yet
|
||||
* recovered. It's unlikely but it's good to be safe.
|
||||
*/
|
||||
TransactionIdAsyncCommitTree(xid, xlrec->nsubxacts, sub_xids, lsn);
|
||||
@@ -4413,17 +4416,17 @@ xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid, XLogRecPtr lsn)
|
||||
|
||||
/*
|
||||
* Send any cache invalidations attached to the commit. We must
|
||||
* maintain the same order of invalidation then release locks
|
||||
* as occurs in .
|
||||
* maintain the same order of invalidation then release locks as
|
||||
* occurs in .
|
||||
*/
|
||||
ProcessCommittedInvalidationMessages(inval_msgs, xlrec->nmsgs,
|
||||
XactCompletionRelcacheInitFileInval(xlrec),
|
||||
xlrec->dbId, xlrec->tsId);
|
||||
XactCompletionRelcacheInitFileInval(xlrec),
|
||||
xlrec->dbId, xlrec->tsId);
|
||||
|
||||
/*
|
||||
* Release locks, if any. We do this for both two phase and normal
|
||||
* one phase transactions. In effect we are ignoring the prepare
|
||||
* phase and just going straight to lock release.
|
||||
* Release locks, if any. We do this for both two phase and normal one
|
||||
* phase transactions. In effect we are ignoring the prepare phase and
|
||||
* just going straight to lock release.
|
||||
*/
|
||||
StandbyReleaseLockTree(xid, xlrec->nsubxacts, sub_xids);
|
||||
}
|
||||
@@ -4446,15 +4449,16 @@ xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid, XLogRecPtr lsn)
|
||||
}
|
||||
|
||||
/*
|
||||
* We issue an XLogFlush() for the same reason we emit ForceSyncCommit() in
|
||||
* normal operation. For example, in DROP DATABASE, we delete all the files
|
||||
* belonging to the database, and then commit the transaction. If we crash
|
||||
* after all the files have been deleted but before the commit, you have an
|
||||
* entry in pg_database without any files. To minimize the window for that,
|
||||
* we use ForceSyncCommit() to rush the commit record to disk as quick as
|
||||
* possible. We have the same window during recovery, and forcing an
|
||||
* XLogFlush() (which updates minRecoveryPoint during recovery) helps
|
||||
* to reduce that problem window, for any user that requested ForceSyncCommit().
|
||||
* We issue an XLogFlush() for the same reason we emit ForceSyncCommit()
|
||||
* in normal operation. For example, in DROP DATABASE, we delete all the
|
||||
* files belonging to the database, and then commit the transaction. If we
|
||||
* crash after all the files have been deleted but before the commit, you
|
||||
* have an entry in pg_database without any files. To minimize the window
|
||||
* for that, we use ForceSyncCommit() to rush the commit record to disk as
|
||||
* quick as possible. We have the same window during recovery, and forcing
|
||||
* an XLogFlush() (which updates minRecoveryPoint during recovery) helps
|
||||
* to reduce that problem window, for any user that requested
|
||||
* ForceSyncCommit().
|
||||
*/
|
||||
if (XactCompletionForceSyncCommit(xlrec))
|
||||
XLogFlush(lsn);
|
||||
@@ -4480,9 +4484,11 @@ xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
|
||||
max_xid = TransactionIdLatest(xid, xlrec->nsubxacts, sub_xids);
|
||||
|
||||
/* Make sure nextXid is beyond any XID mentioned in the record */
|
||||
/* We don't expect anyone else to modify nextXid, hence we
|
||||
* don't need to hold a lock while checking this. We still acquire
|
||||
* the lock to modify it, though.
|
||||
|
||||
/*
|
||||
* We don't expect anyone else to modify nextXid, hence we don't need to
|
||||
* hold a lock while checking this. We still acquire the lock to modify
|
||||
* it, though.
|
||||
*/
|
||||
if (TransactionIdFollowsOrEquals(max_xid,
|
||||
ShmemVariableCache->nextXid))
|
||||
@@ -4496,12 +4502,13 @@ xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
|
||||
if (InHotStandby)
|
||||
{
|
||||
/*
|
||||
* If a transaction completion record arrives that has as-yet unobserved
|
||||
* subtransactions then this will not have been fully handled by the call
|
||||
* to RecordKnownAssignedTransactionIds() in the main recovery loop in
|
||||
* xlog.c. So we need to do bookkeeping again to cover that case. This is
|
||||
* confusing and it is easy to think this call is irrelevant, which has
|
||||
* happened three times in development already. Leave it in.
|
||||
* If a transaction completion record arrives that has as-yet
|
||||
* unobserved subtransactions then this will not have been fully
|
||||
* handled by the call to RecordKnownAssignedTransactionIds() in the
|
||||
* main recovery loop in xlog.c. So we need to do bookkeeping again to
|
||||
* cover that case. This is confusing and it is easy to think this
|
||||
* call is irrelevant, which has happened three times in development
|
||||
* already. Leave it in.
|
||||
*/
|
||||
RecordKnownAssignedTransactionIds(max_xid);
|
||||
}
|
||||
@@ -4631,8 +4638,8 @@ xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
|
||||
msgs = (SharedInvalidationMessage *) &xacts[xlrec->nsubxacts];
|
||||
|
||||
if (XactCompletionRelcacheInitFileInval(xlrec))
|
||||
appendStringInfo(buf, "; relcache init file inval dbid %u tsid %u",
|
||||
xlrec->dbId, xlrec->tsId);
|
||||
appendStringInfo(buf, "; relcache init file inval dbid %u tsid %u",
|
||||
xlrec->dbId, xlrec->tsId);
|
||||
|
||||
appendStringInfo(buf, "; inval msgs:");
|
||||
for (i = 0; i < xlrec->nmsgs; i++)
|
||||
@@ -4738,8 +4745,8 @@ xact_desc(StringInfo buf, uint8 xl_info, char *rec)
|
||||
|
||||
/*
|
||||
* Note that we ignore the WAL record's xid, since we're more
|
||||
* interested in the top-level xid that issued the record
|
||||
* and which xids are being reported here.
|
||||
* interested in the top-level xid that issued the record and which
|
||||
* xids are being reported here.
|
||||
*/
|
||||
appendStringInfo(buf, "xid assignment xtop %u: ", xlrec->xtop);
|
||||
xact_desc_assignment(buf, xlrec);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.378 2010/02/25 02:17:50 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.379 2010/02/26 02:00:35 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -70,7 +70,7 @@ int XLOGbuffers = 8;
|
||||
int XLogArchiveTimeout = 0;
|
||||
bool XLogArchiveMode = false;
|
||||
char *XLogArchiveCommand = NULL;
|
||||
bool XLogRequestRecoveryConnections = true;
|
||||
bool XLogRequestRecoveryConnections = true;
|
||||
int MaxStandbyDelay = 30;
|
||||
bool fullPageWrites = true;
|
||||
bool log_checkpoints = false;
|
||||
@@ -140,9 +140,9 @@ TimeLineID ThisTimeLineID = 0;
|
||||
bool InRecovery = false;
|
||||
|
||||
/* Are we in Hot Standby mode? Only valid in startup process, see xlog.h */
|
||||
HotStandbyState standbyState = STANDBY_DISABLED;
|
||||
HotStandbyState standbyState = STANDBY_DISABLED;
|
||||
|
||||
static XLogRecPtr LastRec;
|
||||
static XLogRecPtr LastRec;
|
||||
|
||||
/*
|
||||
* Local copy of SharedRecoveryInProgress variable. True actually means "not
|
||||
@@ -156,7 +156,7 @@ static bool LocalRecoveryInProgress = true;
|
||||
* 0: unconditionally not allowed to insert XLOG
|
||||
* -1: must check RecoveryInProgress(); disallow until it is false
|
||||
* Most processes start with -1 and transition to 1 after seeing that recovery
|
||||
* is not in progress. But we can also force the value for special cases.
|
||||
* is not in progress. But we can also force the value for special cases.
|
||||
* The coding in XLogInsertAllowed() depends on the first two of these states
|
||||
* being numerically the same as bool true and false.
|
||||
*/
|
||||
@@ -181,7 +181,7 @@ static TimestampTz recoveryLastXTime = 0;
|
||||
/* options taken from recovery.conf for XLOG streaming */
|
||||
static bool StandbyMode = false;
|
||||
static char *PrimaryConnInfo = NULL;
|
||||
char *TriggerFile = NULL;
|
||||
char *TriggerFile = NULL;
|
||||
|
||||
/* if recoveryStopsHere returns true, it saves actual stop xid/time here */
|
||||
static TransactionId recoveryStopXid;
|
||||
@@ -389,7 +389,7 @@ typedef struct XLogCtlData
|
||||
/* end+1 of the last record replayed (or being replayed) */
|
||||
XLogRecPtr replayEndRecPtr;
|
||||
/* timestamp of last record replayed (or being replayed) */
|
||||
TimestampTz recoveryLastXTime;
|
||||
TimestampTz recoveryLastXTime;
|
||||
/* end+1 of the last record replayed */
|
||||
XLogRecPtr recoveryLastRecPtr;
|
||||
|
||||
@@ -456,6 +456,7 @@ static uint32 readId = 0;
|
||||
static uint32 readSeg = 0;
|
||||
static uint32 readOff = 0;
|
||||
static uint32 readLen = 0;
|
||||
|
||||
/* Is the currently open segment being streamed from primary? */
|
||||
static bool readStreamed = false;
|
||||
|
||||
@@ -510,9 +511,9 @@ static void XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch);
|
||||
static bool InstallXLogFileSegment(uint32 *log, uint32 *seg, char *tmppath,
|
||||
bool find_free, int *max_advance,
|
||||
bool use_lock);
|
||||
static int XLogFileRead(uint32 log, uint32 seg, int emode, TimeLineID tli,
|
||||
static int XLogFileRead(uint32 log, uint32 seg, int emode, TimeLineID tli,
|
||||
bool fromArchive, bool notexistOk);
|
||||
static int XLogFileReadAnyTLI(uint32 log, uint32 seg, int emode,
|
||||
static int XLogFileReadAnyTLI(uint32 log, uint32 seg, int emode,
|
||||
bool fromArchive);
|
||||
static bool XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt,
|
||||
bool randAccess);
|
||||
@@ -1867,10 +1868,10 @@ UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
|
||||
* to not need a valid 'lsn' value.
|
||||
*
|
||||
* Another important reason for doing it this way is that the passed
|
||||
* 'lsn' value could be bogus, i.e., past the end of available WAL,
|
||||
* if the caller got it from a corrupted heap page. Accepting such
|
||||
* a value as the min recovery point would prevent us from coming up
|
||||
* at all. Instead, we just log a warning and continue with recovery.
|
||||
* 'lsn' value could be bogus, i.e., past the end of available WAL, if
|
||||
* the caller got it from a corrupted heap page. Accepting such a
|
||||
* value as the min recovery point would prevent us from coming up at
|
||||
* all. Instead, we just log a warning and continue with recovery.
|
||||
* (See also the comments about corrupt LSNs in XLogFlush.)
|
||||
*/
|
||||
SpinLockAcquire(&xlogctl->info_lck);
|
||||
@@ -1879,7 +1880,7 @@ UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
|
||||
|
||||
if (!force && XLByteLT(newMinRecoveryPoint, lsn))
|
||||
elog(WARNING,
|
||||
"xlog min recovery request %X/%X is past current point %X/%X",
|
||||
"xlog min recovery request %X/%X is past current point %X/%X",
|
||||
lsn.xlogid, lsn.xrecoff,
|
||||
newMinRecoveryPoint.xlogid, newMinRecoveryPoint.xrecoff);
|
||||
|
||||
@@ -1912,10 +1913,10 @@ XLogFlush(XLogRecPtr record)
|
||||
|
||||
/*
|
||||
* During REDO, we are reading not writing WAL. Therefore, instead of
|
||||
* trying to flush the WAL, we should update minRecoveryPoint instead.
|
||||
* We test XLogInsertAllowed(), not InRecovery, because we need the
|
||||
* bgwriter to act this way too, and because when the bgwriter tries
|
||||
* to write the end-of-recovery checkpoint, it should indeed flush.
|
||||
* trying to flush the WAL, we should update minRecoveryPoint instead. We
|
||||
* test XLogInsertAllowed(), not InRecovery, because we need the bgwriter
|
||||
* to act this way too, and because when the bgwriter tries to write the
|
||||
* end-of-recovery checkpoint, it should indeed flush.
|
||||
*/
|
||||
if (!XLogInsertAllowed())
|
||||
{
|
||||
@@ -2007,16 +2008,16 @@ XLogFlush(XLogRecPtr record)
|
||||
* the whole system due to corruption on one data page. In particular, if
|
||||
* the bad page is encountered again during recovery then we would be
|
||||
* unable to restart the database at all! (This scenario actually
|
||||
* happened in the field several times with 7.1 releases.) As of 8.4,
|
||||
* bad LSNs encountered during recovery are UpdateMinRecoveryPoint's
|
||||
* problem; the only time we can reach here during recovery is while
|
||||
* flushing the end-of-recovery checkpoint record, and we don't expect
|
||||
* that to have a bad LSN.
|
||||
* happened in the field several times with 7.1 releases.) As of 8.4, bad
|
||||
* LSNs encountered during recovery are UpdateMinRecoveryPoint's problem;
|
||||
* the only time we can reach here during recovery is while flushing the
|
||||
* end-of-recovery checkpoint record, and we don't expect that to have a
|
||||
* bad LSN.
|
||||
*
|
||||
* Note that for calls from xact.c, the ERROR will
|
||||
* be promoted to PANIC since xact.c calls this routine inside a critical
|
||||
* section. However, calls from bufmgr.c are not within critical sections
|
||||
* and so we will not force a restart for a bad LSN on a data page.
|
||||
* Note that for calls from xact.c, the ERROR will be promoted to PANIC
|
||||
* since xact.c calls this routine inside a critical section. However,
|
||||
* calls from bufmgr.c are not within critical sections and so we will not
|
||||
* force a restart for a bad LSN on a data page.
|
||||
*/
|
||||
if (XLByteLT(LogwrtResult.Flush, record))
|
||||
elog(ERROR,
|
||||
@@ -2136,9 +2137,10 @@ XLogNeedsFlush(XLogRecPtr record)
|
||||
LWLockRelease(ControlFileLock);
|
||||
|
||||
/*
|
||||
* An invalid minRecoveryPoint means that we need to recover all the WAL,
|
||||
* i.e., we're doing crash recovery. We never modify the control file's
|
||||
* value in that case, so we can short-circuit future checks here too.
|
||||
* An invalid minRecoveryPoint means that we need to recover all the
|
||||
* WAL, i.e., we're doing crash recovery. We never modify the control
|
||||
* file's value in that case, so we can short-circuit future checks
|
||||
* here too.
|
||||
*/
|
||||
if (minRecoveryPoint.xlogid == 0 && minRecoveryPoint.xrecoff == 0)
|
||||
updateMinRecoveryPoint = false;
|
||||
@@ -2572,46 +2574,46 @@ XLogFileRead(uint32 log, uint32 seg, int emode, TimeLineID tli,
|
||||
char path[MAXPGPATH];
|
||||
int fd;
|
||||
|
||||
XLogFileName(xlogfname, tli, log, seg);
|
||||
XLogFileName(xlogfname, tli, log, seg);
|
||||
|
||||
if (fromArchive)
|
||||
{
|
||||
/* Report recovery progress in PS display */
|
||||
snprintf(activitymsg, sizeof(activitymsg), "waiting for %s",
|
||||
xlogfname);
|
||||
set_ps_display(activitymsg, false);
|
||||
if (fromArchive)
|
||||
{
|
||||
/* Report recovery progress in PS display */
|
||||
snprintf(activitymsg, sizeof(activitymsg), "waiting for %s",
|
||||
xlogfname);
|
||||
set_ps_display(activitymsg, false);
|
||||
|
||||
restoredFromArchive = RestoreArchivedFile(path, xlogfname,
|
||||
"RECOVERYXLOG",
|
||||
XLogSegSize);
|
||||
if (!restoredFromArchive)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
XLogFilePath(path, tli, log, seg);
|
||||
restoredFromArchive = false;
|
||||
}
|
||||
restoredFromArchive = RestoreArchivedFile(path, xlogfname,
|
||||
"RECOVERYXLOG",
|
||||
XLogSegSize);
|
||||
if (!restoredFromArchive)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
XLogFilePath(path, tli, log, seg);
|
||||
restoredFromArchive = false;
|
||||
}
|
||||
|
||||
fd = BasicOpenFile(path, O_RDONLY | PG_BINARY, 0);
|
||||
if (fd >= 0)
|
||||
{
|
||||
/* Success! */
|
||||
curFileTLI = tli;
|
||||
fd = BasicOpenFile(path, O_RDONLY | PG_BINARY, 0);
|
||||
if (fd >= 0)
|
||||
{
|
||||
/* Success! */
|
||||
curFileTLI = tli;
|
||||
|
||||
/* Report recovery progress in PS display */
|
||||
snprintf(activitymsg, sizeof(activitymsg), "recovering %s",
|
||||
xlogfname);
|
||||
set_ps_display(activitymsg, false);
|
||||
/* Report recovery progress in PS display */
|
||||
snprintf(activitymsg, sizeof(activitymsg), "recovering %s",
|
||||
xlogfname);
|
||||
set_ps_display(activitymsg, false);
|
||||
|
||||
return fd;
|
||||
}
|
||||
if (errno != ENOENT || !notfoundOk) /* unexpected failure? */
|
||||
ereport(PANIC,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not open file \"%s\" (log file %u, segment %u): %m",
|
||||
path, log, seg)));
|
||||
return -1;
|
||||
return fd;
|
||||
}
|
||||
if (errno != ENOENT || !notfoundOk) /* unexpected failure? */
|
||||
ereport(PANIC,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not open file \"%s\" (log file %u, segment %u): %m",
|
||||
path, log, seg)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2653,8 +2655,8 @@ XLogFileReadAnyTLI(uint32 log, uint32 seg, int emode, bool fromArchive)
|
||||
* If not in StandbyMode, fall back to searching pg_xlog. In
|
||||
* StandbyMode we're streaming segments from the primary to pg_xlog,
|
||||
* and we mustn't confuse the (possibly partial) segments in pg_xlog
|
||||
* with complete segments ready to be applied. We rather wait for
|
||||
* the records to arrive through streaming.
|
||||
* with complete segments ready to be applied. We rather wait for the
|
||||
* records to arrive through streaming.
|
||||
*/
|
||||
if (!StandbyMode && fromArchive)
|
||||
{
|
||||
@@ -2685,8 +2687,8 @@ XLogFileClose(void)
|
||||
/*
|
||||
* WAL segment files will not be re-read in normal operation, so we advise
|
||||
* the OS to release any cached pages. But do not do so if WAL archiving
|
||||
* or streaming is active, because archiver and walsender process could use
|
||||
* the cache to read the WAL segment.
|
||||
* or streaming is active, because archiver and walsender process could
|
||||
* use the cache to read the WAL segment.
|
||||
*/
|
||||
#if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
|
||||
if (!XLogIsNeeded())
|
||||
@@ -2893,7 +2895,7 @@ RestoreArchivedFile(char *path, const char *xlogfname,
|
||||
{
|
||||
if (expectedSize > 0 && stat_buf.st_size != expectedSize)
|
||||
{
|
||||
int elevel;
|
||||
int elevel;
|
||||
|
||||
/*
|
||||
* If we find a partial file in standby mode, we assume it's
|
||||
@@ -2901,11 +2903,11 @@ RestoreArchivedFile(char *path, const char *xlogfname,
|
||||
* trying.
|
||||
*
|
||||
* Otherwise treat a wrong-sized file as FATAL to ensure the
|
||||
* DBA would notice it, but is that too strong? We could try
|
||||
* DBA would notice it, but is that too strong? We could try
|
||||
* to plow ahead with a local copy of the file ... but the
|
||||
* problem is that there probably isn't one, and we'd
|
||||
* incorrectly conclude we've reached the end of WAL and
|
||||
* we're done recovering ...
|
||||
* incorrectly conclude we've reached the end of WAL and we're
|
||||
* done recovering ...
|
||||
*/
|
||||
if (StandbyMode && stat_buf.st_size < expectedSize)
|
||||
elevel = DEBUG1;
|
||||
@@ -2975,6 +2977,7 @@ RestoreArchivedFile(char *path, const char *xlogfname,
|
||||
xlogfname, rc)));
|
||||
|
||||
not_available:
|
||||
|
||||
/*
|
||||
* if an archived file is not available, there might still be a version of
|
||||
* this file in XLOGDIR, so return that as the filename to open.
|
||||
@@ -3141,6 +3144,7 @@ RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr)
|
||||
struct dirent *xlde;
|
||||
char lastoff[MAXFNAMELEN];
|
||||
char path[MAXPGPATH];
|
||||
|
||||
#ifdef WIN32
|
||||
char newpath[MAXPGPATH];
|
||||
#endif
|
||||
@@ -3218,21 +3222,22 @@ RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr)
|
||||
else
|
||||
{
|
||||
/* No need for any more future segments... */
|
||||
int rc;
|
||||
int rc;
|
||||
|
||||
ereport(DEBUG2,
|
||||
(errmsg("removing transaction log file \"%s\"",
|
||||
xlde->d_name)));
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
/*
|
||||
* On Windows, if another process (e.g another backend)
|
||||
* holds the file open in FILE_SHARE_DELETE mode, unlink
|
||||
* will succeed, but the file will still show up in
|
||||
* directory listing until the last handle is closed.
|
||||
* To avoid confusing the lingering deleted file for a
|
||||
* live WAL file that needs to be archived, rename it
|
||||
* before deleting it.
|
||||
* directory listing until the last handle is closed. To
|
||||
* avoid confusing the lingering deleted file for a live
|
||||
* WAL file that needs to be archived, rename it before
|
||||
* deleting it.
|
||||
*
|
||||
* If another process holds the file open without
|
||||
* FILE_SHARE_DELETE flag, rename will fail. We'll try
|
||||
@@ -3553,8 +3558,8 @@ ReadRecord(XLogRecPtr *RecPtr, int emode_arg, bool fetching_ckpt)
|
||||
RecPtr = &tmpRecPtr;
|
||||
|
||||
/*
|
||||
* Align recptr to next page if no more records can fit on the
|
||||
* current page.
|
||||
* Align recptr to next page if no more records can fit on the current
|
||||
* page.
|
||||
*/
|
||||
if (XLOG_BLCKSZ - (RecPtr->xrecoff % XLOG_BLCKSZ) < SizeOfXLogRecord)
|
||||
{
|
||||
@@ -5093,8 +5098,8 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg)
|
||||
UpdateMinRecoveryPoint(InvalidXLogRecPtr, true);
|
||||
|
||||
/*
|
||||
* If the ending log segment is still open, close it (to avoid
|
||||
* problems on Windows with trying to rename or delete an open file).
|
||||
* If the ending log segment is still open, close it (to avoid problems on
|
||||
* Windows with trying to rename or delete an open file).
|
||||
*/
|
||||
if (readFile >= 0)
|
||||
{
|
||||
@@ -5376,17 +5381,17 @@ CheckRequiredParameterValues(CheckPoint checkPoint)
|
||||
{
|
||||
/* We ignore autovacuum_max_workers when we make this test. */
|
||||
RecoveryRequiresIntParameter("max_connections",
|
||||
MaxConnections, checkPoint.MaxConnections);
|
||||
MaxConnections, checkPoint.MaxConnections);
|
||||
|
||||
RecoveryRequiresIntParameter("max_prepared_xacts",
|
||||
max_prepared_xacts, checkPoint.max_prepared_xacts);
|
||||
max_prepared_xacts, checkPoint.max_prepared_xacts);
|
||||
RecoveryRequiresIntParameter("max_locks_per_xact",
|
||||
max_locks_per_xact, checkPoint.max_locks_per_xact);
|
||||
max_locks_per_xact, checkPoint.max_locks_per_xact);
|
||||
|
||||
if (!checkPoint.XLogStandbyInfoMode)
|
||||
ereport(ERROR,
|
||||
(errmsg("recovery connections cannot start because the recovery_connections "
|
||||
"parameter is disabled on the WAL source server")));
|
||||
(errmsg("recovery connections cannot start because the recovery_connections "
|
||||
"parameter is disabled on the WAL source server")));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5464,12 +5469,12 @@ StartupXLOG(void)
|
||||
ValidateXLOGDirectoryStructure();
|
||||
|
||||
/*
|
||||
* Clear out any old relcache cache files. This is *necessary* if we
|
||||
* do any WAL replay, since that would probably result in the cache files
|
||||
* being out of sync with database reality. In theory we could leave
|
||||
* them in place if the database had been cleanly shut down, but it
|
||||
* seems safest to just remove them always and let them be rebuilt
|
||||
* during the first backend startup.
|
||||
* Clear out any old relcache cache files. This is *necessary* if we do
|
||||
* any WAL replay, since that would probably result in the cache files
|
||||
* being out of sync with database reality. In theory we could leave them
|
||||
* in place if the database had been cleanly shut down, but it seems
|
||||
* safest to just remove them always and let them be rebuilt during the
|
||||
* first backend startup.
|
||||
*/
|
||||
RelationCacheInitFileRemove();
|
||||
|
||||
@@ -5648,8 +5653,8 @@ StartupXLOG(void)
|
||||
{
|
||||
if (recoveryTargetExact)
|
||||
ereport(LOG,
|
||||
(errmsg("starting point-in-time recovery to XID %u",
|
||||
recoveryTargetXid)));
|
||||
(errmsg("starting point-in-time recovery to XID %u",
|
||||
recoveryTargetXid)));
|
||||
else
|
||||
ereport(LOG,
|
||||
(errmsg("starting point-in-time recovery to %s",
|
||||
@@ -5676,6 +5681,7 @@ StartupXLOG(void)
|
||||
if (XLByteLT(ControlFile->minRecoveryPoint, checkPoint.redo))
|
||||
ControlFile->minRecoveryPoint = checkPoint.redo;
|
||||
}
|
||||
|
||||
/*
|
||||
* set backupStartupPoint if we're starting archive recovery from a
|
||||
* base backup
|
||||
@@ -5714,14 +5720,14 @@ StartupXLOG(void)
|
||||
|
||||
/*
|
||||
* Initialize recovery connections, if enabled. We won't let backends
|
||||
* in yet, not until we've reached the min recovery point specified
|
||||
* in control file and we've established a recovery snapshot from a
|
||||
* in yet, not until we've reached the min recovery point specified in
|
||||
* control file and we've established a recovery snapshot from a
|
||||
* running-xacts WAL record.
|
||||
*/
|
||||
if (InArchiveRecovery && XLogRequestRecoveryConnections)
|
||||
{
|
||||
TransactionId *xids;
|
||||
int nxids;
|
||||
int nxids;
|
||||
|
||||
CheckRequiredParameterValues(checkPoint);
|
||||
|
||||
@@ -5814,7 +5820,7 @@ StartupXLOG(void)
|
||||
{
|
||||
#ifdef WAL_DEBUG
|
||||
if (XLOG_DEBUG ||
|
||||
(rmid == RM_XACT_ID && trace_recovery_messages <= DEBUG2) ||
|
||||
(rmid == RM_XACT_ID && trace_recovery_messages <= DEBUG2) ||
|
||||
(rmid != RM_XACT_ID && trace_recovery_messages <= DEBUG3))
|
||||
{
|
||||
StringInfoData buf;
|
||||
@@ -5845,14 +5851,14 @@ StartupXLOG(void)
|
||||
{
|
||||
reachedMinRecoveryPoint = true;
|
||||
ereport(LOG,
|
||||
(errmsg("consistent recovery state reached at %X/%X",
|
||||
EndRecPtr.xlogid, EndRecPtr.xrecoff)));
|
||||
(errmsg("consistent recovery state reached at %X/%X",
|
||||
EndRecPtr.xlogid, EndRecPtr.xrecoff)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Have we got a valid starting snapshot that will allow
|
||||
* queries to be run? If so, we can tell postmaster that
|
||||
* the database is consistent now, enabling connections.
|
||||
* queries to be run? If so, we can tell postmaster that the
|
||||
* database is consistent now, enabling connections.
|
||||
*/
|
||||
if (standbyState == STANDBY_SNAPSHOT_READY &&
|
||||
!backendsAllowed &&
|
||||
@@ -5950,9 +5956,8 @@ StartupXLOG(void)
|
||||
|
||||
/*
|
||||
* We are now done reading the xlog from stream. Turn off streaming
|
||||
* recovery to force fetching the files (which would be required
|
||||
* at end of recovery, e.g., timeline history file) from archive or
|
||||
* pg_xlog.
|
||||
* recovery to force fetching the files (which would be required at end of
|
||||
* recovery, e.g., timeline history file) from archive or pg_xlog.
|
||||
*/
|
||||
StandbyMode = false;
|
||||
|
||||
@@ -6155,8 +6160,8 @@ StartupXLOG(void)
|
||||
TransactionIdRetreat(ShmemVariableCache->latestCompletedXid);
|
||||
|
||||
/*
|
||||
* Start up the commit log and related stuff, too. In hot standby mode
|
||||
* we did this already before WAL replay.
|
||||
* Start up the commit log and related stuff, too. In hot standby mode we
|
||||
* did this already before WAL replay.
|
||||
*/
|
||||
if (standbyState == STANDBY_DISABLED)
|
||||
{
|
||||
@@ -6194,7 +6199,7 @@ StartupXLOG(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* All done. Allow backends to write WAL. (Although the bool flag is
|
||||
* All done. Allow backends to write WAL. (Although the bool flag is
|
||||
* probably atomic in itself, we use the info_lck here to ensure that
|
||||
* there are no race conditions concerning visibility of other recent
|
||||
* updates to shared memory.)
|
||||
@@ -6222,9 +6227,9 @@ bool
|
||||
RecoveryInProgress(void)
|
||||
{
|
||||
/*
|
||||
* We check shared state each time only until we leave recovery mode.
|
||||
* We can't re-enter recovery, so there's no need to keep checking after
|
||||
* the shared variable has once been seen false.
|
||||
* We check shared state each time only until we leave recovery mode. We
|
||||
* can't re-enter recovery, so there's no need to keep checking after the
|
||||
* shared variable has once been seen false.
|
||||
*/
|
||||
if (!LocalRecoveryInProgress)
|
||||
return false;
|
||||
@@ -6241,7 +6246,7 @@ RecoveryInProgress(void)
|
||||
/*
|
||||
* Initialize TimeLineID and RedoRecPtr when we discover that recovery
|
||||
* is finished. InitPostgres() relies upon this behaviour to ensure
|
||||
* that InitXLOGAccess() is called at backend startup. (If you change
|
||||
* that InitXLOGAccess() is called at backend startup. (If you change
|
||||
* this, see also LocalSetXLogInsertAllowed.)
|
||||
*/
|
||||
if (!LocalRecoveryInProgress)
|
||||
@@ -6262,9 +6267,9 @@ bool
|
||||
XLogInsertAllowed(void)
|
||||
{
|
||||
/*
|
||||
* If value is "unconditionally true" or "unconditionally false",
|
||||
* just return it. This provides the normal fast path once recovery
|
||||
* is known done.
|
||||
* If value is "unconditionally true" or "unconditionally false", just
|
||||
* return it. This provides the normal fast path once recovery is known
|
||||
* done.
|
||||
*/
|
||||
if (LocalXLogInsertAllowed >= 0)
|
||||
return (bool) LocalXLogInsertAllowed;
|
||||
@@ -6276,8 +6281,8 @@ XLogInsertAllowed(void)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* On exit from recovery, reset to "unconditionally true", since there
|
||||
* is no need to keep checking.
|
||||
* On exit from recovery, reset to "unconditionally true", since there is
|
||||
* no need to keep checking.
|
||||
*/
|
||||
LocalXLogInsertAllowed = 1;
|
||||
return true;
|
||||
@@ -6938,9 +6943,9 @@ CreateCheckPoint(int flags)
|
||||
CheckPointGuts(checkPoint.redo, flags);
|
||||
|
||||
/*
|
||||
* Take a snapshot of running transactions and write this to WAL.
|
||||
* This allows us to reconstruct the state of running transactions
|
||||
* during archive recovery, if required. Skip, if this info disabled.
|
||||
* Take a snapshot of running transactions and write this to WAL. This
|
||||
* allows us to reconstruct the state of running transactions during
|
||||
* archive recovery, if required. Skip, if this info disabled.
|
||||
*
|
||||
* If we are shutting down, or Startup process is completing crash
|
||||
* recovery we don't need to write running xact data.
|
||||
@@ -6948,7 +6953,7 @@ CreateCheckPoint(int flags)
|
||||
* Update checkPoint.nextXid since we have a later value
|
||||
*/
|
||||
if (!shutdown && XLogStandbyInfoActive())
|
||||
LogStandbySnapshot(&checkPoint.oldestActiveXid, &checkPoint.nextXid);
|
||||
LogStandbySnapshot(&checkPoint.oldestActiveXid, &checkPoint.nextXid);
|
||||
else
|
||||
checkPoint.oldestActiveXid = InvalidTransactionId;
|
||||
|
||||
@@ -6970,18 +6975,18 @@ CreateCheckPoint(int flags)
|
||||
XLogFlush(recptr);
|
||||
|
||||
/*
|
||||
* We mustn't write any new WAL after a shutdown checkpoint, or it will
|
||||
* be overwritten at next startup. No-one should even try, this just
|
||||
* allows sanity-checking. In the case of an end-of-recovery checkpoint,
|
||||
* we want to just temporarily disable writing until the system has exited
|
||||
* We mustn't write any new WAL after a shutdown checkpoint, or it will be
|
||||
* overwritten at next startup. No-one should even try, this just allows
|
||||
* sanity-checking. In the case of an end-of-recovery checkpoint, we want
|
||||
* to just temporarily disable writing until the system has exited
|
||||
* recovery.
|
||||
*/
|
||||
if (shutdown)
|
||||
{
|
||||
if (flags & CHECKPOINT_END_OF_RECOVERY)
|
||||
LocalXLogInsertAllowed = -1; /* return to "check" state */
|
||||
LocalXLogInsertAllowed = -1; /* return to "check" state */
|
||||
else
|
||||
LocalXLogInsertAllowed = 0; /* never again write WAL */
|
||||
LocalXLogInsertAllowed = 0; /* never again write WAL */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -7036,18 +7041,17 @@ CreateCheckPoint(int flags)
|
||||
smgrpostckpt();
|
||||
|
||||
/*
|
||||
* If there's connected standby servers doing XLOG streaming, don't
|
||||
* delete XLOG files that have not been streamed to all of them yet.
|
||||
* This does nothing to prevent them from being deleted when the
|
||||
* standby is disconnected (e.g because of network problems), but at
|
||||
* least it avoids an open replication connection from failing because
|
||||
* of that.
|
||||
* If there's connected standby servers doing XLOG streaming, don't delete
|
||||
* XLOG files that have not been streamed to all of them yet. This does
|
||||
* nothing to prevent them from being deleted when the standby is
|
||||
* disconnected (e.g because of network problems), but at least it avoids
|
||||
* an open replication connection from failing because of that.
|
||||
*/
|
||||
if ((_logId || _logSeg) && MaxWalSenders > 0)
|
||||
{
|
||||
XLogRecPtr oldest;
|
||||
uint32 log;
|
||||
uint32 seg;
|
||||
XLogRecPtr oldest;
|
||||
uint32 log;
|
||||
uint32 seg;
|
||||
|
||||
oldest = GetOldestWALSendPointer();
|
||||
if (oldest.xlogid != 0 || oldest.xrecoff != 0)
|
||||
@@ -7055,15 +7059,15 @@ CreateCheckPoint(int flags)
|
||||
XLByteToSeg(oldest, log, seg);
|
||||
if (log < _logId || (log == _logId && seg < _logSeg))
|
||||
{
|
||||
_logId = log;
|
||||
_logSeg = seg;
|
||||
_logId = log;
|
||||
_logSeg = seg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete old log files (those no longer needed even for
|
||||
* previous checkpoint or the standbys in XLOG streaming).
|
||||
* Delete old log files (those no longer needed even for previous
|
||||
* checkpoint or the standbys in XLOG streaming).
|
||||
*/
|
||||
if (_logId || _logSeg)
|
||||
{
|
||||
@@ -7262,8 +7266,8 @@ CreateRestartPoint(int flags)
|
||||
/*
|
||||
* Update pg_control, using current time. Check that it still shows
|
||||
* IN_ARCHIVE_RECOVERY state and an older checkpoint, else do nothing;
|
||||
* this is a quick hack to make sure nothing really bad happens if
|
||||
* somehow we get here after the end-of-recovery checkpoint.
|
||||
* this is a quick hack to make sure nothing really bad happens if somehow
|
||||
* we get here after the end-of-recovery checkpoint.
|
||||
*/
|
||||
LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
|
||||
if (ControlFile->state == DB_IN_ARCHIVE_RECOVERY &&
|
||||
@@ -7312,9 +7316,9 @@ CreateRestartPoint(int flags)
|
||||
LogCheckpointEnd(true);
|
||||
|
||||
ereport((log_checkpoints ? LOG : DEBUG2),
|
||||
(errmsg("recovery restart point at %X/%X with latest known log time %s",
|
||||
lastCheckPoint.redo.xlogid, lastCheckPoint.redo.xrecoff,
|
||||
timestamptz_to_str(GetLatestXLogTime()))));
|
||||
(errmsg("recovery restart point at %X/%X with latest known log time %s",
|
||||
lastCheckPoint.redo.xlogid, lastCheckPoint.redo.xrecoff,
|
||||
timestamptz_to_str(GetLatestXLogTime()))));
|
||||
|
||||
LWLockRelease(CheckpointLock);
|
||||
return true;
|
||||
@@ -7522,6 +7526,7 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
|
||||
else if (info == XLOG_BACKUP_END)
|
||||
{
|
||||
XLogRecPtr startpoint;
|
||||
|
||||
memcpy(&startpoint, XLogRecGetData(record), sizeof(startpoint));
|
||||
|
||||
if (XLByteEQ(ControlFile->backupStartPoint, startpoint))
|
||||
@@ -7550,12 +7555,12 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
|
||||
if (InArchiveRecovery)
|
||||
{
|
||||
/*
|
||||
* Note: We don't print the reason string from the record,
|
||||
* because that gets added as a line using xlog_desc()
|
||||
* Note: We don't print the reason string from the record, because
|
||||
* that gets added as a line using xlog_desc()
|
||||
*/
|
||||
ereport(WARNING,
|
||||
(errmsg("unlogged operation performed, data may be missing"),
|
||||
errhint("This can happen if you temporarily disable archive_mode without taking a new base backup.")));
|
||||
(errmsg("unlogged operation performed, data may be missing"),
|
||||
errhint("This can happen if you temporarily disable archive_mode without taking a new base backup.")));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7601,7 +7606,7 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
|
||||
}
|
||||
else if (info == XLOG_BACKUP_END)
|
||||
{
|
||||
XLogRecPtr startpoint;
|
||||
XLogRecPtr startpoint;
|
||||
|
||||
memcpy(&startpoint, rec, sizeof(XLogRecPtr));
|
||||
appendStringInfo(buf, "backup end: %X/%X",
|
||||
@@ -7609,7 +7614,7 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
|
||||
}
|
||||
else if (info == XLOG_UNLOGGED)
|
||||
{
|
||||
char *reason = rec;
|
||||
char *reason = rec;
|
||||
|
||||
appendStringInfo(buf, "unlogged operation: %s", reason);
|
||||
}
|
||||
@@ -7649,7 +7654,7 @@ xlog_outrec(StringInfo buf, XLogRecord *record)
|
||||
static int
|
||||
get_sync_bit(int method)
|
||||
{
|
||||
int o_direct_flag = 0;
|
||||
int o_direct_flag = 0;
|
||||
|
||||
/* If fsync is disabled, never open in sync mode */
|
||||
if (!enableFsync)
|
||||
@@ -7658,11 +7663,11 @@ get_sync_bit(int method)
|
||||
/*
|
||||
* Optimize writes by bypassing kernel cache with O_DIRECT when using
|
||||
* O_SYNC, O_DSYNC or O_FSYNC. But only if archiving and streaming are
|
||||
* disabled, otherwise the archive command or walsender process will
|
||||
* read the WAL soon after writing it, which is guaranteed to cause a
|
||||
* physical read if we bypassed the kernel cache. We also skip the
|
||||
* posix_fadvise(POSIX_FADV_DONTNEED) call in XLogFileClose() for the
|
||||
* same reason.
|
||||
* disabled, otherwise the archive command or walsender process will read
|
||||
* the WAL soon after writing it, which is guaranteed to cause a physical
|
||||
* read if we bypassed the kernel cache. We also skip the
|
||||
* posix_fadvise(POSIX_FADV_DONTNEED) call in XLogFileClose() for the same
|
||||
* reason.
|
||||
*
|
||||
* Never use O_DIRECT in walreceiver process for similar reasons; the WAL
|
||||
* written by walreceiver is normally read by the startup process soon
|
||||
@@ -7985,7 +7990,7 @@ pg_stop_backup(PG_FUNCTION_ARGS)
|
||||
{
|
||||
XLogRecPtr startpoint;
|
||||
XLogRecPtr stoppoint;
|
||||
XLogRecData rdata;
|
||||
XLogRecData rdata;
|
||||
pg_time_t stamp_time;
|
||||
char strfbuf[128];
|
||||
char histfilepath[MAXPGPATH];
|
||||
@@ -8132,8 +8137,8 @@ pg_stop_backup(PG_FUNCTION_ARGS)
|
||||
*
|
||||
* We wait forever, since archive_command is supposed to work and we
|
||||
* assume the admin wanted his backup to work completely. If you don't
|
||||
* wish to wait, you can set statement_timeout. Also, some notices
|
||||
* are issued to clue in anyone who might be doing this interactively.
|
||||
* wish to wait, you can set statement_timeout. Also, some notices are
|
||||
* issued to clue in anyone who might be doing this interactively.
|
||||
*/
|
||||
XLByteToPrevSeg(stoppoint, _logId, _logSeg);
|
||||
XLogFileName(lastxlogfilename, ThisTimeLineID, _logId, _logSeg);
|
||||
@@ -8161,9 +8166,9 @@ pg_stop_backup(PG_FUNCTION_ARGS)
|
||||
ereport(WARNING,
|
||||
(errmsg("pg_stop_backup still waiting for all required WAL segments to be archived (%d seconds elapsed)",
|
||||
waits),
|
||||
errhint("Check that your archive_command is executing properly. "
|
||||
"pg_stop_backup can be cancelled safely, "
|
||||
"but the database backup will not be usable without all the WAL segments.")));
|
||||
errhint("Check that your archive_command is executing properly. "
|
||||
"pg_stop_backup can be cancelled safely, "
|
||||
"but the database backup will not be usable without all the WAL segments.")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8621,6 +8626,7 @@ HandleStartupProcInterrupts(void)
|
||||
got_SIGHUP = false;
|
||||
ProcessConfigFile(PGC_SIGHUP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if we were requested to exit without finishing recovery.
|
||||
*/
|
||||
@@ -8653,10 +8659,11 @@ StartupProcessMain(void)
|
||||
*/
|
||||
pqsignal(SIGHUP, StartupProcSigHupHandler); /* reload config file */
|
||||
pqsignal(SIGINT, SIG_IGN); /* ignore query cancel */
|
||||
pqsignal(SIGTERM, StartupProcShutdownHandler); /* request shutdown */
|
||||
pqsignal(SIGQUIT, startupproc_quickdie); /* hard crash time */
|
||||
pqsignal(SIGTERM, StartupProcShutdownHandler); /* request shutdown */
|
||||
pqsignal(SIGQUIT, startupproc_quickdie); /* hard crash time */
|
||||
if (XLogRequestRecoveryConnections)
|
||||
pqsignal(SIGALRM, handle_standby_sig_alarm); /* ignored unless InHotStandby */
|
||||
pqsignal(SIGALRM, handle_standby_sig_alarm); /* ignored unless
|
||||
* InHotStandby */
|
||||
else
|
||||
pqsignal(SIGALRM, SIG_IGN);
|
||||
pqsignal(SIGPIPE, SIG_IGN);
|
||||
@@ -8731,20 +8738,20 @@ XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt,
|
||||
{
|
||||
if (StandbyMode)
|
||||
{
|
||||
bool last_restore_failed = false;
|
||||
bool last_restore_failed = false;
|
||||
|
||||
/*
|
||||
* In standby mode, wait for the requested record to become
|
||||
* available, either via restore_command succeeding to restore
|
||||
* the segment, or via walreceiver having streamed the record.
|
||||
* available, either via restore_command succeeding to restore the
|
||||
* segment, or via walreceiver having streamed the record.
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
if (WalRcvInProgress())
|
||||
{
|
||||
/*
|
||||
* While walreceiver is active, wait for new WAL to
|
||||
* arrive from primary.
|
||||
* While walreceiver is active, wait for new WAL to arrive
|
||||
* from primary.
|
||||
*/
|
||||
receivedUpto = GetWalRcvWriteRecPtr();
|
||||
if (XLByteLT(*RecPtr, receivedUpto))
|
||||
@@ -8798,10 +8805,10 @@ XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt,
|
||||
|
||||
/*
|
||||
* If we succeeded restoring some segments from archive
|
||||
* since the last connection attempt (or we haven't
|
||||
* tried streaming yet, retry immediately. But if we
|
||||
* haven't, assume the problem is persistent, so be
|
||||
* less aggressive.
|
||||
* since the last connection attempt (or we haven't tried
|
||||
* streaming yet, retry immediately. But if we haven't,
|
||||
* assume the problem is persistent, so be less
|
||||
* aggressive.
|
||||
*/
|
||||
if (last_restore_failed)
|
||||
{
|
||||
@@ -8813,7 +8820,7 @@ XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt,
|
||||
*/
|
||||
if (CheckForStandbyTrigger())
|
||||
goto next_record_is_invalid;
|
||||
pg_usleep(5000000L); /* 5 seconds */
|
||||
pg_usleep(5000000L); /* 5 seconds */
|
||||
}
|
||||
last_restore_failed = true;
|
||||
|
||||
@@ -8832,8 +8839,8 @@ XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt,
|
||||
}
|
||||
|
||||
/*
|
||||
* This possibly-long loop needs to handle interrupts of startup
|
||||
* process.
|
||||
* This possibly-long loop needs to handle interrupts of
|
||||
* startup process.
|
||||
*/
|
||||
HandleStartupProcInterrupts();
|
||||
}
|
||||
@@ -8857,16 +8864,16 @@ XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt,
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, we have the right segment open and we know the
|
||||
* requested record is in it.
|
||||
* At this point, we have the right segment open and we know the requested
|
||||
* record is in it.
|
||||
*/
|
||||
Assert(readFile != -1);
|
||||
|
||||
/*
|
||||
* If the current segment is being streamed from master, calculate
|
||||
* how much of the current page we have received already. We know the
|
||||
* requested record has been received, but this is for the benefit
|
||||
* of future calls, to allow quick exit at the top of this function.
|
||||
* If the current segment is being streamed from master, calculate how
|
||||
* much of the current page we have received already. We know the
|
||||
* requested record has been received, but this is for the benefit of
|
||||
* future calls, to allow quick exit at the top of this function.
|
||||
*/
|
||||
if (readStreamed)
|
||||
{
|
||||
@@ -8909,16 +8916,16 @@ XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt,
|
||||
{
|
||||
ereport(emode,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not seek in log file %u, segment %u to offset %u: %m",
|
||||
readId, readSeg, readOff)));
|
||||
errmsg("could not seek in log file %u, segment %u to offset %u: %m",
|
||||
readId, readSeg, readOff)));
|
||||
goto next_record_is_invalid;
|
||||
}
|
||||
if (read(readFile, readBuf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
|
||||
{
|
||||
ereport(emode,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not read from log file %u, segment %u, offset %u: %m",
|
||||
readId, readSeg, readOff)));
|
||||
errmsg("could not read from log file %u, segment %u, offset %u: %m",
|
||||
readId, readSeg, readOff)));
|
||||
goto next_record_is_invalid;
|
||||
}
|
||||
if (!ValidXLOGHeader((XLogPageHeader) readBuf, emode))
|
||||
|
||||
Reference in New Issue
Block a user