2012-11-28 16:35:01 +01:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* gindesc.c
|
2013-05-29 22:58:43 +02:00
|
|
|
* rmgr descriptor routines for access/transam/gin/ginxlog.c
|
2012-11-28 16:35:01 +01:00
|
|
|
*
|
2014-01-07 22:05:30 +01:00
|
|
|
* Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
|
2012-11-28 16:35:01 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2013-05-29 22:58:43 +02:00
|
|
|
* src/backend/access/rmgrdesc/gindesc.c
|
2012-11-28 16:35:01 +01:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
#include "access/gin_private.h"
|
|
|
|
#include "lib/stringinfo.h"
|
|
|
|
#include "storage/relfilenode.h"
|
|
|
|
|
|
|
|
static void
|
|
|
|
desc_node(StringInfo buf, RelFileNode node, BlockNumber blkno)
|
|
|
|
{
|
|
|
|
appendStringInfo(buf, "node: %u/%u/%u blkno: %u",
|
|
|
|
node.spcNode, node.dbNode, node.relNode, blkno);
|
|
|
|
}
|
|
|
|
|
2014-03-31 14:15:19 +02:00
|
|
|
static void
|
|
|
|
desc_recompress_leaf(StringInfo buf, ginxlogRecompressDataLeaf *insertData)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *walbuf = ((char *) insertData) + sizeof(ginxlogRecompressDataLeaf);
|
|
|
|
|
|
|
|
appendStringInfo(buf, " %d segments:", (int) insertData->nactions);
|
|
|
|
|
|
|
|
for (i = 0; i < insertData->nactions; i++)
|
|
|
|
{
|
|
|
|
uint8 a_segno = *((uint8 *) (walbuf++));
|
|
|
|
uint8 a_action = *((uint8 *) (walbuf++));
|
|
|
|
uint16 nitems = 0;
|
|
|
|
int newsegsize = 0;
|
|
|
|
|
|
|
|
if (a_action == GIN_SEGMENT_INSERT ||
|
|
|
|
a_action == GIN_SEGMENT_REPLACE)
|
|
|
|
{
|
|
|
|
newsegsize = SizeOfGinPostingList((GinPostingList *) walbuf);
|
|
|
|
walbuf += SHORTALIGN(newsegsize);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a_action == GIN_SEGMENT_ADDITEMS)
|
|
|
|
{
|
|
|
|
memcpy(&nitems, walbuf, sizeof(uint16));
|
|
|
|
walbuf += sizeof(uint16);
|
|
|
|
walbuf += nitems * sizeof(ItemPointerData);
|
|
|
|
}
|
|
|
|
|
2014-05-06 18:12:18 +02:00
|
|
|
switch (a_action)
|
2014-03-31 14:15:19 +02:00
|
|
|
{
|
|
|
|
case GIN_SEGMENT_ADDITEMS:
|
|
|
|
appendStringInfo(buf, " %d (add %d items)", a_segno, nitems);
|
|
|
|
break;
|
|
|
|
case GIN_SEGMENT_DELETE:
|
|
|
|
appendStringInfo(buf, " %d (delete)", a_segno);
|
|
|
|
break;
|
|
|
|
case GIN_SEGMENT_INSERT:
|
|
|
|
appendStringInfo(buf, " %d (insert)", a_segno);
|
|
|
|
break;
|
|
|
|
case GIN_SEGMENT_REPLACE:
|
|
|
|
appendStringInfo(buf, " %d (replace)", a_segno);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
appendStringInfo(buf, " %d unknown action %d ???", a_segno, a_action);
|
|
|
|
/* cannot decode unrecognized actions further */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-28 16:35:01 +01:00
|
|
|
void
|
2014-06-14 09:46:48 +02:00
|
|
|
gin_desc(StringInfo buf, XLogRecord *record)
|
2012-11-28 16:35:01 +01:00
|
|
|
{
|
2014-06-14 09:46:48 +02:00
|
|
|
char *rec = XLogRecGetData(record);
|
|
|
|
uint8 info = record->xl_info & ~XLR_INFO_MASK;
|
2012-11-28 16:35:01 +01:00
|
|
|
|
|
|
|
switch (info)
|
|
|
|
{
|
|
|
|
case XLOG_GIN_CREATE_INDEX:
|
|
|
|
desc_node(buf, *(RelFileNode *) rec, GIN_ROOT_BLKNO);
|
|
|
|
break;
|
|
|
|
case XLOG_GIN_CREATE_PTREE:
|
|
|
|
desc_node(buf, ((ginxlogCreatePostingTree *) rec)->node, ((ginxlogCreatePostingTree *) rec)->blkno);
|
|
|
|
break;
|
|
|
|
case XLOG_GIN_INSERT:
|
2013-11-27 18:21:23 +01:00
|
|
|
{
|
|
|
|
ginxlogInsert *xlrec = (ginxlogInsert *) rec;
|
2014-05-06 18:12:18 +02:00
|
|
|
char *payload = rec + sizeof(ginxlogInsert);
|
2013-11-27 18:21:23 +01:00
|
|
|
|
|
|
|
desc_node(buf, xlrec->node, xlrec->blkno);
|
2014-01-22 17:51:48 +01:00
|
|
|
appendStringInfo(buf, " isdata: %c isleaf: %c",
|
2014-05-06 18:12:18 +02:00
|
|
|
(xlrec->flags & GIN_INSERT_ISDATA) ? 'T' : 'F',
|
|
|
|
(xlrec->flags & GIN_INSERT_ISLEAF) ? 'T' : 'F');
|
2013-11-27 18:21:23 +01:00
|
|
|
if (!(xlrec->flags & GIN_INSERT_ISLEAF))
|
|
|
|
{
|
|
|
|
BlockNumber leftChildBlkno;
|
|
|
|
BlockNumber rightChildBlkno;
|
|
|
|
|
2013-11-28 20:54:49 +01:00
|
|
|
leftChildBlkno = BlockIdGetBlockNumber((BlockId) payload);
|
|
|
|
payload += sizeof(BlockIdData);
|
|
|
|
rightChildBlkno = BlockIdGetBlockNumber((BlockId) payload);
|
2013-11-27 18:21:23 +01:00
|
|
|
payload += sizeof(BlockNumber);
|
|
|
|
appendStringInfo(buf, " children: %u/%u",
|
|
|
|
leftChildBlkno, rightChildBlkno);
|
|
|
|
}
|
|
|
|
if (!(xlrec->flags & GIN_INSERT_ISDATA))
|
|
|
|
appendStringInfo(buf, " isdelete: %c",
|
2014-05-06 18:12:18 +02:00
|
|
|
(((ginxlogInsertEntry *) payload)->isDelete) ? 'T' : 'F');
|
2013-11-27 18:21:23 +01:00
|
|
|
else if (xlrec->flags & GIN_INSERT_ISLEAF)
|
2014-01-22 17:51:48 +01:00
|
|
|
{
|
|
|
|
ginxlogRecompressDataLeaf *insertData =
|
2014-05-06 18:12:18 +02:00
|
|
|
(ginxlogRecompressDataLeaf *) payload;
|
2014-01-22 17:51:48 +01:00
|
|
|
|
2014-06-14 09:46:48 +02:00
|
|
|
if (record->xl_info & XLR_BKP_BLOCK(0))
|
2014-03-31 14:15:19 +02:00
|
|
|
appendStringInfo(buf, " (full page image)");
|
|
|
|
else
|
|
|
|
desc_recompress_leaf(buf, insertData);
|
2014-01-22 17:51:48 +01:00
|
|
|
}
|
2013-11-27 18:21:23 +01:00
|
|
|
else
|
2014-01-22 17:51:48 +01:00
|
|
|
{
|
|
|
|
ginxlogInsertDataInternal *insertData = (ginxlogInsertDataInternal *) payload;
|
2014-05-06 18:12:18 +02:00
|
|
|
|
2013-11-27 18:21:23 +01:00
|
|
|
appendStringInfo(buf, " pitem: %u-%u/%u",
|
2014-05-06 18:12:18 +02:00
|
|
|
PostingItemGetBlockNumber(&insertData->newitem),
|
|
|
|
ItemPointerGetBlockNumber(&insertData->newitem.key),
|
|
|
|
ItemPointerGetOffsetNumber(&insertData->newitem.key));
|
2014-01-22 17:51:48 +01:00
|
|
|
}
|
2013-11-27 18:21:23 +01:00
|
|
|
}
|
2012-11-28 16:35:01 +01:00
|
|
|
break;
|
|
|
|
case XLOG_GIN_SPLIT:
|
2014-01-22 17:51:48 +01:00
|
|
|
{
|
|
|
|
ginxlogSplit *xlrec = (ginxlogSplit *) rec;
|
|
|
|
|
|
|
|
desc_node(buf, ((ginxlogSplit *) rec)->node, ((ginxlogSplit *) rec)->lblkno);
|
|
|
|
appendStringInfo(buf, " isrootsplit: %c", (((ginxlogSplit *) rec)->flags & GIN_SPLIT_ROOT) ? 'T' : 'F');
|
|
|
|
appendStringInfo(buf, " isdata: %c isleaf: %c",
|
2014-05-06 18:12:18 +02:00
|
|
|
(xlrec->flags & GIN_INSERT_ISDATA) ? 'T' : 'F',
|
|
|
|
(xlrec->flags & GIN_INSERT_ISLEAF) ? 'T' : 'F');
|
2014-01-22 17:51:48 +01:00
|
|
|
}
|
2012-11-28 16:35:01 +01:00
|
|
|
break;
|
|
|
|
case XLOG_GIN_VACUUM_PAGE:
|
|
|
|
desc_node(buf, ((ginxlogVacuumPage *) rec)->node, ((ginxlogVacuumPage *) rec)->blkno);
|
|
|
|
break;
|
2014-01-22 17:51:48 +01:00
|
|
|
case XLOG_GIN_VACUUM_DATA_LEAF_PAGE:
|
|
|
|
{
|
|
|
|
ginxlogVacuumDataLeafPage *xlrec = (ginxlogVacuumDataLeafPage *) rec;
|
2014-05-06 18:12:18 +02:00
|
|
|
|
2014-01-22 17:51:48 +01:00
|
|
|
desc_node(buf, xlrec->node, xlrec->blkno);
|
2014-06-14 09:46:48 +02:00
|
|
|
if (record->xl_info & XLR_BKP_BLOCK(0))
|
2014-03-31 14:15:19 +02:00
|
|
|
appendStringInfo(buf, " (full page image)");
|
|
|
|
else
|
|
|
|
desc_recompress_leaf(buf, &xlrec->data);
|
2014-01-22 17:51:48 +01:00
|
|
|
}
|
|
|
|
break;
|
2012-11-28 16:35:01 +01:00
|
|
|
case XLOG_GIN_DELETE_PAGE:
|
|
|
|
desc_node(buf, ((ginxlogDeletePage *) rec)->node, ((ginxlogDeletePage *) rec)->blkno);
|
|
|
|
break;
|
|
|
|
case XLOG_GIN_UPDATE_META_PAGE:
|
|
|
|
desc_node(buf, ((ginxlogUpdateMeta *) rec)->node, GIN_METAPAGE_BLKNO);
|
|
|
|
break;
|
|
|
|
case XLOG_GIN_INSERT_LISTPAGE:
|
|
|
|
desc_node(buf, ((ginxlogInsertListPage *) rec)->node, ((ginxlogInsertListPage *) rec)->blkno);
|
|
|
|
break;
|
|
|
|
case XLOG_GIN_DELETE_LISTPAGE:
|
2014-09-19 15:17:12 +02:00
|
|
|
appendStringInfo(buf, "%d pages, ", ((ginxlogDeleteListPages *) rec)->ndeleted);
|
2012-11-28 16:35:01 +01:00
|
|
|
desc_node(buf, ((ginxlogDeleteListPages *) rec)->node, GIN_METAPAGE_BLKNO);
|
|
|
|
break;
|
2014-09-19 15:17:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
gin_identify(uint8 info)
|
|
|
|
{
|
|
|
|
const char *id = NULL;
|
|
|
|
|
2014-09-22 16:48:14 +02:00
|
|
|
switch (info & ~XLR_INFO_MASK)
|
2014-09-19 15:17:12 +02:00
|
|
|
{
|
|
|
|
case XLOG_GIN_CREATE_INDEX:
|
|
|
|
id = "CREATE_INDEX";
|
|
|
|
break;
|
|
|
|
case XLOG_GIN_CREATE_PTREE:
|
|
|
|
id = "CREATE_PTREE";
|
|
|
|
break;
|
|
|
|
case XLOG_GIN_INSERT:
|
|
|
|
id = "INSERT";
|
|
|
|
break;
|
|
|
|
case XLOG_GIN_SPLIT:
|
|
|
|
id = "SPLIT";
|
|
|
|
break;
|
|
|
|
case XLOG_GIN_VACUUM_PAGE:
|
|
|
|
id = "VACUUM_PAGE";
|
|
|
|
break;
|
|
|
|
case XLOG_GIN_VACUUM_DATA_LEAF_PAGE:
|
|
|
|
id = "VACUUM_DATA_LEAF_PAGE";
|
|
|
|
break;
|
|
|
|
case XLOG_GIN_DELETE_PAGE:
|
|
|
|
id = "DELETE_PAGE";
|
|
|
|
break;
|
|
|
|
case XLOG_GIN_UPDATE_META_PAGE:
|
|
|
|
id = "UPDATE_META_PAGE";
|
|
|
|
break;
|
|
|
|
case XLOG_GIN_INSERT_LISTPAGE:
|
|
|
|
id = "INSERT_LISTPAGE";
|
|
|
|
break;
|
|
|
|
case XLOG_GIN_DELETE_LISTPAGE:
|
|
|
|
id = "DELETE_LISTPAGE";
|
2012-11-28 16:35:01 +01:00
|
|
|
break;
|
|
|
|
}
|
2014-09-19 15:17:12 +02:00
|
|
|
|
|
|
|
return id;
|
2012-11-28 16:35:01 +01:00
|
|
|
}
|