Compare commits

..

No commits in common. "00d7fb5e2e39198387ae00af8dd18b787b6a4d63" and "b6f1cca9ba3d24c8fcaa9facc30c96bcc50b37aa" have entirely different histories.

21 changed files with 116 additions and 263 deletions

View File

@ -1119,7 +1119,7 @@ SELECT a.pid, a.wait_event, w.description
FROM pg_stat_activity a JOIN FROM pg_stat_activity a JOIN
pg_wait_events w ON (a.wait_event_type = w.type AND pg_wait_events w ON (a.wait_event_type = w.type AND
a.wait_event = w.name) a.wait_event = w.name)
WHERE a.wait_event is NOT NULL and a.state = 'active'; WHERE wait_event is NOT NULL and a.state = 'active';
-[ RECORD 1 ]------------------------------------------------------&zwsp;------------ -[ RECORD 1 ]------------------------------------------------------&zwsp;------------
pid | 686674 pid | 686674
wait_event | WALInitSync wait_event | WALInitSync

View File

@ -387,22 +387,24 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
START_CRIT_SECTION(); START_CRIT_SECTION();
if (RelationNeedsWAL(btree->index) && !btree->isBuild) if (RelationNeedsWAL(btree->index) && !btree->isBuild)
{
XLogBeginInsert(); XLogBeginInsert();
XLogRegisterBuffer(0, stack->buffer, REGBUF_STANDARD);
if (BufferIsValid(childbuf))
XLogRegisterBuffer(1, childbuf, REGBUF_STANDARD);
}
/* /* Perform the page update, and register any extra WAL data */
* Perform the page update, dirty and register stack->buffer, and
* register any extra WAL data.
*/
btree->execPlaceToPage(btree, stack->buffer, stack, btree->execPlaceToPage(btree, stack->buffer, stack,
insertdata, updateblkno, ptp_workspace); insertdata, updateblkno, ptp_workspace);
MarkBufferDirty(stack->buffer);
/* An insert to an internal page finishes the split of the child. */ /* An insert to an internal page finishes the split of the child. */
if (BufferIsValid(childbuf)) if (BufferIsValid(childbuf))
{ {
GinPageGetOpaque(childpage)->flags &= ~GIN_INCOMPLETE_SPLIT; GinPageGetOpaque(childpage)->flags &= ~GIN_INCOMPLETE_SPLIT;
MarkBufferDirty(childbuf); MarkBufferDirty(childbuf);
if (RelationNeedsWAL(btree->index) && !btree->isBuild)
XLogRegisterBuffer(1, childbuf, REGBUF_STANDARD);
} }
if (RelationNeedsWAL(btree->index) && !btree->isBuild) if (RelationNeedsWAL(btree->index) && !btree->isBuild)

View File

