提交 0a202070 编写于 作者: T Tom Lane

Arrange to emit a description of the current XLOG record as error context

when an error occurs during xlog replay.  Also, replace the former risky
'write into a fixed-size buffer with no overflow detection' API for XLOG
record description routines; use an expansible StringInfo instead.  (The
latter accounts for most of the patch bulk.)

Qingqing Zhou
上级 4fb92718
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/gist/gistxlog.c,v 1.10 2006/03/05 15:58:20 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/gist/gistxlog.c,v 1.11 2006/03/24 04:32:12 tgl Exp $
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h" #include "postgres.h"
...@@ -442,67 +442,67 @@ gist_redo(XLogRecPtr lsn, XLogRecord *record) ...@@ -442,67 +442,67 @@ gist_redo(XLogRecPtr lsn, XLogRecord *record)
} }
static void static void
out_target(char *buf, RelFileNode node, ItemPointerData key) out_target(StringInfo buf, RelFileNode node, ItemPointerData key)
{ {
sprintf(buf + strlen(buf), "rel %u/%u/%u; tid %u/%u", appendStringInfo(buf, "rel %u/%u/%u; tid %u/%u",
node.spcNode, node.dbNode, node.relNode, node.spcNode, node.dbNode, node.relNode,
ItemPointerGetBlockNumber(&key), ItemPointerGetBlockNumber(&key),
ItemPointerGetOffsetNumber(&key)); ItemPointerGetOffsetNumber(&key));
} }
static void static void
out_gistxlogEntryUpdate(char *buf, gistxlogEntryUpdate *xlrec) out_gistxlogEntryUpdate(StringInfo buf, gistxlogEntryUpdate *xlrec)
{ {
out_target(buf, xlrec->node, xlrec->key); out_target(buf, xlrec->node, xlrec->key);
sprintf(buf + strlen(buf), "; block number %u", appendStringInfo(buf, "; block number %u", xlrec->blkno);
xlrec->blkno);
} }
static void static void
out_gistxlogPageSplit(char *buf, gistxlogPageSplit *xlrec) out_gistxlogPageSplit(StringInfo buf, gistxlogPageSplit *xlrec)
{ {
strcat(buf, "page_split: "); appendStringInfo(buf, "page_split: ");
out_target(buf, xlrec->node, xlrec->key); out_target(buf, xlrec->node, xlrec->key);
sprintf(buf + strlen(buf), "; block number %u splits to %d pages", appendStringInfo(buf, "; block number %u splits to %d pages",
xlrec->origblkno, xlrec->npage); xlrec->origblkno, xlrec->npage);
} }
void void
gist_desc(char *buf, uint8 xl_info, char *rec) gist_desc(StringInfo buf, uint8 xl_info, char *rec)
{ {
uint8 info = xl_info & ~XLR_INFO_MASK; uint8 info = xl_info & ~XLR_INFO_MASK;
switch (info) switch (info)
{ {
case XLOG_GIST_ENTRY_UPDATE: case XLOG_GIST_ENTRY_UPDATE:
strcat(buf, "entry_update: "); appendStringInfo(buf, "entry_update: ");
out_gistxlogEntryUpdate(buf, (gistxlogEntryUpdate *) rec); out_gistxlogEntryUpdate(buf, (gistxlogEntryUpdate *) rec);
break; break;
case XLOG_GIST_ENTRY_DELETE: case XLOG_GIST_ENTRY_DELETE:
strcat(buf, "entry_delete: "); appendStringInfo(buf, "entry_delete: ");
out_gistxlogEntryUpdate(buf, (gistxlogEntryUpdate *) rec); out_gistxlogEntryUpdate(buf, (gistxlogEntryUpdate *) rec);
break; break;
case XLOG_GIST_NEW_ROOT: case XLOG_GIST_NEW_ROOT:
strcat(buf, "new_root: "); appendStringInfo(buf, "new_root: ");
out_target(buf, ((gistxlogEntryUpdate *) rec)->node, ((gistxlogEntryUpdate *) rec)->key); out_target(buf, ((gistxlogEntryUpdate *) rec)->node, ((gistxlogEntryUpdate *) rec)->key);
break; break;
case XLOG_GIST_PAGE_SPLIT: case XLOG_GIST_PAGE_SPLIT:
out_gistxlogPageSplit(buf, (gistxlogPageSplit *) rec); out_gistxlogPageSplit(buf, (gistxlogPageSplit *) rec);
break; break;
case XLOG_GIST_CREATE_INDEX: case XLOG_GIST_CREATE_INDEX:
sprintf(buf + strlen(buf), "create_index: rel %u/%u/%u", appendStringInfo(buf, "create_index: rel %u/%u/%u",
((RelFileNode *) rec)->spcNode, ((RelFileNode *) rec)->spcNode,
((RelFileNode *) rec)->dbNode, ((RelFileNode *) rec)->dbNode,
((RelFileNode *) rec)->relNode); ((RelFileNode *) rec)->relNode);
break; break;
case XLOG_GIST_INSERT_COMPLETE: case XLOG_GIST_INSERT_COMPLETE:
sprintf(buf + strlen(buf), "complete_insert: rel %u/%u/%u", appendStringInfo(buf, "complete_insert: rel %u/%u/%u",
((gistxlogInsertComplete *) rec)->node.spcNode, ((gistxlogInsertComplete *) rec)->node.spcNode,
((gistxlogInsertComplete *) rec)->node.dbNode, ((gistxlogInsertComplete *) rec)->node.dbNode,
((gistxlogInsertComplete *) rec)->node.relNode); ((gistxlogInsertComplete *) rec)->node.relNode);
break; break;
default: default:
elog(PANIC, "gist_desc: unknown op code %u", info); appendStringInfo(buf, "unknown gist op code %u", info);
break;
} }
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.87 2006/03/05 15:58:20 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.88 2006/03/24 04:32:12 tgl Exp $
* *
* NOTES * NOTES
* This file contains only the public interface routines. * This file contains only the public interface routines.
...@@ -675,6 +675,6 @@ hash_redo(XLogRecPtr lsn, XLogRecord *record) ...@@ -675,6 +675,6 @@ hash_redo(XLogRecPtr lsn, XLogRecord *record)
} }
void void
hash_desc(char *buf, uint8 xl_info, char *rec) hash_desc(StringInfo buf, uint8 xl_info, char *rec)
{ {
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.208 2006/03/05 15:58:21 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.209 2006/03/24 04:32:12 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -3363,16 +3363,16 @@ heap_redo(XLogRecPtr lsn, XLogRecord *record) ...@@ -3363,16 +3363,16 @@ heap_redo(XLogRecPtr lsn, XLogRecord *record)
} }
static void static void
out_target(char *buf, xl_heaptid *target) out_target(StringInfo buf, xl_heaptid *target)
{ {
sprintf(buf + strlen(buf), "rel %u/%u/%u; tid %u/%u", appendStringInfo(buf, "rel %u/%u/%u; tid %u/%u",
target->node.spcNode, target->node.dbNode, target->node.relNode, target->node.spcNode, target->node.dbNode, target->node.relNode,
ItemPointerGetBlockNumber(&(target->tid)), ItemPointerGetBlockNumber(&(target->tid)),
ItemPointerGetOffsetNumber(&(target->tid))); ItemPointerGetOffsetNumber(&(target->tid)));
} }
void void
heap_desc(char *buf, uint8 xl_info, char *rec) heap_desc(StringInfo buf, uint8 xl_info, char *rec)
{ {
uint8 info = xl_info & ~XLR_INFO_MASK; uint8 info = xl_info & ~XLR_INFO_MASK;
...@@ -3381,14 +3381,14 @@ heap_desc(char *buf, uint8 xl_info, char *rec) ...@@ -3381,14 +3381,14 @@ heap_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_heap_insert *xlrec = (xl_heap_insert *) rec; xl_heap_insert *xlrec = (xl_heap_insert *) rec;
strcat(buf, "insert: "); appendStringInfo(buf, "insert: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
} }
else if (info == XLOG_HEAP_DELETE) else if (info == XLOG_HEAP_DELETE)
{ {
xl_heap_delete *xlrec = (xl_heap_delete *) rec; xl_heap_delete *xlrec = (xl_heap_delete *) rec;
strcat(buf, "delete: "); appendStringInfo(buf, "delete: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
} }
else if (info == XLOG_HEAP_UPDATE || info == XLOG_HEAP_MOVE) else if (info == XLOG_HEAP_UPDATE || info == XLOG_HEAP_MOVE)
...@@ -3396,11 +3396,11 @@ heap_desc(char *buf, uint8 xl_info, char *rec) ...@@ -3396,11 +3396,11 @@ heap_desc(char *buf, uint8 xl_info, char *rec)
xl_heap_update *xlrec = (xl_heap_update *) rec; xl_heap_update *xlrec = (xl_heap_update *) rec;
if (info == XLOG_HEAP_UPDATE) if (info == XLOG_HEAP_UPDATE)
strcat(buf, "update: "); appendStringInfo(buf, "update: ");
else else
strcat(buf, "move: "); appendStringInfo(buf, "move: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
sprintf(buf + strlen(buf), "; new %u/%u", appendStringInfo(buf, "; new %u/%u",
ItemPointerGetBlockNumber(&(xlrec->newtid)), ItemPointerGetBlockNumber(&(xlrec->newtid)),
ItemPointerGetOffsetNumber(&(xlrec->newtid))); ItemPointerGetOffsetNumber(&(xlrec->newtid)));
} }
...@@ -3408,7 +3408,7 @@ heap_desc(char *buf, uint8 xl_info, char *rec) ...@@ -3408,7 +3408,7 @@ heap_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_heap_clean *xlrec = (xl_heap_clean *) rec; xl_heap_clean *xlrec = (xl_heap_clean *) rec;
sprintf(buf + strlen(buf), "clean: rel %u/%u/%u; blk %u", appendStringInfo(buf, "clean: rel %u/%u/%u; blk %u",
xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.spcNode, xlrec->node.dbNode,
xlrec->node.relNode, xlrec->block); xlrec->node.relNode, xlrec->block);
} }
...@@ -3416,7 +3416,7 @@ heap_desc(char *buf, uint8 xl_info, char *rec) ...@@ -3416,7 +3416,7 @@ heap_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_heap_newpage *xlrec = (xl_heap_newpage *) rec; xl_heap_newpage *xlrec = (xl_heap_newpage *) rec;
sprintf(buf + strlen(buf), "newpage: rel %u/%u/%u; blk %u", appendStringInfo(buf, "newpage: rel %u/%u/%u; blk %u",
xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.spcNode, xlrec->node.dbNode,
xlrec->node.relNode, xlrec->blkno); xlrec->node.relNode, xlrec->blkno);
} }
...@@ -3425,16 +3425,16 @@ heap_desc(char *buf, uint8 xl_info, char *rec) ...@@ -3425,16 +3425,16 @@ heap_desc(char *buf, uint8 xl_info, char *rec)
xl_heap_lock *xlrec = (xl_heap_lock *) rec; xl_heap_lock *xlrec = (xl_heap_lock *) rec;
if (xlrec->shared_lock) if (xlrec->shared_lock)
strcat(buf, "shared_lock: "); appendStringInfo(buf, "shared_lock: ");
else else
strcat(buf, "exclusive_lock: "); appendStringInfo(buf, "exclusive_lock: ");
if (xlrec->xid_is_mxact) if (xlrec->xid_is_mxact)
strcat(buf, "mxid "); appendStringInfo(buf, "mxid ");
else else
strcat(buf, "xid "); appendStringInfo(buf, "xid ");
sprintf(buf + strlen(buf), "%u ", xlrec->locking_xid); appendStringInfo(buf, "%u ", xlrec->locking_xid);
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
} }
else else
strcat(buf, "UNKNOWN"); appendStringInfo(buf, "UNKNOWN");
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.26 2006/03/05 15:58:21 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.27 2006/03/24 04:32:12 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -650,16 +650,16 @@ btree_redo(XLogRecPtr lsn, XLogRecord *record) ...@@ -650,16 +650,16 @@ btree_redo(XLogRecPtr lsn, XLogRecord *record)
} }
static void static void
out_target(char *buf, xl_btreetid *target) out_target(StringInfo buf, xl_btreetid *target)
{ {
sprintf(buf + strlen(buf), "rel %u/%u/%u; tid %u/%u", appendStringInfo(buf, "rel %u/%u/%u; tid %u/%u",
target->node.spcNode, target->node.dbNode, target->node.relNode, target->node.spcNode, target->node.dbNode, target->node.relNode,
ItemPointerGetBlockNumber(&(target->tid)), ItemPointerGetBlockNumber(&(target->tid)),
ItemPointerGetOffsetNumber(&(target->tid))); ItemPointerGetOffsetNumber(&(target->tid)));
} }
void void
btree_desc(char *buf, uint8 xl_info, char *rec) btree_desc(StringInfo buf, uint8 xl_info, char *rec)
{ {
uint8 info = xl_info & ~XLR_INFO_MASK; uint8 info = xl_info & ~XLR_INFO_MASK;
...@@ -669,7 +669,7 @@ btree_desc(char *buf, uint8 xl_info, char *rec) ...@@ -669,7 +669,7 @@ btree_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_btree_insert *xlrec = (xl_btree_insert *) rec; xl_btree_insert *xlrec = (xl_btree_insert *) rec;
strcat(buf, "insert: "); appendStringInfo(buf, "insert: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
break; break;
} }
...@@ -677,7 +677,7 @@ btree_desc(char *buf, uint8 xl_info, char *rec) ...@@ -677,7 +677,7 @@ btree_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_btree_insert *xlrec = (xl_btree_insert *) rec; xl_btree_insert *xlrec = (xl_btree_insert *) rec;
strcat(buf, "insert_upper: "); appendStringInfo(buf, "insert_upper: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
break; break;
} }
...@@ -685,7 +685,7 @@ btree_desc(char *buf, uint8 xl_info, char *rec) ...@@ -685,7 +685,7 @@ btree_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_btree_insert *xlrec = (xl_btree_insert *) rec; xl_btree_insert *xlrec = (xl_btree_insert *) rec;
strcat(buf, "insert_meta: "); appendStringInfo(buf, "insert_meta: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
break; break;
} }
...@@ -693,9 +693,9 @@ btree_desc(char *buf, uint8 xl_info, char *rec) ...@@ -693,9 +693,9 @@ btree_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_btree_split *xlrec = (xl_btree_split *) rec; xl_btree_split *xlrec = (xl_btree_split *) rec;
strcat(buf, "split_l: "); appendStringInfo(buf, "split_l: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
sprintf(buf + strlen(buf), "; oth %u; rgh %u", appendStringInfo(buf, "; oth %u; rgh %u",
xlrec->otherblk, xlrec->rightblk); xlrec->otherblk, xlrec->rightblk);
break; break;
} }
...@@ -703,9 +703,9 @@ btree_desc(char *buf, uint8 xl_info, char *rec) ...@@ -703,9 +703,9 @@ btree_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_btree_split *xlrec = (xl_btree_split *) rec; xl_btree_split *xlrec = (xl_btree_split *) rec;
strcat(buf, "split_r: "); appendStringInfo(buf, "split_r: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
sprintf(buf + strlen(buf), "; oth %u; rgh %u", appendStringInfo(buf, "; oth %u; rgh %u",
xlrec->otherblk, xlrec->rightblk); xlrec->otherblk, xlrec->rightblk);
break; break;
} }
...@@ -713,9 +713,9 @@ btree_desc(char *buf, uint8 xl_info, char *rec) ...@@ -713,9 +713,9 @@ btree_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_btree_split *xlrec = (xl_btree_split *) rec; xl_btree_split *xlrec = (xl_btree_split *) rec;
strcat(buf, "split_l_root: "); appendStringInfo(buf, "split_l_root: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
sprintf(buf + strlen(buf), "; oth %u; rgh %u", appendStringInfo(buf, "; oth %u; rgh %u",
xlrec->otherblk, xlrec->rightblk); xlrec->otherblk, xlrec->rightblk);
break; break;
} }
...@@ -723,9 +723,9 @@ btree_desc(char *buf, uint8 xl_info, char *rec) ...@@ -723,9 +723,9 @@ btree_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_btree_split *xlrec = (xl_btree_split *) rec; xl_btree_split *xlrec = (xl_btree_split *) rec;
strcat(buf, "split_r_root: "); appendStringInfo(buf, "split_r_root: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
sprintf(buf + strlen(buf), "; oth %u; rgh %u", appendStringInfo(buf, "; oth %u; rgh %u",
xlrec->otherblk, xlrec->rightblk); xlrec->otherblk, xlrec->rightblk);
break; break;
} }
...@@ -733,7 +733,7 @@ btree_desc(char *buf, uint8 xl_info, char *rec) ...@@ -733,7 +733,7 @@ btree_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_btree_delete *xlrec = (xl_btree_delete *) rec; xl_btree_delete *xlrec = (xl_btree_delete *) rec;
sprintf(buf + strlen(buf), "delete: rel %u/%u/%u; blk %u", appendStringInfo(buf, "delete: rel %u/%u/%u; blk %u",
xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.spcNode, xlrec->node.dbNode,
xlrec->node.relNode, xlrec->block); xlrec->node.relNode, xlrec->block);
break; break;
...@@ -743,9 +743,9 @@ btree_desc(char *buf, uint8 xl_info, char *rec) ...@@ -743,9 +743,9 @@ btree_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_btree_delete_page *xlrec = (xl_btree_delete_page *) rec; xl_btree_delete_page *xlrec = (xl_btree_delete_page *) rec;
strcat(buf, "delete_page: "); appendStringInfo(buf, "delete_page: ");
out_target(buf, &(xlrec->target)); out_target(buf, &(xlrec->target));
sprintf(buf + strlen(buf), "; dead %u; left %u; right %u", appendStringInfo(buf, "; dead %u; left %u; right %u",
xlrec->deadblk, xlrec->leftblk, xlrec->rightblk); xlrec->deadblk, xlrec->leftblk, xlrec->rightblk);
break; break;
} }
...@@ -753,7 +753,7 @@ btree_desc(char *buf, uint8 xl_info, char *rec) ...@@ -753,7 +753,7 @@ btree_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_btree_newroot *xlrec = (xl_btree_newroot *) rec; xl_btree_newroot *xlrec = (xl_btree_newroot *) rec;
sprintf(buf + strlen(buf), "newroot: rel %u/%u/%u; root %u lev %u", appendStringInfo(buf, "newroot: rel %u/%u/%u; root %u lev %u",
xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.spcNode, xlrec->node.dbNode,
xlrec->node.relNode, xlrec->node.relNode,
xlrec->rootblk, xlrec->level); xlrec->rootblk, xlrec->level);
...@@ -763,7 +763,7 @@ btree_desc(char *buf, uint8 xl_info, char *rec) ...@@ -763,7 +763,7 @@ btree_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_btree_newmeta *xlrec = (xl_btree_newmeta *) rec; xl_btree_newmeta *xlrec = (xl_btree_newmeta *) rec;
sprintf(buf + strlen(buf), "newmeta: rel %u/%u/%u; root %u lev %u fast %u lev %u", appendStringInfo(buf, "newmeta: rel %u/%u/%u; root %u lev %u fast %u lev %u",
xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.spcNode, xlrec->node.dbNode,
xlrec->node.relNode, xlrec->node.relNode,
xlrec->meta.root, xlrec->meta.level, xlrec->meta.root, xlrec->meta.level,
...@@ -771,7 +771,7 @@ btree_desc(char *buf, uint8 xl_info, char *rec) ...@@ -771,7 +771,7 @@ btree_desc(char *buf, uint8 xl_info, char *rec)
break; break;
} }
default: default:
strcat(buf, "UNKNOWN"); appendStringInfo(buf, "UNKNOWN");
break; break;
} }
} }
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/access/transam/clog.c,v 1.37 2006/03/05 15:58:21 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/clog.c,v 1.38 2006/03/24 04:32:12 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -412,17 +412,17 @@ clog_redo(XLogRecPtr lsn, XLogRecord *record) ...@@ -412,17 +412,17 @@ clog_redo(XLogRecPtr lsn, XLogRecord *record)
} }
void void
clog_desc(char *buf, uint8 xl_info, char *rec) clog_desc(StringInfo buf, uint8 xl_info, char *rec)
{ {
uint8 info = xl_info & ~XLR_INFO_MASK; uint8 info = xl_info & ~XLR_INFO_MASK;
if (info == CLOG_ZEROPAGE) if (info == CLOG_ZEROPAGE)
{ {
int pageno; int pageno;
memcpy(&pageno, rec, sizeof(int)); memcpy(&pageno, rec, sizeof(int));
sprintf(buf + strlen(buf), "zeropage: %d", pageno); appendStringInfo(buf, "zeropage: %d", pageno);
} }
else else
strcat(buf, "UNKNOWN"); appendStringInfo(buf, "UNKNOWN");
} }
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/access/transam/multixact.c,v 1.16 2006/03/05 15:58:21 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/multixact.c,v 1.17 2006/03/24 04:32:12 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1887,7 +1887,7 @@ multixact_redo(XLogRecPtr lsn, XLogRecord *record) ...@@ -1887,7 +1887,7 @@ multixact_redo(XLogRecPtr lsn, XLogRecord *record)
} }
void void
multixact_desc(char *buf, uint8 xl_info, char *rec) multixact_desc(StringInfo buf, uint8 xl_info, char *rec)
{ {
uint8 info = xl_info & ~XLR_INFO_MASK; uint8 info = xl_info & ~XLR_INFO_MASK;
...@@ -1896,25 +1896,25 @@ multixact_desc(char *buf, uint8 xl_info, char *rec) ...@@ -1896,25 +1896,25 @@ multixact_desc(char *buf, uint8 xl_info, char *rec)
int pageno; int pageno;
memcpy(&pageno, rec, sizeof(int)); memcpy(&pageno, rec, sizeof(int));
sprintf(buf + strlen(buf), "zero offsets page: %d", pageno); appendStringInfo(buf, "zero offsets page: %d", pageno);
} }
else if (info == XLOG_MULTIXACT_ZERO_MEM_PAGE) else if (info == XLOG_MULTIXACT_ZERO_MEM_PAGE)
{ {
int pageno; int pageno;
memcpy(&pageno, rec, sizeof(int)); memcpy(&pageno, rec, sizeof(int));
sprintf(buf + strlen(buf), "zero members page: %d", pageno); appendStringInfo(buf, "zero members page: %d", pageno);
} }
else if (info == XLOG_MULTIXACT_CREATE_ID) else if (info == XLOG_MULTIXACT_CREATE_ID)
{ {
xl_multixact_create *xlrec = (xl_multixact_create *) rec; xl_multixact_create *xlrec = (xl_multixact_create *) rec;
int i; int i;
sprintf(buf + strlen(buf), "create multixact %u offset %u:", appendStringInfo(buf, "create multixact %u offset %u:",
xlrec->mid, xlrec->moff); xlrec->mid, xlrec->moff);
for (i = 0; i < xlrec->nxids; i++) for (i = 0; i < xlrec->nxids; i++)
sprintf(buf + strlen(buf), " %u", xlrec->xids[i]); appendStringInfo(buf, " %u", xlrec->xids[i]);
} }
else else
strcat(buf, "UNKNOWN"); appendStringInfo(buf, "UNKNOWN");
} }
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.217 2006/03/05 15:58:22 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.218 2006/03/24 04:32:12 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -4179,22 +4179,22 @@ xact_redo(XLogRecPtr lsn, XLogRecord *record) ...@@ -4179,22 +4179,22 @@ xact_redo(XLogRecPtr lsn, XLogRecord *record)
} }
static void static void
xact_desc_commit(char *buf, xl_xact_commit *xlrec) xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
{ {
struct tm *tm = localtime(&xlrec->xtime); struct tm *tm = localtime(&xlrec->xtime);
int i; int i;
sprintf(buf + strlen(buf), "%04u-%02u-%02u %02u:%02u:%02u", appendStringInfo(buf, "%04u-%02u-%02u %02u:%02u:%02u",
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec); tm->tm_hour, tm->tm_min, tm->tm_sec);
if (xlrec->nrels > 0) if (xlrec->nrels > 0)
{ {
sprintf(buf + strlen(buf), "; rels:"); appendStringInfo(buf, "; rels:");
for (i = 0; i < xlrec->nrels; i++) for (i = 0; i < xlrec->nrels; i++)
{ {
RelFileNode rnode = xlrec->xnodes[i]; RelFileNode rnode = xlrec->xnodes[i];
sprintf(buf + strlen(buf), " %u/%u/%u", appendStringInfo(buf, " %u/%u/%u",
rnode.spcNode, rnode.dbNode, rnode.relNode); rnode.spcNode, rnode.dbNode, rnode.relNode);
} }
} }
...@@ -4203,29 +4203,29 @@ xact_desc_commit(char *buf, xl_xact_commit *xlrec) ...@@ -4203,29 +4203,29 @@ xact_desc_commit(char *buf, xl_xact_commit *xlrec)
TransactionId *xacts = (TransactionId *) TransactionId *xacts = (TransactionId *)
&xlrec->xnodes[xlrec->nrels]; &xlrec->xnodes[xlrec->nrels];
sprintf(buf + strlen(buf), "; subxacts:"); appendStringInfo(buf, "; subxacts:");
for (i = 0; i < xlrec->nsubxacts; i++) for (i = 0; i < xlrec->nsubxacts; i++)
sprintf(buf + strlen(buf), " %u", xacts[i]); appendStringInfo(buf, " %u", xacts[i]);
} }
} }
static void static void
xact_desc_abort(char *buf, xl_xact_abort *xlrec) xact_desc_abort(StringInfo buf, xl_xact_abort *xlrec)
{ {
struct tm *tm = localtime(&xlrec->xtime); struct tm *tm = localtime(&xlrec->xtime);
int i; int i;
sprintf(buf + strlen(buf), "%04u-%02u-%02u %02u:%02u:%02u", appendStringInfo(buf, "%04u-%02u-%02u %02u:%02u:%02u",
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec); tm->tm_hour, tm->tm_min, tm->tm_sec);
if (xlrec->nrels > 0) if (xlrec->nrels > 0)
{ {
sprintf(buf + strlen(buf), "; rels:"); appendStringInfo(buf, "; rels:");
for (i = 0; i < xlrec->nrels; i++) for (i = 0; i < xlrec->nrels; i++)
{ {
RelFileNode rnode = xlrec->xnodes[i]; RelFileNode rnode = xlrec->xnodes[i];
sprintf(buf + strlen(buf), " %u/%u/%u", appendStringInfo(buf, " %u/%u/%u",
rnode.spcNode, rnode.dbNode, rnode.relNode); rnode.spcNode, rnode.dbNode, rnode.relNode);
} }
} }
...@@ -4234,49 +4234,49 @@ xact_desc_abort(char *buf, xl_xact_abort *xlrec) ...@@ -4234,49 +4234,49 @@ xact_desc_abort(char *buf, xl_xact_abort *xlrec)
TransactionId *xacts = (TransactionId *) TransactionId *xacts = (TransactionId *)
&xlrec->xnodes[xlrec->nrels]; &xlrec->xnodes[xlrec->nrels];
sprintf(buf + strlen(buf), "; subxacts:"); appendStringInfo(buf, "; subxacts:");
for (i = 0; i < xlrec->nsubxacts; i++) for (i = 0; i < xlrec->nsubxacts; i++)
sprintf(buf + strlen(buf), " %u", xacts[i]); appendStringInfo(buf, " %u", xacts[i]);
} }
} }
void void
xact_desc(char *buf, uint8 xl_info, char *rec) xact_desc(StringInfo buf, uint8 xl_info, char *rec)
{ {
uint8 info = xl_info & ~XLR_INFO_MASK; uint8 info = xl_info & ~XLR_INFO_MASK;
if (info == XLOG_XACT_COMMIT) if (info == XLOG_XACT_COMMIT)
{ {
xl_xact_commit *xlrec = (xl_xact_commit *) rec; xl_xact_commit *xlrec = (xl_xact_commit *) rec;
strcat(buf, "commit: "); appendStringInfo(buf, "commit: ");
xact_desc_commit(buf, xlrec); xact_desc_commit(buf, xlrec);
} }
else if (info == XLOG_XACT_ABORT) else if (info == XLOG_XACT_ABORT)
{ {
xl_xact_abort *xlrec = (xl_xact_abort *) rec; xl_xact_abort *xlrec = (xl_xact_abort *) rec;
strcat(buf, "abort: "); appendStringInfo(buf, "abort: ");
xact_desc_abort(buf, xlrec); xact_desc_abort(buf, xlrec);
} }
else if (info == XLOG_XACT_PREPARE) else if (info == XLOG_XACT_PREPARE)
{ {
strcat(buf, "prepare"); appendStringInfo(buf, "prepare");
} }
else if (info == XLOG_XACT_COMMIT_PREPARED) else if (info == XLOG_XACT_COMMIT_PREPARED)
{ {
xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) rec; xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) rec;
sprintf(buf + strlen(buf), "commit %u: ", xlrec->xid); appendStringInfo(buf, "commit %u: ", xlrec->xid);
xact_desc_commit(buf, &xlrec->crec); xact_desc_commit(buf, &xlrec->crec);
} }
else if (info == XLOG_XACT_ABORT_PREPARED) else if (info == XLOG_XACT_ABORT_PREPARED)
{ {
xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) rec; xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) rec;
sprintf(buf + strlen(buf), "abort %u: ", xlrec->xid); appendStringInfo(buf, "abort %u: ", xlrec->xid);
xact_desc_abort(buf, &xlrec->arec); xact_desc_abort(buf, &xlrec->arec);
} }
else else
strcat(buf, "UNKNOWN"); appendStringInfo(buf, "UNKNOWN");
} }
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.227 2006/03/05 15:58:22 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.228 2006/03/24 04:32:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -498,10 +498,11 @@ static char *str_time(time_t tnow); ...@@ -498,10 +498,11 @@ static char *str_time(time_t tnow);
static void issue_xlog_fsync(void); static void issue_xlog_fsync(void);
#ifdef WAL_DEBUG #ifdef WAL_DEBUG
static void xlog_outrec(char *buf, XLogRecord *record); static void xlog_outrec(StringInfo buf, XLogRecord *record);
#endif #endif
static bool read_backup_label(XLogRecPtr *checkPointLoc); static bool read_backup_label(XLogRecPtr *checkPointLoc);
static void remove_backup_label(void); static void remove_backup_label(void);
static void rm_redo_error_callback(void *arg);
/* /*
...@@ -852,16 +853,19 @@ begin:; ...@@ -852,16 +853,19 @@ begin:;
#ifdef WAL_DEBUG #ifdef WAL_DEBUG
if (XLOG_DEBUG) if (XLOG_DEBUG)
{ {
char buf[8192]; StringInfoData buf;
sprintf(buf, "INSERT @ %X/%X: ", RecPtr.xlogid, RecPtr.xrecoff); initStringInfo(&buf);
xlog_outrec(buf, record); appendStringInfo(&buf, "INSERT @ %X/%X: ",
RecPtr.xlogid, RecPtr.xrecoff);
xlog_outrec(&buf, record);
if (rdata->data != NULL) if (rdata->data != NULL)
{ {
strcat(buf, " - "); appendStringInfo(&buf, " - ");
RmgrTable[record->xl_rmid].rm_desc(buf, record->xl_info, rdata->data); RmgrTable[record->xl_rmid].rm_desc(&buf, record->xl_info, rdata->data);
} }
elog(LOG, "%s", buf); elog(LOG, "%s", buf.data);
pfree(buf.data);
} }
#endif #endif
...@@ -4562,6 +4566,7 @@ StartupXLOG(void) ...@@ -4562,6 +4566,7 @@ StartupXLOG(void)
{ {
bool recoveryContinue = true; bool recoveryContinue = true;
bool recoveryApply = true; bool recoveryApply = true;
ErrorContextCallback errcontext;
InRedo = true; InRedo = true;
ereport(LOG, ereport(LOG,
...@@ -4576,16 +4581,19 @@ StartupXLOG(void) ...@@ -4576,16 +4581,19 @@ StartupXLOG(void)
#ifdef WAL_DEBUG #ifdef WAL_DEBUG
if (XLOG_DEBUG) if (XLOG_DEBUG)
{ {
char buf[8192]; StringInfoData buf;
sprintf(buf, "REDO @ %X/%X; LSN %X/%X: ", initStringInfo(&buf);
appendStringInfo(&buf, "REDO @ %X/%X; LSN %X/%X: ",
ReadRecPtr.xlogid, ReadRecPtr.xrecoff, ReadRecPtr.xlogid, ReadRecPtr.xrecoff,
EndRecPtr.xlogid, EndRecPtr.xrecoff); EndRecPtr.xlogid, EndRecPtr.xrecoff);
xlog_outrec(buf, record); xlog_outrec(&buf, record);
strcat(buf, " - "); appendStringInfo(&buf, " - ");
RmgrTable[record->xl_rmid].rm_desc(buf, RmgrTable[record->xl_rmid].rm_desc(&buf,
record->xl_info, XLogRecGetData(record)); record->xl_info,
elog(LOG, "%s", buf); XLogRecGetData(record));
elog(LOG, "%s", buf.data);
pfree(buf.data);
} }
#endif #endif
...@@ -4600,6 +4608,12 @@ StartupXLOG(void) ...@@ -4600,6 +4608,12 @@ StartupXLOG(void)
break; break;
} }
/* Setup error traceback support for ereport() */
errcontext.callback = rm_redo_error_callback;
errcontext.arg = (void *) record;
errcontext.previous = error_context_stack;
error_context_stack = &errcontext;
/* nextXid must be beyond record's xid */ /* nextXid must be beyond record's xid */
if (TransactionIdFollowsOrEquals(record->xl_xid, if (TransactionIdFollowsOrEquals(record->xl_xid,
ShmemVariableCache->nextXid)) ShmemVariableCache->nextXid))
...@@ -4613,6 +4627,9 @@ StartupXLOG(void) ...@@ -4613,6 +4627,9 @@ StartupXLOG(void)
RmgrTable[record->xl_rmid].rm_redo(EndRecPtr, record); RmgrTable[record->xl_rmid].rm_redo(EndRecPtr, record);
/* Pop the error context stack */
error_context_stack = errcontext.previous;
LastRec = ReadRecPtr; LastRec = ReadRecPtr;
record = ReadRecord(NULL, LOG); record = ReadRecord(NULL, LOG);
...@@ -5400,16 +5417,16 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record) ...@@ -5400,16 +5417,16 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
} }
void void
xlog_desc(char *buf, uint8 xl_info, char *rec) xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
{ {
uint8 info = xl_info & ~XLR_INFO_MASK; uint8 info = xl_info & ~XLR_INFO_MASK;
if (info == XLOG_CHECKPOINT_SHUTDOWN || if (info == XLOG_CHECKPOINT_SHUTDOWN ||
info == XLOG_CHECKPOINT_ONLINE) info == XLOG_CHECKPOINT_ONLINE)
{ {
CheckPoint *checkpoint = (CheckPoint *) rec; CheckPoint *checkpoint = (CheckPoint *) rec;
sprintf(buf + strlen(buf), "checkpoint: redo %X/%X; undo %X/%X; " appendStringInfo(buf, "checkpoint: redo %X/%X; undo %X/%X; "
"tli %u; xid %u; oid %u; multi %u; offset %u; %s", "tli %u; xid %u; oid %u; multi %u; offset %u; %s",
checkpoint->redo.xlogid, checkpoint->redo.xrecoff, checkpoint->redo.xlogid, checkpoint->redo.xrecoff,
checkpoint->undo.xlogid, checkpoint->undo.xrecoff, checkpoint->undo.xlogid, checkpoint->undo.xrecoff,
...@@ -5424,21 +5441,21 @@ xlog_desc(char *buf, uint8 xl_info, char *rec) ...@@ -5424,21 +5441,21 @@ xlog_desc(char *buf, uint8 xl_info, char *rec)
Oid nextOid; Oid nextOid;
memcpy(&nextOid, rec, sizeof(Oid)); memcpy(&nextOid, rec, sizeof(Oid));
sprintf(buf + strlen(buf), "nextOid: %u", nextOid); appendStringInfo(buf, "nextOid: %u", nextOid);
} }
else else
strcat(buf, "UNKNOWN"); appendStringInfo(buf, "UNKNOWN");
} }
#ifdef WAL_DEBUG #ifdef WAL_DEBUG
static void static void
xlog_outrec(char *buf, XLogRecord *record) xlog_outrec(StringInfo buf, XLogRecord *record)
{ {
int bkpb; int bkpb;
int i; int i;
sprintf(buf + strlen(buf), "prev %X/%X; xid %u", appendStringInfo(buf, "prev %X/%X; xid %u",
record->xl_prev.xlogid, record->xl_prev.xrecoff, record->xl_prev.xlogid, record->xl_prev.xrecoff,
record->xl_xid); record->xl_xid);
...@@ -5450,9 +5467,9 @@ xlog_outrec(char *buf, XLogRecord *record) ...@@ -5450,9 +5467,9 @@ xlog_outrec(char *buf, XLogRecord *record)
} }
if (bkpb) if (bkpb)
sprintf(buf + strlen(buf), "; bkpb %d", bkpb); appendStringInfo(buf, "; bkpb %d", bkpb);
sprintf(buf + strlen(buf), ": %s", appendStringInfo(buf, ": %s",
RmgrTable[record->xl_rmid].rm_name); RmgrTable[record->xl_rmid].rm_name);
} }
#endif /* WAL_DEBUG */ #endif /* WAL_DEBUG */
...@@ -5976,3 +5993,24 @@ remove_backup_label(void) ...@@ -5976,3 +5993,24 @@ remove_backup_label(void)
errmsg("could not remove file \"%s\": %m", errmsg("could not remove file \"%s\": %m",
BACKUP_LABEL_FILE))); BACKUP_LABEL_FILE)));
} }
/*
* Error context callback for errors occurring during rm_redo().
*/
static void
rm_redo_error_callback(void *arg)
{
XLogRecord *record = (XLogRecord *) arg;
StringInfoData buf;
initStringInfo(&buf);
RmgrTable[record->xl_rmid].rm_desc(&buf,
record->xl_info,
XLogRecGetData(record));
/* don't bother emitting empty description */
if (buf.len > 0)
errcontext("xlog redo %s", buf.data);
pfree(buf.data);
}
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.177 2006/03/05 15:58:24 momjian Exp $ * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.178 2006/03/24 04:32:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1392,7 +1392,7 @@ dbase_redo(XLogRecPtr lsn, XLogRecord *record) ...@@ -1392,7 +1392,7 @@ dbase_redo(XLogRecPtr lsn, XLogRecord *record)
} }
void void
dbase_desc(char *buf, uint8 xl_info, char *rec) dbase_desc(StringInfo buf, uint8 xl_info, char *rec)
{ {
uint8 info = xl_info & ~XLR_INFO_MASK; uint8 info = xl_info & ~XLR_INFO_MASK;
...@@ -1400,7 +1400,7 @@ dbase_desc(char *buf, uint8 xl_info, char *rec) ...@@ -1400,7 +1400,7 @@ dbase_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_dbase_create_rec *xlrec = (xl_dbase_create_rec *) rec; xl_dbase_create_rec *xlrec = (xl_dbase_create_rec *) rec;
sprintf(buf + strlen(buf), "create db: copy dir %u/%u to %u/%u", appendStringInfo(buf, "create db: copy dir %u/%u to %u/%u",
xlrec->src_db_id, xlrec->src_tablespace_id, xlrec->src_db_id, xlrec->src_tablespace_id,
xlrec->db_id, xlrec->tablespace_id); xlrec->db_id, xlrec->tablespace_id);
} }
...@@ -1408,9 +1408,9 @@ dbase_desc(char *buf, uint8 xl_info, char *rec) ...@@ -1408,9 +1408,9 @@ dbase_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_dbase_drop_rec *xlrec = (xl_dbase_drop_rec *) rec; xl_dbase_drop_rec *xlrec = (xl_dbase_drop_rec *) rec;
sprintf(buf + strlen(buf), "drop db: dir %u/%u", appendStringInfo(buf, "drop db: dir %u/%u",
xlrec->db_id, xlrec->tablespace_id); xlrec->db_id, xlrec->tablespace_id);
} }
else else
strcat(buf, "UNKNOWN"); appendStringInfo(buf, "UNKNOWN");
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.129 2006/03/14 22:48:18 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.130 2006/03/24 04:32:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1170,19 +1170,19 @@ seq_redo(XLogRecPtr lsn, XLogRecord *record) ...@@ -1170,19 +1170,19 @@ seq_redo(XLogRecPtr lsn, XLogRecord *record)
} }
void void
seq_desc(char *buf, uint8 xl_info, char *rec) seq_desc(StringInfo buf, uint8 xl_info, char *rec)
{ {
uint8 info = xl_info & ~XLR_INFO_MASK; uint8 info = xl_info & ~XLR_INFO_MASK;
xl_seq_rec *xlrec = (xl_seq_rec *) rec; xl_seq_rec *xlrec = (xl_seq_rec *) rec;
if (info == XLOG_SEQ_LOG) if (info == XLOG_SEQ_LOG)
strcat(buf, "log: "); appendStringInfo(buf, "log: ");
else else
{ {
strcat(buf, "UNKNOWN"); appendStringInfo(buf, "UNKNOWN");
return; return;
} }
sprintf(buf + strlen(buf), "rel %u/%u/%u", appendStringInfo(buf, "rel %u/%u/%u",
xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.relNode); xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.relNode);
} }
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.31 2006/03/05 15:58:25 momjian Exp $ * $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.32 2006/03/24 04:32:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1042,7 +1042,7 @@ tblspc_redo(XLogRecPtr lsn, XLogRecord *record) ...@@ -1042,7 +1042,7 @@ tblspc_redo(XLogRecPtr lsn, XLogRecord *record)
} }
void void
tblspc_desc(char *buf, uint8 xl_info, char *rec) tblspc_desc(StringInfo buf, uint8 xl_info, char *rec)
{ {
uint8 info = xl_info & ~XLR_INFO_MASK; uint8 info = xl_info & ~XLR_INFO_MASK;
...@@ -1050,16 +1050,15 @@ tblspc_desc(char *buf, uint8 xl_info, char *rec) ...@@ -1050,16 +1050,15 @@ tblspc_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_tblspc_create_rec *xlrec = (xl_tblspc_create_rec *) rec; xl_tblspc_create_rec *xlrec = (xl_tblspc_create_rec *) rec;
sprintf(buf + strlen(buf), "create ts: %u \"%s\"", appendStringInfo(buf, "create ts: %u \"%s\"",
xlrec->ts_id, xlrec->ts_path); xlrec->ts_id, xlrec->ts_path);
} }
else if (info == XLOG_TBLSPC_DROP) else if (info == XLOG_TBLSPC_DROP)
{ {
xl_tblspc_drop_rec *xlrec = (xl_tblspc_drop_rec *) rec; xl_tblspc_drop_rec *xlrec = (xl_tblspc_drop_rec *) rec;
sprintf(buf + strlen(buf), "drop ts: %u", appendStringInfo(buf, "drop ts: %u", xlrec->ts_id);
xlrec->ts_id);
} }
else else
strcat(buf, "UNKNOWN"); appendStringInfo(buf, "UNKNOWN");
} }
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/smgr/smgr.c,v 1.96 2006/03/05 15:58:39 momjian Exp $ * $PostgreSQL: pgsql/src/backend/storage/smgr/smgr.c,v 1.97 2006/03/24 04:32:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -942,7 +942,7 @@ smgr_redo(XLogRecPtr lsn, XLogRecord *record) ...@@ -942,7 +942,7 @@ smgr_redo(XLogRecPtr lsn, XLogRecord *record)
} }
void void
smgr_desc(char *buf, uint8 xl_info, char *rec) smgr_desc(StringInfo buf, uint8 xl_info, char *rec)
{ {
uint8 info = xl_info & ~XLR_INFO_MASK; uint8 info = xl_info & ~XLR_INFO_MASK;
...@@ -950,7 +950,7 @@ smgr_desc(char *buf, uint8 xl_info, char *rec) ...@@ -950,7 +950,7 @@ smgr_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_smgr_create *xlrec = (xl_smgr_create *) rec; xl_smgr_create *xlrec = (xl_smgr_create *) rec;
sprintf(buf + strlen(buf), "file create: %u/%u/%u", appendStringInfo(buf, "file create: %u/%u/%u",
xlrec->rnode.spcNode, xlrec->rnode.dbNode, xlrec->rnode.spcNode, xlrec->rnode.dbNode,
xlrec->rnode.relNode); xlrec->rnode.relNode);
} }
...@@ -958,10 +958,10 @@ smgr_desc(char *buf, uint8 xl_info, char *rec) ...@@ -958,10 +958,10 @@ smgr_desc(char *buf, uint8 xl_info, char *rec)
{ {
xl_smgr_truncate *xlrec = (xl_smgr_truncate *) rec; xl_smgr_truncate *xlrec = (xl_smgr_truncate *) rec;
sprintf(buf + strlen(buf), "file truncate: %u/%u/%u to %u blocks", appendStringInfo(buf, "file truncate: %u/%u/%u to %u blocks",
xlrec->rnode.spcNode, xlrec->rnode.dbNode, xlrec->rnode.spcNode, xlrec->rnode.dbNode,
xlrec->rnode.relNode, xlrec->blkno); xlrec->rnode.relNode, xlrec->blkno);
} }
else else
strcat(buf, "UNKNOWN"); appendStringInfo(buf, "UNKNOWN");
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/clog.h,v 1.16 2006/03/05 15:58:53 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/clog.h,v 1.17 2006/03/24 04:32:13 tgl Exp $
*/ */
#ifndef CLOG_H #ifndef CLOG_H
#define CLOG_H #define CLOG_H
...@@ -48,6 +48,6 @@ extern void TruncateCLOG(TransactionId oldestXact); ...@@ -48,6 +48,6 @@ extern void TruncateCLOG(TransactionId oldestXact);
#define CLOG_ZEROPAGE 0x00 #define CLOG_ZEROPAGE 0x00
extern void clog_redo(XLogRecPtr lsn, XLogRecord *record); extern void clog_redo(XLogRecPtr lsn, XLogRecord *record);
extern void clog_desc(char *buf, uint8 xl_info, char *rec); extern void clog_desc(StringInfo buf, uint8 xl_info, char *rec);
#endif /* CLOG_H */ #endif /* CLOG_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.10 2006/03/05 15:58:53 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.11 2006/03/24 04:32:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -244,7 +244,7 @@ extern GISTInsertStack *gistFindPath(Relation r, BlockNumber child, ...@@ -244,7 +244,7 @@ extern GISTInsertStack *gistFindPath(Relation r, BlockNumber child,
/* gistxlog.c */ /* gistxlog.c */
extern void gist_redo(XLogRecPtr lsn, XLogRecord *record); extern void gist_redo(XLogRecPtr lsn, XLogRecord *record);
extern void gist_desc(char *buf, uint8 xl_info, char *rec); extern void gist_desc(StringInfo buf, uint8 xl_info, char *rec);
extern void gist_xlog_startup(void); extern void gist_xlog_startup(void);
extern void gist_xlog_cleanup(void); extern void gist_xlog_cleanup(void);
extern IndexTuple gist_form_invalid_tuple(BlockNumber blkno); extern IndexTuple gist_form_invalid_tuple(BlockNumber blkno);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/hash.h,v 1.66 2006/03/05 15:58:53 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/hash.h,v 1.67 2006/03/24 04:32:13 tgl Exp $
* *
* NOTES * NOTES
* modeled after Margo Seltzer's hash implementation for unix. * modeled after Margo Seltzer's hash implementation for unix.
...@@ -306,6 +306,6 @@ extern void _hash_checkpage(Relation rel, Buffer buf, int flags); ...@@ -306,6 +306,6 @@ extern void _hash_checkpage(Relation rel, Buffer buf, int flags);
/* hash.c */ /* hash.c */
extern void hash_redo(XLogRecPtr lsn, XLogRecord *record); extern void hash_redo(XLogRecPtr lsn, XLogRecord *record);
extern void hash_desc(char *buf, uint8 xl_info, char *rec); extern void hash_desc(StringInfo buf, uint8 xl_info, char *rec);
#endif /* HASH_H */ #endif /* HASH_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.106 2006/03/05 15:58:53 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.107 2006/03/24 04:32:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -178,7 +178,7 @@ extern void heap_markpos(HeapScanDesc scan); ...@@ -178,7 +178,7 @@ extern void heap_markpos(HeapScanDesc scan);
extern void heap_restrpos(HeapScanDesc scan); extern void heap_restrpos(HeapScanDesc scan);
extern void heap_redo(XLogRecPtr lsn, XLogRecord *rptr); extern void heap_redo(XLogRecPtr lsn, XLogRecord *rptr);
extern void heap_desc(char *buf, uint8 xl_info, char *rec); extern void heap_desc(StringInfo buf, uint8 xl_info, char *rec);
extern XLogRecPtr log_heap_clean(Relation reln, Buffer buffer, extern XLogRecPtr log_heap_clean(Relation reln, Buffer buffer,
OffsetNumber *unused, int uncnt); OffsetNumber *unused, int uncnt);
extern XLogRecPtr log_heap_move(Relation reln, Buffer oldbuf, extern XLogRecPtr log_heap_move(Relation reln, Buffer oldbuf,
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/multixact.h,v 1.9 2006/03/05 15:58:53 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/multixact.h,v 1.10 2006/03/24 04:32:13 tgl Exp $
*/ */
#ifndef MULTIXACT_H #ifndef MULTIXACT_H
#define MULTIXACT_H #define MULTIXACT_H
...@@ -67,6 +67,6 @@ extern void MultiXactAdvanceNextMXact(MultiXactId minMulti, ...@@ -67,6 +67,6 @@ extern void MultiXactAdvanceNextMXact(MultiXactId minMulti,
MultiXactOffset minMultiOffset); MultiXactOffset minMultiOffset);
extern void multixact_redo(XLogRecPtr lsn, XLogRecord *record); extern void multixact_redo(XLogRecPtr lsn, XLogRecord *record);
extern void multixact_desc(char *buf, uint8 xl_info, char *rec); extern void multixact_desc(StringInfo buf, uint8 xl_info, char *rec);
#endif /* MULTIXACT_H */ #endif /* MULTIXACT_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.92 2006/03/05 15:58:53 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.93 2006/03/24 04:32:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -470,7 +470,7 @@ extern void _bt_leafbuild(BTSpool *btspool, BTSpool *spool2); ...@@ -470,7 +470,7 @@ extern void _bt_leafbuild(BTSpool *btspool, BTSpool *spool2);
* prototypes for functions in nbtxlog.c * prototypes for functions in nbtxlog.c
*/ */
extern void btree_redo(XLogRecPtr lsn, XLogRecord *record); extern void btree_redo(XLogRecPtr lsn, XLogRecord *record);
extern void btree_desc(char *buf, uint8 xl_info, char *rec); extern void btree_desc(StringInfo buf, uint8 xl_info, char *rec);
extern void btree_xlog_startup(void); extern void btree_xlog_startup(void);
extern void btree_xlog_cleanup(void); extern void btree_xlog_cleanup(void);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/xact.h,v 1.80 2006/03/05 15:58:54 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/xact.h,v 1.81 2006/03/24 04:32:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -175,6 +175,6 @@ extern void RecordTransactionCommit(void); ...@@ -175,6 +175,6 @@ extern void RecordTransactionCommit(void);
extern int xactGetCommittedChildren(TransactionId **ptr); extern int xactGetCommittedChildren(TransactionId **ptr);
extern void xact_redo(XLogRecPtr lsn, XLogRecord *record); extern void xact_redo(XLogRecPtr lsn, XLogRecord *record);
extern void xact_desc(char *buf, uint8 xl_info, char *rec); extern void xact_desc(StringInfo buf, uint8 xl_info, char *rec);
#endif /* XACT_H */ #endif /* XACT_H */
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.70 2006/03/05 15:58:54 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.71 2006/03/24 04:32:13 tgl Exp $
*/ */
#ifndef XLOG_H #ifndef XLOG_H
#define XLOG_H #define XLOG_H
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "access/rmgr.h" #include "access/rmgr.h"
#include "access/transam.h" #include "access/transam.h"
#include "access/xlogdefs.h" #include "access/xlogdefs.h"
#include "lib/stringinfo.h"
#include "storage/buf.h" #include "storage/buf.h"
#include "utils/pg_crc.h" #include "utils/pg_crc.h"
...@@ -152,7 +153,7 @@ extern XLogRecPtr XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata); ...@@ -152,7 +153,7 @@ extern XLogRecPtr XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata);
extern void XLogFlush(XLogRecPtr RecPtr); extern void XLogFlush(XLogRecPtr RecPtr);
extern void xlog_redo(XLogRecPtr lsn, XLogRecord *record); extern void xlog_redo(XLogRecPtr lsn, XLogRecord *record);
extern void xlog_desc(char *buf, uint8 xl_info, char *rec); extern void xlog_desc(StringInfo buf, uint8 xl_info, char *rec);
extern void UpdateControlFile(void); extern void UpdateControlFile(void);
extern Size XLOGShmemSize(void); extern Size XLOGShmemSize(void);
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/xlog_internal.h,v 1.10 2006/03/05 15:58:54 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/xlog_internal.h,v 1.11 2006/03/24 04:32:13 tgl Exp $
*/ */
#ifndef XLOG_INTERNAL_H #ifndef XLOG_INTERNAL_H
#define XLOG_INTERNAL_H #define XLOG_INTERNAL_H
...@@ -228,7 +228,7 @@ typedef struct RmgrData ...@@ -228,7 +228,7 @@ typedef struct RmgrData
{ {
const char *rm_name; const char *rm_name;
void (*rm_redo) (XLogRecPtr lsn, XLogRecord *rptr); void (*rm_redo) (XLogRecPtr lsn, XLogRecord *rptr);
void (*rm_desc) (char *buf, uint8 xl_info, char *rec); void (*rm_desc) (StringInfo buf, uint8 xl_info, char *rec);
void (*rm_startup) (void); void (*rm_startup) (void);
void (*rm_cleanup) (void); void (*rm_cleanup) (void);
} RmgrData; } RmgrData;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/commands/dbcommands.h,v 1.44 2006/03/05 15:58:55 momjian Exp $ * $PostgreSQL: pgsql/src/include/commands/dbcommands.h,v 1.45 2006/03/24 04:32:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -63,6 +63,6 @@ extern Oid get_database_oid(const char *dbname); ...@@ -63,6 +63,6 @@ extern Oid get_database_oid(const char *dbname);
extern char *get_database_name(Oid dbid); extern char *get_database_name(Oid dbid);
extern void dbase_redo(XLogRecPtr lsn, XLogRecord *rptr); extern void dbase_redo(XLogRecPtr lsn, XLogRecord *rptr);
extern void dbase_desc(char *buf, uint8 xl_info, char *rec); extern void dbase_desc(StringInfo buf, uint8 xl_info, char *rec);
#endif /* DBCOMMANDS_H */ #endif /* DBCOMMANDS_H */
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/commands/sequence.h,v 1.35 2006/03/05 15:58:55 momjian Exp $ * $PostgreSQL: pgsql/src/include/commands/sequence.h,v 1.36 2006/03/24 04:32:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -91,7 +91,7 @@ extern void DefineSequence(CreateSeqStmt *stmt); ...@@ -91,7 +91,7 @@ extern void DefineSequence(CreateSeqStmt *stmt);
extern void AlterSequence(AlterSeqStmt *stmt); extern void AlterSequence(AlterSeqStmt *stmt);
extern void seq_redo(XLogRecPtr lsn, XLogRecord *rptr); extern void seq_redo(XLogRecPtr lsn, XLogRecord *rptr);
extern void seq_desc(char *buf, uint8 xl_info, char *rec); extern void seq_desc(StringInfo buf, uint8 xl_info, char *rec);
/* Set the upper and lower bounds of a sequence */ /* Set the upper and lower bounds of a sequence */
#ifndef INT64_IS_BUSTED #ifndef INT64_IS_BUSTED
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/commands/tablespace.h,v 1.12 2006/03/05 15:58:55 momjian Exp $ * $PostgreSQL: pgsql/src/include/commands/tablespace.h,v 1.13 2006/03/24 04:32:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -48,6 +48,6 @@ extern char *get_tablespace_name(Oid spc_oid); ...@@ -48,6 +48,6 @@ extern char *get_tablespace_name(Oid spc_oid);
extern bool directory_is_empty(const char *path); extern bool directory_is_empty(const char *path);
extern void tblspc_redo(XLogRecPtr lsn, XLogRecord *rptr); extern void tblspc_redo(XLogRecPtr lsn, XLogRecord *rptr);
extern void tblspc_desc(char *buf, uint8 xl_info, char *rec); extern void tblspc_desc(StringInfo buf, uint8 xl_info, char *rec);
#endif /* TABLESPACE_H */ #endif /* TABLESPACE_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/storage/smgr.h,v 1.54 2006/03/05 15:59:00 momjian Exp $ * $PostgreSQL: pgsql/src/include/storage/smgr.h,v 1.55 2006/03/24 04:32:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -85,7 +85,7 @@ extern void smgrabort(void); ...@@ -85,7 +85,7 @@ extern void smgrabort(void);
extern void smgrsync(void); extern void smgrsync(void);
extern void smgr_redo(XLogRecPtr lsn, XLogRecord *record); extern void smgr_redo(XLogRecPtr lsn, XLogRecord *record);
extern void smgr_desc(char *buf, uint8 xl_info, char *rec); extern void smgr_desc(StringInfo buf, uint8 xl_info, char *rec);
/* internals: move me elsewhere -- ay 7/94 */ /* internals: move me elsewhere -- ay 7/94 */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册