* storage.c
* code to create and destroy physical storage for relations
*
- * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
#include "access/visibilitymap.h"
#include "access/xact.h"
+#include "access/xlog.h"
+#include "access/xloginsert.h"
#include "access/xlogutils.h"
#include "catalog/catalog.h"
#include "catalog/storage.h"
* that have been created or deleted in the current transaction. When
* a relation is created, we create the physical file immediately, but
* remember it so that we can delete the file again if the current
- * transaction is aborted. Conversely, a deletion request is NOT
+ * transaction is aborted. Conversely, a deletion request is NOT
* executed immediately, but is just entered in the list. When and if
* the transaction commits, we can delete the physical file.
*
}
/*
- * Perform XLogInsert of a XLOG_SMGR_CREATE record to WAL.
+ * Perform XLogInsert of an XLOG_SMGR_CREATE record to WAL.
*/
void
log_smgrcreate(RelFileNode *rnode, ForkNumber forkNum)
{
xl_smgr_create xlrec;
- XLogRecData rdata;
/*
* Make an XLOG entry reporting the file creation.
xlrec.rnode = *rnode;
xlrec.forkNum = forkNum;
- rdata.data = (char *) &xlrec;
- rdata.len = sizeof(xlrec);
- rdata.buffer = InvalidBuffer;
- rdata.next = NULL;
-
- XLogInsert(RM_SMGR_ID, XLOG_SMGR_CREATE, &rdata);
+ XLogBeginInsert();
+ XLogRegisterData((char *) &xlrec, sizeof(xlrec));
+ XLogInsert(RM_SMGR_ID, XLOG_SMGR_CREATE | XLR_SPECIAL_REL_UPDATE);
}
/*
* Make an XLOG entry reporting the file truncation.
*/
XLogRecPtr lsn;
- XLogRecData rdata;
xl_smgr_truncate xlrec;
xlrec.blkno = nblocks;
xlrec.rnode = rel->rd_node;
- rdata.data = (char *) &xlrec;
- rdata.len = sizeof(xlrec);
- rdata.buffer = InvalidBuffer;
- rdata.next = NULL;
+ XLogBeginInsert();
+ XLogRegisterData((char *) &xlrec, sizeof(xlrec));
- lsn = XLogInsert(RM_SMGR_ID, XLOG_SMGR_TRUNCATE, &rdata);
+ lsn = XLogInsert(RM_SMGR_ID,
+ XLOG_SMGR_TRUNCATE | XLR_SPECIAL_REL_UPDATE);
/*
* Flush, because otherwise the truncation of the main relation might
PendingRelDelete *next;
int nrels = 0,
i = 0,
- maxrels = 8;
- SMgrRelation *srels = palloc(maxrels * sizeof(SMgrRelation));
+ maxrels = 0;
+ SMgrRelation *srels = NULL;
prev = NULL;
for (pending = pendingDeletes; pending != NULL; pending = next)
srel = smgropen(pending->relnode, pending->backend);
- /* extend the array if needed (double the size) */
- if (maxrels <= nrels)
+ /* allocate the initial array, or extend it, if needed */
+ if (maxrels == 0)
+ {
+ maxrels = 8;
+ srels = palloc(sizeof(SMgrRelation) * maxrels);
+ }
+ else if (maxrels <= nrels)
{
maxrels *= 2;
srels = repalloc(srels, sizeof(SMgrRelation) * maxrels);
for (i = 0; i < nrels; i++)
smgrclose(srels[i]);
- }
-
- pfree(srels);
+ pfree(srels);
+ }
}
/*
* *ptr is set to point to a freshly-palloc'd array of RelFileNodes.
* If there are no relations to be deleted, *ptr is set to NULL.
*
- * Only non-temporary relations are included in the returned list. This is OK
+ * Only non-temporary relations are included in the returned list. This is OK
* because the list is used only in contexts where temporary relations don't
* matter: we're either writing to the two-phase state file (and transactions
* that have touched temp tables can't be prepared) or we're writing to xlog
}
void
-smgr_redo(XLogRecPtr lsn, XLogRecord *record)
+smgr_redo(XLogReaderState *record)
{
- uint8 info = record->xl_info & ~XLR_INFO_MASK;
+ XLogRecPtr lsn = record->EndRecPtr;
+ uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
/* Backup blocks are not used in smgr records */
- Assert(!(record->xl_info & XLR_BKP_BLOCK_MASK));
+ Assert(!XLogRecHasAnyBlockRefs(record));
if (info == XLOG_SMGR_CREATE)
{
/*
* Forcibly create relation if it doesn't exist (which suggests that
* it was dropped somewhere later in the WAL sequence). As in
- * XLogReadBuffer, we prefer to recreate the rel and replay the log as
- * best we can until the drop is seen.
+ * XLogReadBufferForRedo, we prefer to recreate the rel and replay the
+ * log as best we can until the drop is seen.
*/
smgrcreate(reln, MAIN_FORKNUM, true);
/*
- * Before we perform the truncation, update minimum recovery point
- * to cover this WAL record. Once the relation is truncated, there's
- * no going back. The buffer manager enforces the WAL-first rule
- * for normal updates to relation files, so that the minimum recovery
- * point is always updated before the corresponding change in the
- * data file is flushed to disk. We have to do the same manually
- * here.
+ * Before we perform the truncation, update minimum recovery point to
+ * cover this WAL record. Once the relation is truncated, there's no
+ * going back. The buffer manager enforces the WAL-first rule for
+ * normal updates to relation files, so that the minimum recovery
+ * point is always updated before the corresponding change in the data
+ * file is flushed to disk. We have to do the same manually here.
*
* Doing this before the truncation means that if the truncation fails
* for some reason, you cannot start up the system even after restart,