@ -721,12 +721,9 @@ dataExecPlaceToPageLeaf(GinBtree btree, Buffer buf, GinBtreeStack *stack,
/* Apply changes to page */ /* Apply changes to page */
dataPlaceToPageLeafRecompress(buf, leaf); dataPlaceToPageLeafRecompress(buf, leaf);
MarkBufferDirty(buf);
/* If needed, register WAL data built by computeLeafRecompressWALData */ /* If needed, register WAL data built by computeLeafRecompressWALData */
if (RelationNeedsWAL(btree->index) && !btree->isBuild) if (RelationNeedsWAL(btree->index) && !btree->isBuild)
{ {
XLogRegisterBuffer(0, buf, REGBUF_STANDARD);
XLogRegisterBufData(0, leaf->walinfo, leaf->walinfolen); XLogRegisterBufData(0, leaf->walinfo, leaf->walinfolen);
} }
} }
@ -1158,8 +1155,6 @@ dataExecPlaceToPageInternal(GinBtree btree, Buffer buf, GinBtreeStack *stack,
pitem = (PostingItem *) insertdata; pitem = (PostingItem *) insertdata;
GinDataPageAddPostingItem(page, pitem, off); GinDataPageAddPostingItem(page, pitem, off);
MarkBufferDirty(buf);
if (RelationNeedsWAL(btree->index) && !btree->isBuild) if (RelationNeedsWAL(btree->index) && !btree->isBuild)
{ {
/* /*
@ -1172,7 +1167,6 @@ dataExecPlaceToPageInternal(GinBtree btree, Buffer buf, GinBtreeStack *stack,
data.offset = off; data.offset = off;
data.newitem = *pitem; data.newitem = *pitem;
XLogRegisterBuffer(0, buf, REGBUF_STANDARD);
XLogRegisterBufData(0, (char *) &data, XLogRegisterBufData(0, (char *) &data,
sizeof(ginxlogInsertDataInternal)); sizeof(ginxlogInsertDataInternal));
} }

View File

@ -571,8 +571,6 @@ entryExecPlaceToPage(GinBtree btree, Buffer buf, GinBtreeStack *stack,
elog(ERROR, "failed to add item to index page in \"%s\"", elog(ERROR, "failed to add item to index page in \"%s\"",
RelationGetRelationName(btree->index)); RelationGetRelationName(btree->index));
MarkBufferDirty(buf);
if (RelationNeedsWAL(btree->index) && !btree->isBuild) if (RelationNeedsWAL(btree->index) && !btree->isBuild)
{ {
/* /*
@ -585,7 +583,6 @@ entryExecPlaceToPage(GinBtree btree, Buffer buf, GinBtreeStack *stack,
data.isDelete = insertData->isDelete; data.isDelete = insertData->isDelete;
data.offset = off; data.offset = off;
XLogRegisterBuffer(0, buf, REGBUF_STANDARD);
XLogRegisterBufData(0, (char *) &data, XLogRegisterBufData(0, (char *) &data,
offsetof(ginxlogInsertEntry, tuple)); offsetof(ginxlogInsertEntry, tuple));
XLogRegisterBufData(0, (char *) insertData->entry, XLogRegisterBufData(0, (char *) insertData->entry,

View File

@ -397,9 +397,6 @@ ginHeapTupleFastInsert(GinState *ginstate, GinTupleCollector *collector)
} }
Assert((ptr - collectordata) <= collector->sumsize); Assert((ptr - collectordata) <= collector->sumsize);
MarkBufferDirty(buffer);
if (needWal) if (needWal)
{ {
XLogRegisterBuffer(1, buffer, REGBUF_STANDARD); XLogRegisterBuffer(1, buffer, REGBUF_STANDARD);
@ -407,6 +404,8 @@ ginHeapTupleFastInsert(GinState *ginstate, GinTupleCollector *collector)
} }
metadata->tailFreeSize = PageGetExactFreeSpace(page); metadata->tailFreeSize = PageGetExactFreeSpace(page);
MarkBufferDirty(buffer);
} }
/* /*

View File

@ -824,16 +824,11 @@ hashbucketcleanup(Relation rel, Bucket cur_bucket, Buffer bucket_buf,
XLogRegisterData((char *) &xlrec, SizeOfHashDelete); XLogRegisterData((char *) &xlrec, SizeOfHashDelete);
/* /*
* bucket buffer was not changed, but still needs to be * bucket buffer needs to be registered to ensure that we can
* registered to ensure that we can acquire a cleanup lock on * acquire a cleanup lock on it during replay.
* it during replay.
*/ */
if (!xlrec.is_primary_bucket_page) if (!xlrec.is_primary_bucket_page)
{ XLogRegisterBuffer(0, bucket_buf, REGBUF_STANDARD | REGBUF_NO_IMAGE);
uint8 flags = REGBUF_STANDARD | REGBUF_NO_IMAGE | REGBUF_NO_CHANGE;
XLogRegisterBuffer(0, bucket_buf, flags);
}
XLogRegisterBuffer(1, buf, REGBUF_STANDARD); XLogRegisterBuffer(1, buf, REGBUF_STANDARD);
XLogRegisterBufData(1, (char *) deletable, XLogRegisterBufData(1, (char *) deletable,

View File

@ -658,15 +658,11 @@ _hash_freeovflpage(Relation rel, Buffer bucketbuf, Buffer ovflbuf,
XLogRegisterData((char *) &xlrec, SizeOfHashSqueezePage); XLogRegisterData((char *) &xlrec, SizeOfHashSqueezePage);
/* /*
* bucket buffer was not changed, but still needs to be registered to * bucket buffer needs to be registered to ensure that we can acquire
* ensure that we can acquire a cleanup lock on it during replay. * a cleanup lock on it during replay.
*/ */
if (!xlrec.is_prim_bucket_same_wrt) if (!xlrec.is_prim_bucket_same_wrt)
{ XLogRegisterBuffer(0, bucketbuf, REGBUF_STANDARD | REGBUF_NO_IMAGE);
uint8 flags = REGBUF_STANDARD | REGBUF_NO_IMAGE | REGBUF_NO_CHANGE;
XLogRegisterBuffer(0, bucketbuf, flags);
}
XLogRegisterBuffer(1, wbuf, REGBUF_STANDARD); XLogRegisterBuffer(1, wbuf, REGBUF_STANDARD);
if (xlrec.ntups > 0) if (xlrec.ntups > 0)
@ -964,16 +960,11 @@ readpage:
XLogRegisterData((char *) &xlrec, SizeOfHashMovePageContents); XLogRegisterData((char *) &xlrec, SizeOfHashMovePageContents);
/* /*
* bucket buffer was not changed, but still needs to * bucket buffer needs to be registered to ensure that
* be registered to ensure that we can acquire a * we can acquire a cleanup lock on it during replay.
* cleanup lock on it during replay.
*/ */
if (!xlrec.is_prim_bucket_same_wrt) if (!xlrec.is_prim_bucket_same_wrt)
{ XLogRegisterBuffer(0, bucket_buf, REGBUF_STANDARD | REGBUF_NO_IMAGE);
int flags = REGBUF_STANDARD | REGBUF_NO_IMAGE | REGBUF_NO_CHANGE;
XLogRegisterBuffer(0, bucket_buf, flags);
}
XLogRegisterBuffer(1, wbuf, REGBUF_STANDARD); XLogRegisterBuffer(1, wbuf, REGBUF_STANDARD);
XLogRegisterBufData(1, (char *) itup_offsets, XLogRegisterBufData(1, (char *) itup_offsets,

View File

@ -8579,22 +8579,9 @@ do_pg_backup_start(const char *backupidstr, bool fast, List **tablespaces,
char *relpath = NULL; char *relpath = NULL;
char *s; char *s;
PGFileType de_type; PGFileType de_type;
char *badp;
Oid tsoid;
/* /* Skip anything that doesn't look like a tablespace */
* Try to parse the directory name as an unsigned integer. if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
*
* Tablespace directories should be positive integers that can be
* represented in 32 bits, with no leading zeroes or trailing
* garbage. If we come across a name that doesn't meet those
* criteria, skip it.
*/
if (de->d_name[0] < '1' || de->d_name[1] > '9')
continue;
errno = 0;
tsoid = strtoul(de->d_name, &badp, 10);
if (*badp != '\0' || errno == EINVAL || errno == ERANGE)
continue; continue;
snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name); snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);
@ -8669,7 +8656,7 @@ do_pg_backup_start(const char *backupidstr, bool fast, List **tablespaces,
} }
ti = palloc(sizeof(tablespaceinfo)); ti = palloc(sizeof(tablespaceinfo));
ti->oid = tsoid; ti->oid = pstrdup(de->d_name);
ti->path = pstrdup(linkpath); ti->path = pstrdup(linkpath);
ti->rpath = relpath; ti->rpath = relpath;
ti->size = -1; ti->size = -1;

View File

@ -248,20 +248,6 @@ XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Assert(!((flags & REGBUF_FORCE_IMAGE) && (flags & (REGBUF_NO_IMAGE)))); Assert(!((flags & REGBUF_FORCE_IMAGE) && (flags & (REGBUF_NO_IMAGE))));
Assert(begininsert_called); Assert(begininsert_called);
/*
* Ordinarily, buffer should be exclusive-locked and marked dirty before
* we get here, otherwise we could end up violating one of the rules in
* access/transam/README.
*
* Some callers intentionally register a clean page and never update that
* page's LSN; in that case they can pass the flag REGBUF_NO_CHANGE to
* bypass these checks.
*/
#ifdef USE_ASSERT_CHECKING
if (!(flags & REGBUF_NO_CHANGE))
Assert(BufferIsExclusiveLocked(buffer) && BufferIsDirty(buffer));
#endif
if (block_id >= max_registered_block_id) if (block_id >= max_registered_block_id)
{ {
if (block_id >= max_registered_buffers) if (block_id >= max_registered_buffers)
@ -1327,8 +1313,8 @@ log_newpage_range(Relation rel, ForkNumber forknum,
START_CRIT_SECTION(); START_CRIT_SECTION();
for (i = 0; i < nbufs; i++) for (i = 0; i < nbufs; i++)
{ {
MarkBufferDirty(bufpack[i]);
XLogRegisterBuffer(i, bufpack[i], flags); XLogRegisterBuffer(i, bufpack[i], flags);
MarkBufferDirty(bufpack[i]);
} }
recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI); recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI);

View File

@ -678,7 +678,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
tablespaceinfo *ti = lfirst(lc); tablespaceinfo *ti = lfirst(lc);
char *linkloc; char *linkloc;
linkloc = psprintf("pg_tblspc/%u", ti->oid); linkloc = psprintf("pg_tblspc/%s", ti->oid);
/* /*
* Remove the existing symlink if any and Create the symlink * Remove the existing symlink if any and Create the symlink
@ -692,6 +692,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
errmsg("could not create symbolic link \"%s\": %m", errmsg("could not create symbolic link \"%s\": %m",
linkloc))); linkloc)));
pfree(ti->oid);
pfree(ti->path); pfree(ti->path);
pfree(ti); pfree(ti);
} }
@ -1340,8 +1341,6 @@ read_tablespace_map(List **tablespaces)
{ {
if (!was_backslash && (ch == '\n' || ch == '\r')) if (!was_backslash && (ch == '\n' || ch == '\r'))
{ {
char *endp;
if (i == 0) if (i == 0)
continue; /* \r immediately followed by \n */ continue; /* \r immediately followed by \n */
@ -1361,12 +1360,7 @@ read_tablespace_map(List **tablespaces)
str[n++] = '\0'; str[n++] = '\0';
ti = palloc0(sizeof(tablespaceinfo)); ti = palloc0(sizeof(tablespaceinfo));
errno = 0; ti->oid = pstrdup(str);
ti->oid = strtoul(str, &endp, 10);
if (*endp != '\0' || errno == EINVAL || errno == ERANGE)
ereport(FATAL,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
ti->path = pstrdup(str + n); ti->path = pstrdup(str + n);
*tablespaces = lappend(*tablespaces, ti); *tablespaces = lappend(*tablespaces, ti);

View File

@ -97,7 +97,7 @@ FreeBackupManifest(backup_manifest_info *manifest)
* Add an entry to the backup manifest for a file. * Add an entry to the backup manifest for a file.
*/ */
void void
AddFileToBackupManifest(backup_manifest_info *manifest, Oid spcoid, AddFileToBackupManifest(backup_manifest_info *manifest, const char *spcoid,
const char *pathname, size_t size, pg_time_t mtime, const char *pathname, size_t size, pg_time_t mtime,
pg_checksum_context *checksum_ctx) pg_checksum_context *checksum_ctx)
{ {
@ -114,9 +114,9 @@ AddFileToBackupManifest(backup_manifest_info *manifest, Oid spcoid,
* pathname relative to the data directory (ignoring the intermediate * pathname relative to the data directory (ignoring the intermediate
* symlink traversal). * symlink traversal).
*/ */
if (OidIsValid(spcoid)) if (spcoid != NULL)
{ {
snprintf(pathbuf, sizeof(pathbuf), "pg_tblspc/%u/%s", spcoid, snprintf(pathbuf, sizeof(pathbuf), "pg_tblspc/%s/%s", spcoid,
pathname); pathname);
pathname = pathbuf; pathname = pathbuf;
} }

View File

@ -75,15 +75,14 @@ typedef struct
pg_checksum_type manifest_checksum_type; pg_checksum_type manifest_checksum_type;
} basebackup_options; } basebackup_options;
static int64 sendTablespace(bbsink *sink, char *path, Oid spcoid, bool sizeonly, static int64 sendTablespace(bbsink *sink, char *path, char *spcoid, bool sizeonly,
struct backup_manifest_info *manifest); struct backup_manifest_info *manifest);
static int64 sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly, static int64 sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
List *tablespaces, bool sendtblspclinks, List *tablespaces, bool sendtblspclinks,
backup_manifest_info *manifest, Oid spcoid); backup_manifest_info *manifest, const char *spcoid);
static bool sendFile(bbsink *sink, const char *readfilename, const char *tarfilename, static bool sendFile(bbsink *sink, const char *readfilename, const char *tarfilename,
struct stat *statbuf, bool missing_ok, struct stat *statbuf, bool missing_ok, Oid dboid,
Oid dboid, Oid spcoid, backup_manifest_info *manifest, const char *spcoid);
backup_manifest_info *manifest);
static off_t read_file_data_into_buffer(bbsink *sink, static off_t read_file_data_into_buffer(bbsink *sink,
const char *readfilename, int fd, const char *readfilename, int fd,
off_t offset, size_t length, off_t offset, size_t length,
@ -306,7 +305,7 @@ perform_base_backup(basebackup_options *opt, bbsink *sink)
if (tmp->path == NULL) if (tmp->path == NULL)
tmp->size = sendDir(sink, ".", 1, true, state.tablespaces, tmp->size = sendDir(sink, ".", 1, true, state.tablespaces,
true, NULL, InvalidOid); true, NULL, NULL);
else else
tmp->size = sendTablespace(sink, tmp->path, tmp->oid, true, tmp->size = sendTablespace(sink, tmp->path, tmp->oid, true,
NULL); NULL);
@ -347,7 +346,7 @@ perform_base_backup(basebackup_options *opt, bbsink *sink)
/* Then the bulk of the files... */ /* Then the bulk of the files... */
sendDir(sink, ".", 1, false, state.tablespaces, sendDir(sink, ".", 1, false, state.tablespaces,
sendtblspclinks, &manifest, InvalidOid); sendtblspclinks, &manifest, NULL);
/* ... and pg_control after everything else. */ /* ... and pg_control after everything else. */
if (lstat(XLOG_CONTROL_FILE, &statbuf) != 0) if (lstat(XLOG_CONTROL_FILE, &statbuf) != 0)
@ -356,11 +355,11 @@ perform_base_backup(basebackup_options *opt, bbsink *sink)
errmsg("could not stat file \"%s\": %m", errmsg("could not stat file \"%s\": %m",
XLOG_CONTROL_FILE))); XLOG_CONTROL_FILE)));
sendFile(sink, XLOG_CONTROL_FILE, XLOG_CONTROL_FILE, &statbuf, sendFile(sink, XLOG_CONTROL_FILE, XLOG_CONTROL_FILE, &statbuf,
false, InvalidOid, InvalidOid, &manifest); false, InvalidOid, &manifest, NULL);
} }
else else
{ {
char *archive_name = psprintf("%u.tar", ti->oid); char *archive_name = psprintf("%s.tar", ti->oid);
bbsink_begin_archive(sink, archive_name); bbsink_begin_archive(sink, archive_name);
@ -624,8 +623,8 @@ perform_base_backup(basebackup_options *opt, bbsink *sink)
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not stat file \"%s\": %m", pathbuf))); errmsg("could not stat file \"%s\": %m", pathbuf)));
sendFile(sink, pathbuf, pathbuf, &statbuf, false, sendFile(sink, pathbuf, pathbuf, &statbuf, false, InvalidOid,
InvalidOid, InvalidOid, &manifest); &manifest, NULL);
/* unconditionally mark file as archived */ /* unconditionally mark file as archived */
StatusFilePath(pathbuf, fname, ".done"); StatusFilePath(pathbuf, fname, ".done");
@ -1088,7 +1087,7 @@ sendFileWithContent(bbsink *sink, const char *filename, const char *content,
_tarWritePadding(sink, len); _tarWritePadding(sink, len);
AddFileToBackupManifest(manifest, InvalidOid, filename, len, AddFileToBackupManifest(manifest, NULL, filename, len,
(pg_time_t) statbuf.st_mtime, &checksum_ctx); (pg_time_t) statbuf.st_mtime, &checksum_ctx);
} }
@ -1100,7 +1099,7 @@ sendFileWithContent(bbsink *sink, const char *filename, const char *content,
* Only used to send auxiliary tablespaces, not PGDATA. * Only used to send auxiliary tablespaces, not PGDATA.
*/ */
static int64 static int64
sendTablespace(bbsink *sink, char *path, Oid spcoid, bool sizeonly, sendTablespace(bbsink *sink, char *path, char *spcoid, bool sizeonly,
backup_manifest_info *manifest) backup_manifest_info *manifest)
{ {
int64 size; int64 size;
@ -1155,7 +1154,7 @@ sendTablespace(bbsink *sink, char *path, Oid spcoid, bool sizeonly,
static int64 static int64
sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly, sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
List *tablespaces, bool sendtblspclinks, backup_manifest_info *manifest, List *tablespaces, bool sendtblspclinks, backup_manifest_info *manifest,
Oid spcoid) const char *spcoid)
{ {
DIR *dir; DIR *dir;
struct dirent *de; struct dirent *de;
@ -1198,9 +1197,9 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
{ {
int excludeIdx; int excludeIdx;
bool excludeFound; bool excludeFound;
RelFileNumber relNumber; ForkNumber relForkNum; /* Type of fork if file is a relation */
ForkNumber relForkNum; int relnumchars; /* Chars in filename that are the
unsigned segno; * relnumber */
/* Skip special stuff */ /* Skip special stuff */
if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
@ -1250,20 +1249,23 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
/* Exclude all forks for unlogged tables except the init fork */ /* Exclude all forks for unlogged tables except the init fork */
if (isDbDir && if (isDbDir &&
parse_filename_for_nontemp_relation(de->d_name, &relNumber, parse_filename_for_nontemp_relation(de->d_name, &relnumchars,
&relForkNum, &segno)) &relForkNum))
{ {
/* Never exclude init forks */ /* Never exclude init forks */
if (relForkNum != INIT_FORKNUM) if (relForkNum != INIT_FORKNUM)
{ {
char initForkFile[MAXPGPATH]; char initForkFile[MAXPGPATH];
char relNumber[OIDCHARS + 1];
/* /*
* If any other type of fork, check if there is an init fork * If any other type of fork, check if there is an init fork
* with the same RelFileNumber. If so, the file can be * with the same RelFileNumber. If so, the file can be
* excluded. * excluded.
*/ */
snprintf(initForkFile, sizeof(initForkFile), "%s/%u_init", memcpy(relNumber, de->d_name, relnumchars);
relNumber[relnumchars] = '\0';
snprintf(initForkFile, sizeof(initForkFile), "%s/%s_init",
path, relNumber); path, relNumber);
if (lstat(initForkFile, &statbuf) == 0) if (lstat(initForkFile, &statbuf) == 0)
@ -1417,8 +1419,8 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
if (!sizeonly) if (!sizeonly)
sent = sendFile(sink, pathbuf, pathbuf + basepathlen + 1, &statbuf, sent = sendFile(sink, pathbuf, pathbuf + basepathlen + 1, &statbuf,
true, isDbDir ? atooid(lastDir + 1) : InvalidOid, spcoid, true, isDbDir ? atooid(lastDir + 1) : InvalidOid,
manifest); manifest, spcoid);
if (sent || sizeonly) if (sent || sizeonly)
{ {
@ -1487,8 +1489,8 @@ is_checksummed_file(const char *fullpath, const char *filename)
*/ */
static bool static bool
sendFile(bbsink *sink, const char *readfilename, const char *tarfilename, sendFile(bbsink *sink, const char *readfilename, const char *tarfilename,
struct stat *statbuf, bool missing_ok, Oid dboid, Oid spcoid, struct stat *statbuf, bool missing_ok, Oid dboid,
backup_manifest_info *manifest) backup_manifest_info *manifest, const char *spcoid)
{ {
int fd; int fd;
BlockNumber blkno = 0; BlockNumber blkno = 0;

View File

@ -407,7 +407,7 @@ SendTablespaceList(List *tablespaces)
} }
else else
{ {
values[0] = ObjectIdGetDatum(ti->oid); values[0] = ObjectIdGetDatum(strtoul(ti->oid, NULL, 10));
values[1] = CStringGetTextDatum(ti->path); values[1] = CStringGetTextDatum(ti->path);
} }
if (ti->size >= 0) if (ti->size >= 0)

View File

@ -2098,65 +2098,6 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
return first_block; return first_block;
} }
/*
* BufferIsExclusiveLocked
*
* Checks if buffer is exclusive-locked.
*
* Buffer must be pinned.
*/
bool
BufferIsExclusiveLocked(Buffer buffer)
{
BufferDesc *bufHdr;
if (BufferIsLocal(buffer))
{
int bufid = -buffer - 1;
bufHdr = GetLocalBufferDescriptor(bufid);
}
else
{
bufHdr = GetBufferDescriptor(buffer - 1);
}
Assert(BufferIsPinned(buffer));
return LWLockHeldByMeInMode(BufferDescriptorGetContentLock(bufHdr),
LW_EXCLUSIVE);
}
/*
* BufferIsDirty
*
* Checks if buffer is already dirty.
*
* Buffer must be pinned and exclusive-locked. (Without an exclusive lock,
* the result may be stale before it's returned.)
*/
bool
BufferIsDirty(Buffer buffer)
{
BufferDesc *bufHdr;
if (BufferIsLocal(buffer))
{
int bufid = -buffer - 1;
bufHdr = GetLocalBufferDescriptor(bufid);
}
else
{
bufHdr = GetBufferDescriptor(buffer - 1);
}
Assert(BufferIsPinned(buffer));
Assert(LWLockHeldByMeInMode(BufferDescriptorGetContentLock(bufHdr),
LW_EXCLUSIVE));
return pg_atomic_read_u32(&bufHdr->state) & BM_DIRTY;
}
/* /*
* MarkBufferDirty * MarkBufferDirty
* *

View File

@ -31,7 +31,7 @@ static void ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname,
typedef struct typedef struct
{ {
RelFileNumber relnumber; /* hash key */ Oid reloid; /* hash key */
} unlogged_relation_entry; } unlogged_relation_entry;
/* /*
@ -195,13 +195,12 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
while ((de = ReadDir(dbspace_dir, dbspacedirname)) != NULL) while ((de = ReadDir(dbspace_dir, dbspacedirname)) != NULL)
{ {
ForkNumber forkNum; ForkNumber forkNum;
unsigned segno; int relnumchars;
unlogged_relation_entry ent; unlogged_relation_entry ent;
/* Skip anything that doesn't look like a relation data file. */ /* Skip anything that doesn't look like a relation data file. */
if (!parse_filename_for_nontemp_relation(de->d_name, if (!parse_filename_for_nontemp_relation(de->d_name, &relnumchars,
&ent.relnumber, &forkNum))
&forkNum, &segno))
continue; continue;
/* Also skip it unless this is the init fork. */ /* Also skip it unless this is the init fork. */
@ -209,8 +208,10 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
continue; continue;
/* /*
* Put the RelFileNumber into the hash table, if it isn't already. * Put the OID portion of the name into the hash table, if it
* isn't already.
*/ */
ent.reloid = atooid(de->d_name);
(void) hash_search(hash, &ent, HASH_ENTER, NULL); (void) hash_search(hash, &ent, HASH_ENTER, NULL);
} }
@ -234,13 +235,12 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
while ((de = ReadDir(dbspace_dir, dbspacedirname)) != NULL) while ((de = ReadDir(dbspace_dir, dbspacedirname)) != NULL)
{ {
ForkNumber forkNum; ForkNumber forkNum;
unsigned segno; int relnumchars;
unlogged_relation_entry ent; unlogged_relation_entry ent;
/* Skip anything that doesn't look like a relation data file. */ /* Skip anything that doesn't look like a relation data file. */
if (!parse_filename_for_nontemp_relation(de->d_name, if (!parse_filename_for_nontemp_relation(de->d_name, &relnumchars,
&ent.relnumber, &forkNum))
&forkNum, &segno))
continue; continue;
/* We never remove the init fork. */ /* We never remove the init fork. */
@ -251,6 +251,7 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
* See whether the OID portion of the name shows up in the hash * See whether the OID portion of the name shows up in the hash
* table. If so, nuke it! * table. If so, nuke it!
*/ */
ent.reloid = atooid(de->d_name);
if (hash_search(hash, &ent, HASH_FIND, NULL)) if (hash_search(hash, &ent, HASH_FIND, NULL))
{ {
snprintf(rm_path, sizeof(rm_path), "%s/%s", snprintf(rm_path, sizeof(rm_path), "%s/%s",
@ -284,14 +285,14 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
while ((de = ReadDir(dbspace_dir, dbspacedirname)) != NULL) while ((de = ReadDir(dbspace_dir, dbspacedirname)) != NULL)
{ {
ForkNumber forkNum; ForkNumber forkNum;
RelFileNumber relNumber; int relnumchars;
unsigned segno; char relnumbuf[OIDCHARS + 1];
char srcpath[MAXPGPATH * 2]; char srcpath[MAXPGPATH * 2];
char dstpath[MAXPGPATH]; char dstpath[MAXPGPATH];
/* Skip anything that doesn't look like a relation data file. */ /* Skip anything that doesn't look like a relation data file. */
if (!parse_filename_for_nontemp_relation(de->d_name, &relNumber, if (!parse_filename_for_nontemp_relation(de->d_name, &relnumchars,
&forkNum, &segno)) &forkNum))
continue; continue;
/* Also skip it unless this is the init fork. */ /* Also skip it unless this is the init fork. */
@ -303,12 +304,11 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
dbspacedirname, de->d_name); dbspacedirname, de->d_name);
/* Construct destination pathname. */ /* Construct destination pathname. */
if (segno == 0) memcpy(relnumbuf, de->d_name, relnumchars);
snprintf(dstpath, sizeof(dstpath), "%s/%u", relnumbuf[relnumchars] = '\0';
dbspacedirname, relNumber); snprintf(dstpath, sizeof(dstpath), "%s/%s%s",
else dbspacedirname, relnumbuf, de->d_name + relnumchars + 1 +
snprintf(dstpath, sizeof(dstpath), "%s/%u.%u", strlen(forkNames[INIT_FORKNUM]));
dbspacedirname, relNumber, segno);
/* OK, we're ready to perform the actual copy. */ /* OK, we're ready to perform the actual copy. */
elog(DEBUG2, "copying %s to %s", srcpath, dstpath); elog(DEBUG2, "copying %s to %s", srcpath, dstpath);
@ -327,14 +327,14 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
dbspace_dir = AllocateDir(dbspacedirname); dbspace_dir = AllocateDir(dbspacedirname);
while ((de = ReadDir(dbspace_dir, dbspacedirname)) != NULL) while ((de = ReadDir(dbspace_dir, dbspacedirname)) != NULL)
{ {
RelFileNumber relNumber;
ForkNumber forkNum; ForkNumber forkNum;
unsigned segno; int relnumchars;
char relnumbuf[OIDCHARS + 1];
char mainpath[MAXPGPATH]; char mainpath[MAXPGPATH];
/* Skip anything that doesn't look like a relation data file. */ /* Skip anything that doesn't look like a relation data file. */
if (!parse_filename_for_nontemp_relation(de->d_name, &relNumber, if (!parse_filename_for_nontemp_relation(de->d_name, &relnumchars,
&forkNum, &segno)) &forkNum))
continue; continue;
/* Also skip it unless this is the init fork. */ /* Also skip it unless this is the init fork. */
@ -342,12 +342,11 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
continue; continue;
/* Construct main fork pathname. */ /* Construct main fork pathname. */
if (segno == 0) memcpy(relnumbuf, de->d_name, relnumchars);
snprintf(mainpath, sizeof(mainpath), "%s/%u", relnumbuf[relnumchars] = '\0';
dbspacedirname, relNumber); snprintf(mainpath, sizeof(mainpath), "%s/%s%s",
else dbspacedirname, relnumbuf, de->d_name + relnumchars + 1 +
snprintf(mainpath, sizeof(mainpath), "%s/%u.%u", strlen(forkNames[INIT_FORKNUM]));
dbspacedirname, relNumber, segno);
fsync_fname(mainpath, false); fsync_fname(mainpath, false);
} }
@ -372,82 +371,52 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
* This function returns true if the file appears to be in the correct format * This function returns true if the file appears to be in the correct format
* for a non-temporary relation and false otherwise. * for a non-temporary relation and false otherwise.
* *
* If it returns true, it sets *relnumber, *fork, and *segno to the values * NB: If this function returns true, the caller is entitled to assume that
* extracted from the filename. If it returns false, these values are set to * *relnumchars has been set to a value no more than OIDCHARS, and thus
* InvalidRelFileNumber, InvalidForkNumber, and 0, respectively. * that a buffer of OIDCHARS+1 characters is sufficient to hold the
* RelFileNumber portion of the filename. This is critical to protect against
* a possible buffer overrun.
*/ */
bool bool
parse_filename_for_nontemp_relation(const char *name, RelFileNumber *relnumber, parse_filename_for_nontemp_relation(const char *name, int *relnumchars,
ForkNumber *fork, unsigned *segno) ForkNumber *fork)
{ {
unsigned long n, int pos;
s;
ForkNumber f;
char *endp;
*relnumber = InvalidRelFileNumber; /* Look for a non-empty string of digits (that isn't too long). */
*fork = InvalidForkNumber; for (pos = 0; isdigit((unsigned char) name[pos]); ++pos)
*segno = 0; ;
if (pos == 0 || pos > OIDCHARS)
/*
* Relation filenames should begin with a digit that is not a zero. By
* rejecting cases involving leading zeroes, the caller can assume that
* there's only one possible string of characters that could have produced
* any given value for *relnumber.
*
* (To be clear, we don't expect files with names like 0017.3 to exist at
* all -- but if 0017.3 does exist, it's a non-relation file, not part of
* the main fork for relfilenode 17.)
*/
if (name[0] < '1' || name[0] > '9')
return false; return false;
*relnumchars = pos;
/*
* Parse the leading digit string. If the value is out of range, we
* conclude that this isn't a relation file at all.
*/
errno = 0;
n = strtoul(name, &endp, 10);
if (errno || name == endp || n <= 0 || n > PG_UINT32_MAX)
return false;
name = endp;
/* Check for a fork name. */ /* Check for a fork name. */
if (*name != '_') if (name[pos] != '_')
f = MAIN_FORKNUM; *fork = MAIN_FORKNUM;
else else
{ {
int forkchar; int forkchar;
forkchar = forkname_chars(name + 1, &f); forkchar = forkname_chars(&name[pos + 1], fork);
if (forkchar <= 0) if (forkchar <= 0)
return false; return false;
name += forkchar + 1; pos += forkchar + 1;
} }
/* Check for a segment number. */ /* Check for a segment number. */
if (*name != '.') if (name[pos] == '.')
s = 0;
else
{ {
/* Reject leading zeroes, just like we do for RelFileNumber. */ int segchar;
if (name[0] < '1' || name[0] > '9')
return false;
errno = 0; for (segchar = 1; isdigit((unsigned char) name[pos + segchar]); ++segchar)
s = strtoul(name + 1, &endp, 10); ;
if (errno || name + 1 == endp || s <= 0 || s > PG_UINT32_MAX) if (segchar <= 1)
return false; return false;
name = endp; pos += segchar;
} }
/* Now we should be at the end. */ /* Now we should be at the end. */
if (*name != '\0') if (name[pos] != '\0')
return false; return false;
/* Set out parameters and return. */
*relnumber = (RelFileNumber) n;
*fork = f;
*segno = (unsigned) s;
return true; return true;
} }

View File

@ -56,9 +56,9 @@ uint32 *my_wait_event_info = &local_my_wait_event_info;
* It is used to ensure that no duplicated entries are registered. * It is used to ensure that no duplicated entries are registered.
* *
* The size of the hash table is based on the assumption that * The size of the hash table is based on the assumption that
* WAIT_EVENT_EXTENSION_HASH_INIT_SIZE is enough for most cases, and it seems * WAIT_EVENT_EXTENSION_BASH_INIT_SIZE is enough for most cases, and it seems
* unlikely that the number of entries will reach * unlikely that the number of entries will reach
* WAIT_EVENT_EXTENSION_HASH_MAX_SIZE. * WAIT_EVENT_EXTENSION_BASH_MAX_SIZE.
*/ */
static HTAB *WaitEventExtensionHashById; /* find names from IDs */ static HTAB *WaitEventExtensionHashById; /* find names from IDs */
static HTAB *WaitEventExtensionHashByName; /* find IDs from names */ static HTAB *WaitEventExtensionHashByName; /* find IDs from names */

View File

@ -37,7 +37,6 @@
* will be skipped) */ * will be skipped) */
#define REGBUF_KEEP_DATA 0x10 /* include data even if a full-page image #define REGBUF_KEEP_DATA 0x10 /* include data even if a full-page image
* is taken */ * is taken */
#define REGBUF_NO_CHANGE 0x20 /* intentionally register clean buffer */
/* prototypes for public functions in xloginsert.c: */ /* prototypes for public functions in xloginsert.c: */
extern void XLogBeginInsert(void); extern void XLogBeginInsert(void);

View File

@ -39,7 +39,7 @@ extern void InitializeBackupManifest(backup_manifest_info *manifest,
backup_manifest_option want_manifest, backup_manifest_option want_manifest,
pg_checksum_type manifest_checksum_type); pg_checksum_type manifest_checksum_type);
extern void AddFileToBackupManifest(backup_manifest_info *manifest, extern void AddFileToBackupManifest(backup_manifest_info *manifest,
Oid spcoid, const char *spcoid,
const char *pathname, size_t size, const char *pathname, size_t size,
pg_time_t mtime, pg_time_t mtime,
pg_checksum_context *checksum_ctx); pg_checksum_context *checksum_ctx);

View File

@ -27,7 +27,7 @@
*/ */
typedef struct typedef struct
{ {
Oid oid; /* tablespace's OID */ char *oid; /* tablespace's OID, as a decimal string */
char *path; /* full path to tablespace's directory */ char *path; /* full path to tablespace's directory */
char *rpath; /* relative path if it's within PGDATA, else char *rpath; /* relative path if it's within PGDATA, else
* NULL */ * NULL */

View File

@ -179,8 +179,6 @@ extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,
bool permanent); bool permanent);
extern void ReleaseBuffer(Buffer buffer); extern void ReleaseBuffer(Buffer buffer);
extern void UnlockReleaseBuffer(Buffer buffer); extern void UnlockReleaseBuffer(Buffer buffer);
extern bool BufferIsExclusiveLocked(Buffer buffer);
extern bool BufferIsDirty(Buffer buffer);
extern void MarkBufferDirty(Buffer buffer); extern void MarkBufferDirty(Buffer buffer);
extern void IncrBufferRefCount(Buffer buffer); extern void IncrBufferRefCount(Buffer buffer);
extern void CheckBufferIsPinnedOnce(Buffer buffer); extern void CheckBufferIsPinnedOnce(Buffer buffer);

View File

@ -20,9 +20,8 @@
extern void ResetUnloggedRelations(int op); extern void ResetUnloggedRelations(int op);
extern bool parse_filename_for_nontemp_relation(const char *name, extern bool parse_filename_for_nontemp_relation(const char *name,
RelFileNumber *relnumber, int *relnumchars,
ForkNumber *fork, ForkNumber *fork);
unsigned *segno);
#define UNLOGGED_RELATION_CLEANUP 0x0001 #define UNLOGGED_RELATION_CLEANUP 0x0001
#define UNLOGGED_RELATION_INIT 0x0002 #define UNLOGGED_RELATION_INIT 0x0002