mirror of
https://github.com/postgres/postgres.git
synced 2025-06-07 00:02:00 -04:00
Change relpath() et al to return path by value
For AIO, and also some other recent patches, we need the ability to call relpath() in a critical section. Until now that was not feasible, as it allocated memory. The fact that relpath() allocated memory also made it awkward to use in log messages because we had to take care to free the memory afterwards. Which we e.g. didn't do for when zeroing out an invalid buffer. We discussed other solutions, e.g. filling a pre-allocated buffer that's passed to relpath(), but they all came with plenty downsides or were larger projects. The easiest fix seems to be to make relpath() return the path by value. To be able to return the path by value we need to determine the maximum length of a relation path. This patch adds a long #define that computes the exact maximum, which is verified to be correct in a regression test. As this change the signature of relpath(), extensions using it will need to adapt their code. We discussed leaving a backward-compat shim in place, but decided it's not worth it given the use of relpath() doesn't seem widespread. Discussion: https://postgr.es/m/xeri5mla4b5syjd5a25nok5iez2kr3bm26j2qn4u7okzof2bmf@kwdh2vf7npra
This commit is contained in:
parent
32c393f9f1
commit
37c87e63f9
@ -26,19 +26,17 @@ smgr_desc(StringInfo buf, XLogReaderState *record)
|
|||||||
if (info == XLOG_SMGR_CREATE)
|
if (info == XLOG_SMGR_CREATE)
|
||||||
{
|
{
|
||||||
xl_smgr_create *xlrec = (xl_smgr_create *) rec;
|
xl_smgr_create *xlrec = (xl_smgr_create *) rec;
|
||||||
char *path = relpathperm(xlrec->rlocator, xlrec->forkNum);
|
|
||||||
|
|
||||||
appendStringInfoString(buf, path);
|
appendStringInfoString(buf,
|
||||||
pfree(path);
|
relpathperm(xlrec->rlocator, xlrec->forkNum).str);
|
||||||
}
|
}
|
||||||
else if (info == XLOG_SMGR_TRUNCATE)
|
else if (info == XLOG_SMGR_TRUNCATE)
|
||||||
{
|
{
|
||||||
xl_smgr_truncate *xlrec = (xl_smgr_truncate *) rec;
|
xl_smgr_truncate *xlrec = (xl_smgr_truncate *) rec;
|
||||||
char *path = relpathperm(xlrec->rlocator, MAIN_FORKNUM);
|
|
||||||
|
|
||||||
appendStringInfo(buf, "%s to %u blocks flags %d", path,
|
appendStringInfo(buf, "%s to %u blocks flags %d",
|
||||||
|
relpathperm(xlrec->rlocator, MAIN_FORKNUM).str,
|
||||||
xlrec->blkno, xlrec->flags);
|
xlrec->blkno, xlrec->flags);
|
||||||
pfree(path);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,10 +287,8 @@ xact_desc_relations(StringInfo buf, char *label, int nrels,
|
|||||||
appendStringInfo(buf, "; %s:", label);
|
appendStringInfo(buf, "; %s:", label);
|
||||||
for (i = 0; i < nrels; i++)
|
for (i = 0; i < nrels; i++)
|
||||||
{
|
{
|
||||||
char *path = relpathperm(xlocators[i], MAIN_FORKNUM);
|
appendStringInfo(buf, " %s",
|
||||||
|
relpathperm(xlocators[i], MAIN_FORKNUM).str);
|
||||||
appendStringInfo(buf, " %s", path);
|
|
||||||
pfree(path);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,15 +86,14 @@ static void
|
|||||||
report_invalid_page(int elevel, RelFileLocator locator, ForkNumber forkno,
|
report_invalid_page(int elevel, RelFileLocator locator, ForkNumber forkno,
|
||||||
BlockNumber blkno, bool present)
|
BlockNumber blkno, bool present)
|
||||||
{
|
{
|
||||||
char *path = relpathperm(locator, forkno);
|
RelPathStr path = relpathperm(locator, forkno);
|
||||||
|
|
||||||
if (present)
|
if (present)
|
||||||
elog(elevel, "page %u of relation %s is uninitialized",
|
elog(elevel, "page %u of relation %s is uninitialized",
|
||||||
blkno, path);
|
blkno, path.str);
|
||||||
else
|
else
|
||||||
elog(elevel, "page %u of relation %s does not exist",
|
elog(elevel, "page %u of relation %s does not exist",
|
||||||
blkno, path);
|
blkno, path.str);
|
||||||
pfree(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Log a reference to an invalid page */
|
/* Log a reference to an invalid page */
|
||||||
@ -180,14 +179,9 @@ forget_invalid_pages(RelFileLocator locator, ForkNumber forkno,
|
|||||||
hentry->key.forkno == forkno &&
|
hentry->key.forkno == forkno &&
|
||||||
hentry->key.blkno >= minblkno)
|
hentry->key.blkno >= minblkno)
|
||||||
{
|
{
|
||||||
if (message_level_is_interesting(DEBUG2))
|
|
||||||
{
|
|
||||||
char *path = relpathperm(hentry->key.locator, forkno);
|
|
||||||
|
|
||||||
elog(DEBUG2, "page %u of relation %s has been dropped",
|
elog(DEBUG2, "page %u of relation %s has been dropped",
|
||||||
hentry->key.blkno, path);
|
hentry->key.blkno,
|
||||||
pfree(path);
|
relpathperm(hentry->key.locator, forkno).str);
|
||||||
}
|
|
||||||
|
|
||||||
if (hash_search(invalid_page_tab,
|
if (hash_search(invalid_page_tab,
|
||||||
&hentry->key,
|
&hentry->key,
|
||||||
@ -213,14 +207,9 @@ forget_invalid_pages_db(Oid dbid)
|
|||||||
{
|
{
|
||||||
if (hentry->key.locator.dbOid == dbid)
|
if (hentry->key.locator.dbOid == dbid)
|
||||||
{
|
{
|
||||||
if (message_level_is_interesting(DEBUG2))
|
|
||||||
{
|
|
||||||
char *path = relpathperm(hentry->key.locator, hentry->key.forkno);
|
|
||||||
|
|
||||||
elog(DEBUG2, "page %u of relation %s has been dropped",
|
elog(DEBUG2, "page %u of relation %s has been dropped",
|
||||||
hentry->key.blkno, path);
|
hentry->key.blkno,
|
||||||
pfree(path);
|
relpathperm(hentry->key.locator, hentry->key.forkno).str);
|
||||||
}
|
|
||||||
|
|
||||||
if (hash_search(invalid_page_tab,
|
if (hash_search(invalid_page_tab,
|
||||||
&hentry->key,
|
&hentry->key,
|
||||||
|
@ -625,23 +625,21 @@ char *
|
|||||||
GetIncrementalFilePath(Oid dboid, Oid spcoid, RelFileNumber relfilenumber,
|
GetIncrementalFilePath(Oid dboid, Oid spcoid, RelFileNumber relfilenumber,
|
||||||
ForkNumber forknum, unsigned segno)
|
ForkNumber forknum, unsigned segno)
|
||||||
{
|
{
|
||||||
char *path;
|
RelPathStr path;
|
||||||
char *lastslash;
|
char *lastslash;
|
||||||
char *ipath;
|
char *ipath;
|
||||||
|
|
||||||
path = GetRelationPath(dboid, spcoid, relfilenumber, INVALID_PROC_NUMBER,
|
path = GetRelationPath(dboid, spcoid, relfilenumber, INVALID_PROC_NUMBER,
|
||||||
forknum);
|
forknum);
|
||||||
|
|
||||||
lastslash = strrchr(path, '/');
|
lastslash = strrchr(path.str, '/');
|
||||||
Assert(lastslash != NULL);
|
Assert(lastslash != NULL);
|
||||||
*lastslash = '\0';
|
*lastslash = '\0';
|
||||||
|
|
||||||
if (segno > 0)
|
if (segno > 0)
|
||||||
ipath = psprintf("%s/INCREMENTAL.%s.%u", path, lastslash + 1, segno);
|
ipath = psprintf("%s/INCREMENTAL.%s.%u", path.str, lastslash + 1, segno);
|
||||||
else
|
else
|
||||||
ipath = psprintf("%s/INCREMENTAL.%s", path, lastslash + 1);
|
ipath = psprintf("%s/INCREMENTAL.%s", path.str, lastslash + 1);
|
||||||
|
|
||||||
pfree(path);
|
|
||||||
|
|
||||||
return ipath;
|
return ipath;
|
||||||
}
|
}
|
||||||
|
@ -528,7 +528,7 @@ RelFileNumber
|
|||||||
GetNewRelFileNumber(Oid reltablespace, Relation pg_class, char relpersistence)
|
GetNewRelFileNumber(Oid reltablespace, Relation pg_class, char relpersistence)
|
||||||
{
|
{
|
||||||
RelFileLocatorBackend rlocator;
|
RelFileLocatorBackend rlocator;
|
||||||
char *rpath;
|
RelPathStr rpath;
|
||||||
bool collides;
|
bool collides;
|
||||||
ProcNumber procNumber;
|
ProcNumber procNumber;
|
||||||
|
|
||||||
@ -580,7 +580,7 @@ GetNewRelFileNumber(Oid reltablespace, Relation pg_class, char relpersistence)
|
|||||||
/* Check for existing file of same name */
|
/* Check for existing file of same name */
|
||||||
rpath = relpath(rlocator, MAIN_FORKNUM);
|
rpath = relpath(rlocator, MAIN_FORKNUM);
|
||||||
|
|
||||||
if (access(rpath, F_OK) == 0)
|
if (access(rpath.str, F_OK) == 0)
|
||||||
{
|
{
|
||||||
/* definite collision */
|
/* definite collision */
|
||||||
collides = true;
|
collides = true;
|
||||||
@ -596,8 +596,6 @@ GetNewRelFileNumber(Oid reltablespace, Relation pg_class, char relpersistence)
|
|||||||
*/
|
*/
|
||||||
collides = false;
|
collides = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pfree(rpath);
|
|
||||||
} while (collides);
|
} while (collides);
|
||||||
|
|
||||||
return rlocator.locator.relNumber;
|
return rlocator.locator.relNumber;
|
||||||
|
@ -524,14 +524,14 @@ RelationCopyStorage(SMgrRelation src, SMgrRelation dst,
|
|||||||
* (errcontext callbacks shouldn't be risking any such thing, but
|
* (errcontext callbacks shouldn't be risking any such thing, but
|
||||||
* people have been known to forget that rule.)
|
* people have been known to forget that rule.)
|
||||||
*/
|
*/
|
||||||
char *relpath = relpathbackend(src->smgr_rlocator.locator,
|
RelPathStr relpath = relpathbackend(src->smgr_rlocator.locator,
|
||||||
src->smgr_rlocator.backend,
|
src->smgr_rlocator.backend,
|
||||||
forkNum);
|
forkNum);
|
||||||
|
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_DATA_CORRUPTED),
|
(errcode(ERRCODE_DATA_CORRUPTED),
|
||||||
errmsg("invalid page in block %u of relation %s",
|
errmsg("invalid page in block %u of relation %s",
|
||||||
blkno, relpath)));
|
blkno, relpath.str)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2329,7 +2329,7 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn,
|
|||||||
else if (reloid == InvalidOid)
|
else if (reloid == InvalidOid)
|
||||||
elog(ERROR, "could not map filenumber \"%s\" to relation OID",
|
elog(ERROR, "could not map filenumber \"%s\" to relation OID",
|
||||||
relpathperm(change->data.tp.rlocator,
|
relpathperm(change->data.tp.rlocator,
|
||||||
MAIN_FORKNUM));
|
MAIN_FORKNUM).str);
|
||||||
|
|
||||||
relation = RelationIdGetRelation(reloid);
|
relation = RelationIdGetRelation(reloid);
|
||||||
|
|
||||||
@ -2337,7 +2337,7 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn,
|
|||||||
elog(ERROR, "could not open relation with OID %u (for filenumber \"%s\")",
|
elog(ERROR, "could not open relation with OID %u (for filenumber \"%s\")",
|
||||||
reloid,
|
reloid,
|
||||||
relpathperm(change->data.tp.rlocator,
|
relpathperm(change->data.tp.rlocator,
|
||||||
MAIN_FORKNUM));
|
MAIN_FORKNUM).str);
|
||||||
|
|
||||||
if (!RelationIsLogicallyLogged(relation))
|
if (!RelationIsLogicallyLogged(relation))
|
||||||
goto change_done;
|
goto change_done;
|
||||||
|
@ -1541,7 +1541,7 @@ WaitReadBuffers(ReadBuffersOperation *operation)
|
|||||||
(errcode(ERRCODE_DATA_CORRUPTED),
|
(errcode(ERRCODE_DATA_CORRUPTED),
|
||||||
errmsg("invalid page in block %u of relation %s; zeroing out page",
|
errmsg("invalid page in block %u of relation %s; zeroing out page",
|
||||||
io_first_block + j,
|
io_first_block + j,
|
||||||
relpath(operation->smgr->smgr_rlocator, forknum))));
|
relpath(operation->smgr->smgr_rlocator, forknum).str)));
|
||||||
memset(bufBlock, 0, BLCKSZ);
|
memset(bufBlock, 0, BLCKSZ);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1549,7 +1549,7 @@ WaitReadBuffers(ReadBuffersOperation *operation)
|
|||||||
(errcode(ERRCODE_DATA_CORRUPTED),
|
(errcode(ERRCODE_DATA_CORRUPTED),
|
||||||
errmsg("invalid page in block %u of relation %s",
|
errmsg("invalid page in block %u of relation %s",
|
||||||
io_first_block + j,
|
io_first_block + j,
|
||||||
relpath(operation->smgr->smgr_rlocator, forknum))));
|
relpath(operation->smgr->smgr_rlocator, forknum).str)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Terminate I/O and set BM_VALID. */
|
/* Terminate I/O and set BM_VALID. */
|
||||||
@ -2284,7 +2284,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
|
|||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||||
errmsg("cannot extend relation %s beyond %u blocks",
|
errmsg("cannot extend relation %s beyond %u blocks",
|
||||||
relpath(bmr.smgr->smgr_rlocator, fork),
|
relpath(bmr.smgr->smgr_rlocator, fork).str,
|
||||||
MaxBlockNumber)));
|
MaxBlockNumber)));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2355,7 +2355,8 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
|
|||||||
if (valid && !PageIsNew((Page) buf_block))
|
if (valid && !PageIsNew((Page) buf_block))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errmsg("unexpected data beyond EOF in block %u of relation %s",
|
(errmsg("unexpected data beyond EOF in block %u of relation %s",
|
||||||
existing_hdr->tag.blockNum, relpath(bmr.smgr->smgr_rlocator, fork)),
|
existing_hdr->tag.blockNum,
|
||||||
|
relpath(bmr.smgr->smgr_rlocator, fork).str),
|
||||||
errhint("This has been seen to occur with buggy kernels; consider updating your system.")));
|
errhint("This has been seen to occur with buggy kernels; consider updating your system.")));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3663,7 +3664,6 @@ DebugPrintBufferRefcount(Buffer buffer)
|
|||||||
{
|
{
|
||||||
BufferDesc *buf;
|
BufferDesc *buf;
|
||||||
int32 loccount;
|
int32 loccount;
|
||||||
char *path;
|
|
||||||
char *result;
|
char *result;
|
||||||
ProcNumber backend;
|
ProcNumber backend;
|
||||||
uint32 buf_state;
|
uint32 buf_state;
|
||||||
@ -3683,15 +3683,14 @@ DebugPrintBufferRefcount(Buffer buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* theoretically we should lock the bufhdr here */
|
/* theoretically we should lock the bufhdr here */
|
||||||
path = relpathbackend(BufTagGetRelFileLocator(&buf->tag), backend,
|
|
||||||
BufTagGetForkNum(&buf->tag));
|
|
||||||
buf_state = pg_atomic_read_u32(&buf->state);
|
buf_state = pg_atomic_read_u32(&buf->state);
|
||||||
|
|
||||||
result = psprintf("[%03d] (rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)",
|
result = psprintf("[%03d] (rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)",
|
||||||
buffer, path,
|
buffer,
|
||||||
|
relpathbackend(BufTagGetRelFileLocator(&buf->tag), backend,
|
||||||
|
BufTagGetForkNum(&buf->tag)).str,
|
||||||
buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
|
buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
|
||||||
BUF_STATE_GET_REFCOUNT(buf_state), loccount);
|
BUF_STATE_GET_REFCOUNT(buf_state), loccount);
|
||||||
pfree(path);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5611,16 +5610,13 @@ AbortBufferIO(Buffer buffer)
|
|||||||
if (buf_state & BM_IO_ERROR)
|
if (buf_state & BM_IO_ERROR)
|
||||||
{
|
{
|
||||||
/* Buffer is pinned, so we can read tag without spinlock */
|
/* Buffer is pinned, so we can read tag without spinlock */
|
||||||
char *path;
|
|
||||||
|
|
||||||
path = relpathperm(BufTagGetRelFileLocator(&buf_hdr->tag),
|
|
||||||
BufTagGetForkNum(&buf_hdr->tag));
|
|
||||||
ereport(WARNING,
|
ereport(WARNING,
|
||||||
(errcode(ERRCODE_IO_ERROR),
|
(errcode(ERRCODE_IO_ERROR),
|
||||||
errmsg("could not write block %u of %s",
|
errmsg("could not write block %u of %s",
|
||||||
buf_hdr->tag.blockNum, path),
|
buf_hdr->tag.blockNum,
|
||||||
|
relpathperm(BufTagGetRelFileLocator(&buf_hdr->tag),
|
||||||
|
BufTagGetForkNum(&buf_hdr->tag)).str),
|
||||||
errdetail("Multiple failures --- write error might be permanent.")));
|
errdetail("Multiple failures --- write error might be permanent.")));
|
||||||
pfree(path);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5637,14 +5633,10 @@ shared_buffer_write_error_callback(void *arg)
|
|||||||
|
|
||||||
/* Buffer is pinned, so we can read the tag without locking the spinlock */
|
/* Buffer is pinned, so we can read the tag without locking the spinlock */
|
||||||
if (bufHdr != NULL)
|
if (bufHdr != NULL)
|
||||||
{
|
|
||||||
char *path = relpathperm(BufTagGetRelFileLocator(&bufHdr->tag),
|
|
||||||
BufTagGetForkNum(&bufHdr->tag));
|
|
||||||
|
|
||||||
errcontext("writing block %u of relation %s",
|
errcontext("writing block %u of relation %s",
|
||||||
bufHdr->tag.blockNum, path);
|
bufHdr->tag.blockNum,
|
||||||
pfree(path);
|
relpathperm(BufTagGetRelFileLocator(&bufHdr->tag),
|
||||||
}
|
BufTagGetForkNum(&bufHdr->tag)).str);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5656,15 +5648,11 @@ local_buffer_write_error_callback(void *arg)
|
|||||||
BufferDesc *bufHdr = (BufferDesc *) arg;
|
BufferDesc *bufHdr = (BufferDesc *) arg;
|
||||||
|
|
||||||
if (bufHdr != NULL)
|
if (bufHdr != NULL)
|
||||||
{
|
|
||||||
char *path = relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
|
|
||||||
MyProcNumber,
|
|
||||||
BufTagGetForkNum(&bufHdr->tag));
|
|
||||||
|
|
||||||
errcontext("writing block %u of relation %s",
|
errcontext("writing block %u of relation %s",
|
||||||
bufHdr->tag.blockNum, path);
|
bufHdr->tag.blockNum,
|
||||||
pfree(path);
|
relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
|
||||||
}
|
MyProcNumber,
|
||||||
|
BufTagGetForkNum(&bufHdr->tag)).str);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -360,7 +360,7 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr,
|
|||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||||
errmsg("cannot extend relation %s beyond %u blocks",
|
errmsg("cannot extend relation %s beyond %u blocks",
|
||||||
relpath(bmr.smgr->smgr_rlocator, fork),
|
relpath(bmr.smgr->smgr_rlocator, fork).str,
|
||||||
MaxBlockNumber)));
|
MaxBlockNumber)));
|
||||||
|
|
||||||
for (uint32 i = 0; i < extend_by; i++)
|
for (uint32 i = 0; i < extend_by; i++)
|
||||||
@ -510,7 +510,7 @@ DropRelationLocalBuffers(RelFileLocator rlocator, ForkNumber forkNum,
|
|||||||
bufHdr->tag.blockNum,
|
bufHdr->tag.blockNum,
|
||||||
relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
|
relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
|
||||||
MyProcNumber,
|
MyProcNumber,
|
||||||
BufTagGetForkNum(&bufHdr->tag)),
|
BufTagGetForkNum(&bufHdr->tag)).str,
|
||||||
LocalRefCount[i]);
|
LocalRefCount[i]);
|
||||||
|
|
||||||
/* Remove entry from hashtable */
|
/* Remove entry from hashtable */
|
||||||
@ -555,7 +555,7 @@ DropRelationAllLocalBuffers(RelFileLocator rlocator)
|
|||||||
bufHdr->tag.blockNum,
|
bufHdr->tag.blockNum,
|
||||||
relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
|
relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
|
||||||
MyProcNumber,
|
MyProcNumber,
|
||||||
BufTagGetForkNum(&bufHdr->tag)),
|
BufTagGetForkNum(&bufHdr->tag)).str,
|
||||||
LocalRefCount[i]);
|
LocalRefCount[i]);
|
||||||
/* Remove entry from hashtable */
|
/* Remove entry from hashtable */
|
||||||
hresult = (LocalBufferLookupEnt *)
|
hresult = (LocalBufferLookupEnt *)
|
||||||
|
@ -182,7 +182,7 @@ void
|
|||||||
mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
|
mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
|
||||||
{
|
{
|
||||||
MdfdVec *mdfd;
|
MdfdVec *mdfd;
|
||||||
char *path;
|
RelPathStr path;
|
||||||
File fd;
|
File fd;
|
||||||
|
|
||||||
if (isRedo && reln->md_num_open_segs[forknum] > 0)
|
if (isRedo && reln->md_num_open_segs[forknum] > 0)
|
||||||
@ -205,26 +205,24 @@ mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
|
|||||||
|
|
||||||
path = relpath(reln->smgr_rlocator, forknum);
|
path = relpath(reln->smgr_rlocator, forknum);
|
||||||
|
|
||||||
fd = PathNameOpenFile(path, _mdfd_open_flags() | O_CREAT | O_EXCL);
|
fd = PathNameOpenFile(path.str, _mdfd_open_flags() | O_CREAT | O_EXCL);
|
||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
int save_errno = errno;
|
int save_errno = errno;
|
||||||
|
|
||||||
if (isRedo)
|
if (isRedo)
|
||||||
fd = PathNameOpenFile(path, _mdfd_open_flags());
|
fd = PathNameOpenFile(path.str, _mdfd_open_flags());
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
/* be sure to report the error reported by create, not open */
|
/* be sure to report the error reported by create, not open */
|
||||||
errno = save_errno;
|
errno = save_errno;
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode_for_file_access(),
|
(errcode_for_file_access(),
|
||||||
errmsg("could not create file \"%s\": %m", path)));
|
errmsg("could not create file \"%s\": %m", path.str)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pfree(path);
|
|
||||||
|
|
||||||
_fdvec_resize(reln, forknum, 1);
|
_fdvec_resize(reln, forknum, 1);
|
||||||
mdfd = &reln->md_seg_fds[forknum][0];
|
mdfd = &reln->md_seg_fds[forknum][0];
|
||||||
mdfd->mdfd_vfd = fd;
|
mdfd->mdfd_vfd = fd;
|
||||||
@ -335,7 +333,7 @@ do_truncate(const char *path)
|
|||||||
static void
|
static void
|
||||||
mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
|
mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
|
||||||
{
|
{
|
||||||
char *path;
|
RelPathStr path;
|
||||||
int ret;
|
int ret;
|
||||||
int save_errno;
|
int save_errno;
|
||||||
|
|
||||||
@ -351,7 +349,7 @@ mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
|
|||||||
if (!RelFileLocatorBackendIsTemp(rlocator))
|
if (!RelFileLocatorBackendIsTemp(rlocator))
|
||||||
{
|
{
|
||||||
/* Prevent other backends' fds from holding on to the disk space */
|
/* Prevent other backends' fds from holding on to the disk space */
|
||||||
ret = do_truncate(path);
|
ret = do_truncate(path.str);
|
||||||
|
|
||||||
/* Forget any pending sync requests for the first segment */
|
/* Forget any pending sync requests for the first segment */
|
||||||
save_errno = errno;
|
save_errno = errno;
|
||||||
@ -364,13 +362,13 @@ mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
|
|||||||
/* Next unlink the file, unless it was already found to be missing */
|
/* Next unlink the file, unless it was already found to be missing */
|
||||||
if (ret >= 0 || errno != ENOENT)
|
if (ret >= 0 || errno != ENOENT)
|
||||||
{
|
{
|
||||||
ret = unlink(path);
|
ret = unlink(path.str);
|
||||||
if (ret < 0 && errno != ENOENT)
|
if (ret < 0 && errno != ENOENT)
|
||||||
{
|
{
|
||||||
save_errno = errno;
|
save_errno = errno;
|
||||||
ereport(WARNING,
|
ereport(WARNING,
|
||||||
(errcode_for_file_access(),
|
(errcode_for_file_access(),
|
||||||
errmsg("could not remove file \"%s\": %m", path)));
|
errmsg("could not remove file \"%s\": %m", path.str)));
|
||||||
errno = save_errno;
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -378,7 +376,7 @@ mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Prevent other backends' fds from holding on to the disk space */
|
/* Prevent other backends' fds from holding on to the disk space */
|
||||||
ret = do_truncate(path);
|
ret = do_truncate(path.str);
|
||||||
|
|
||||||
/* Register request to unlink first segment later */
|
/* Register request to unlink first segment later */
|
||||||
save_errno = errno;
|
save_errno = errno;
|
||||||
@ -400,12 +398,12 @@ mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
|
|||||||
*/
|
*/
|
||||||
if (ret >= 0 || errno != ENOENT)
|
if (ret >= 0 || errno != ENOENT)
|
||||||
{
|
{
|
||||||
char *segpath = (char *) palloc(strlen(path) + 12);
|
char *segpath = (char *) palloc(strlen(path.str) + 12);
|
||||||
BlockNumber segno;
|
BlockNumber segno;
|
||||||
|
|
||||||
for (segno = 1;; segno++)
|
for (segno = 1;; segno++)
|
||||||
{
|
{
|
||||||
sprintf(segpath, "%s.%u", path, segno);
|
sprintf(segpath, "%s.%u", path.str, segno);
|
||||||
|
|
||||||
if (!RelFileLocatorBackendIsTemp(rlocator))
|
if (!RelFileLocatorBackendIsTemp(rlocator))
|
||||||
{
|
{
|
||||||
@ -435,8 +433,6 @@ mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
|
|||||||
}
|
}
|
||||||
pfree(segpath);
|
pfree(segpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
pfree(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -475,7 +471,7 @@ mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
|
|||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||||
errmsg("cannot extend file \"%s\" beyond %u blocks",
|
errmsg("cannot extend file \"%s\" beyond %u blocks",
|
||||||
relpath(reln->smgr_rlocator, forknum),
|
relpath(reln->smgr_rlocator, forknum).str,
|
||||||
InvalidBlockNumber)));
|
InvalidBlockNumber)));
|
||||||
|
|
||||||
v = _mdfd_getseg(reln, forknum, blocknum, skipFsync, EXTENSION_CREATE);
|
v = _mdfd_getseg(reln, forknum, blocknum, skipFsync, EXTENSION_CREATE);
|
||||||
@ -537,7 +533,7 @@ mdzeroextend(SMgrRelation reln, ForkNumber forknum,
|
|||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||||
errmsg("cannot extend file \"%s\" beyond %u blocks",
|
errmsg("cannot extend file \"%s\" beyond %u blocks",
|
||||||
relpath(reln->smgr_rlocator, forknum),
|
relpath(reln->smgr_rlocator, forknum).str,
|
||||||
InvalidBlockNumber)));
|
InvalidBlockNumber)));
|
||||||
|
|
||||||
while (remblocks > 0)
|
while (remblocks > 0)
|
||||||
@ -629,7 +625,7 @@ static MdfdVec *
|
|||||||
mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior)
|
mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior)
|
||||||
{
|
{
|
||||||
MdfdVec *mdfd;
|
MdfdVec *mdfd;
|
||||||
char *path;
|
RelPathStr path;
|
||||||
File fd;
|
File fd;
|
||||||
|
|
||||||
/* No work if already open */
|
/* No work if already open */
|
||||||
@ -638,23 +634,18 @@ mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior)
|
|||||||
|
|
||||||
path = relpath(reln->smgr_rlocator, forknum);
|
path = relpath(reln->smgr_rlocator, forknum);
|
||||||
|
|
||||||
fd = PathNameOpenFile(path, _mdfd_open_flags());
|
fd = PathNameOpenFile(path.str, _mdfd_open_flags());
|
||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
if ((behavior & EXTENSION_RETURN_NULL) &&
|
if ((behavior & EXTENSION_RETURN_NULL) &&
|
||||||
FILE_POSSIBLY_DELETED(errno))
|
FILE_POSSIBLY_DELETED(errno))
|
||||||
{
|
|
||||||
pfree(path);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode_for_file_access(),
|
(errcode_for_file_access(),
|
||||||
errmsg("could not open file \"%s\": %m", path)));
|
errmsg("could not open file \"%s\": %m", path.str)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pfree(path);
|
|
||||||
|
|
||||||
_fdvec_resize(reln, forknum, 1);
|
_fdvec_resize(reln, forknum, 1);
|
||||||
mdfd = &reln->md_seg_fds[forknum][0];
|
mdfd = &reln->md_seg_fds[forknum][0];
|
||||||
mdfd->mdfd_vfd = fd;
|
mdfd->mdfd_vfd = fd;
|
||||||
@ -1176,7 +1167,7 @@ mdtruncate(SMgrRelation reln, ForkNumber forknum,
|
|||||||
return;
|
return;
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errmsg("could not truncate file \"%s\" to %u blocks: it's only %u blocks now",
|
(errmsg("could not truncate file \"%s\" to %u blocks: it's only %u blocks now",
|
||||||
relpath(reln->smgr_rlocator, forknum),
|
relpath(reln->smgr_rlocator, forknum).str,
|
||||||
nblocks, curnblk)));
|
nblocks, curnblk)));
|
||||||
}
|
}
|
||||||
if (nblocks == curnblk)
|
if (nblocks == curnblk)
|
||||||
@ -1540,18 +1531,15 @@ _fdvec_resize(SMgrRelation reln,
|
|||||||
static char *
|
static char *
|
||||||
_mdfd_segpath(SMgrRelation reln, ForkNumber forknum, BlockNumber segno)
|
_mdfd_segpath(SMgrRelation reln, ForkNumber forknum, BlockNumber segno)
|
||||||
{
|
{
|
||||||
char *path,
|
RelPathStr path;
|
||||||
*fullpath;
|
char *fullpath;
|
||||||
|
|
||||||
path = relpath(reln->smgr_rlocator, forknum);
|
path = relpath(reln->smgr_rlocator, forknum);
|
||||||
|
|
||||||
if (segno > 0)
|
if (segno > 0)
|
||||||
{
|
fullpath = psprintf("%s.%u", path.str, segno);
|
||||||
fullpath = psprintf("%s.%u", path, segno);
|
|
||||||
pfree(path);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
fullpath = path;
|
fullpath = pstrdup(path.str);
|
||||||
|
|
||||||
return fullpath;
|
return fullpath;
|
||||||
}
|
}
|
||||||
@ -1811,12 +1799,11 @@ mdsyncfiletag(const FileTag *ftag, char *path)
|
|||||||
int
|
int
|
||||||
mdunlinkfiletag(const FileTag *ftag, char *path)
|
mdunlinkfiletag(const FileTag *ftag, char *path)
|
||||||
{
|
{
|
||||||
char *p;
|
RelPathStr p;
|
||||||
|
|
||||||
/* Compute the path. */
|
/* Compute the path. */
|
||||||
p = relpathperm(ftag->rlocator, MAIN_FORKNUM);
|
p = relpathperm(ftag->rlocator, MAIN_FORKNUM);
|
||||||
strlcpy(path, p, MAXPGPATH);
|
strlcpy(path, p.str, MAXPGPATH);
|
||||||
pfree(p);
|
|
||||||
|
|
||||||
/* Try to unlink the file. */
|
/* Try to unlink the file. */
|
||||||
return unlink(path);
|
return unlink(path);
|
||||||
|
@ -326,7 +326,7 @@ static int64
|
|||||||
calculate_relation_size(RelFileLocator *rfn, ProcNumber backend, ForkNumber forknum)
|
calculate_relation_size(RelFileLocator *rfn, ProcNumber backend, ForkNumber forknum)
|
||||||
{
|
{
|
||||||
int64 totalsize = 0;
|
int64 totalsize = 0;
|
||||||
char *relationpath;
|
RelPathStr relationpath;
|
||||||
char pathname[MAXPGPATH];
|
char pathname[MAXPGPATH];
|
||||||
unsigned int segcount = 0;
|
unsigned int segcount = 0;
|
||||||
|
|
||||||
@ -340,10 +340,10 @@ calculate_relation_size(RelFileLocator *rfn, ProcNumber backend, ForkNumber fork
|
|||||||
|
|
||||||
if (segcount == 0)
|
if (segcount == 0)
|
||||||
snprintf(pathname, MAXPGPATH, "%s",
|
snprintf(pathname, MAXPGPATH, "%s",
|
||||||
relationpath);
|
relationpath.str);
|
||||||
else
|
else
|
||||||
snprintf(pathname, MAXPGPATH, "%s.%u",
|
snprintf(pathname, MAXPGPATH, "%s.%u",
|
||||||
relationpath, segcount);
|
relationpath.str, segcount);
|
||||||
|
|
||||||
if (stat(pathname, &fst) < 0)
|
if (stat(pathname, &fst) < 0)
|
||||||
{
|
{
|
||||||
@ -973,7 +973,7 @@ pg_relation_filepath(PG_FUNCTION_ARGS)
|
|||||||
Form_pg_class relform;
|
Form_pg_class relform;
|
||||||
RelFileLocator rlocator;
|
RelFileLocator rlocator;
|
||||||
ProcNumber backend;
|
ProcNumber backend;
|
||||||
char *path;
|
RelPathStr path;
|
||||||
|
|
||||||
tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
|
tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
|
||||||
if (!HeapTupleIsValid(tuple))
|
if (!HeapTupleIsValid(tuple))
|
||||||
@ -1039,5 +1039,5 @@ pg_relation_filepath(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
path = relpathbackend(rlocator, backend, MAIN_FORKNUM);
|
path = relpathbackend(rlocator, backend, MAIN_FORKNUM);
|
||||||
|
|
||||||
PG_RETURN_TEXT_P(cstring_to_text(path));
|
PG_RETURN_TEXT_P(cstring_to_text(path.str));
|
||||||
}
|
}
|
||||||
|
@ -652,18 +652,17 @@ isRelDataFile(const char *path)
|
|||||||
static char *
|
static char *
|
||||||
datasegpath(RelFileLocator rlocator, ForkNumber forknum, BlockNumber segno)
|
datasegpath(RelFileLocator rlocator, ForkNumber forknum, BlockNumber segno)
|
||||||
{
|
{
|
||||||
char *path;
|
RelPathStr path;
|
||||||
char *segpath;
|
char *segpath;
|
||||||
|
|
||||||
path = relpathperm(rlocator, forknum);
|
path = relpathperm(rlocator, forknum);
|
||||||
if (segno > 0)
|
if (segno > 0)
|
||||||
{
|
{
|
||||||
segpath = psprintf("%s.%u", path, segno);
|
segpath = psprintf("%s.%u", path.str, segno);
|
||||||
pfree(path);
|
|
||||||
return segpath;
|
return segpath;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return path;
|
return pstrdup(path.str);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -132,17 +132,18 @@ GetDatabasePath(Oid dbOid, Oid spcOid)
|
|||||||
/*
|
/*
|
||||||
* GetRelationPath - construct path to a relation's file
|
* GetRelationPath - construct path to a relation's file
|
||||||
*
|
*
|
||||||
* Result is a palloc'd string.
|
* The result is returned in-place as a struct, to make it suitable for use in
|
||||||
|
* critical sections etc.
|
||||||
*
|
*
|
||||||
* Note: ideally, procNumber would be declared as type ProcNumber, but
|
* Note: ideally, procNumber would be declared as type ProcNumber, but
|
||||||
* relpath.h would have to include a backend-only header to do that; doesn't
|
* relpath.h would have to include a backend-only header to do that; doesn't
|
||||||
* seem worth the trouble considering ProcNumber is just int anyway.
|
* seem worth the trouble considering ProcNumber is just int anyway.
|
||||||
*/
|
*/
|
||||||
char *
|
RelPathStr
|
||||||
GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber,
|
GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber,
|
||||||
int procNumber, ForkNumber forkNumber)
|
int procNumber, ForkNumber forkNumber)
|
||||||
{
|
{
|
||||||
char *path;
|
RelPathStr rp;
|
||||||
|
|
||||||
if (spcOid == GLOBALTABLESPACE_OID)
|
if (spcOid == GLOBALTABLESPACE_OID)
|
||||||
{
|
{
|
||||||
@ -150,10 +151,11 @@ GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber,
|
|||||||
Assert(dbOid == 0);
|
Assert(dbOid == 0);
|
||||||
Assert(procNumber == INVALID_PROC_NUMBER);
|
Assert(procNumber == INVALID_PROC_NUMBER);
|
||||||
if (forkNumber != MAIN_FORKNUM)
|
if (forkNumber != MAIN_FORKNUM)
|
||||||
path = psprintf("global/%u_%s",
|
sprintf(rp.str, "global/%u_%s",
|
||||||
relNumber, forkNames[forkNumber]);
|
relNumber, forkNames[forkNumber]);
|
||||||
else
|
else
|
||||||
path = psprintf("global/%u", relNumber);
|
sprintf(rp.str, "global/%u",
|
||||||
|
relNumber);
|
||||||
}
|
}
|
||||||
else if (spcOid == DEFAULTTABLESPACE_OID)
|
else if (spcOid == DEFAULTTABLESPACE_OID)
|
||||||
{
|
{
|
||||||
@ -161,21 +163,23 @@ GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber,
|
|||||||
if (procNumber == INVALID_PROC_NUMBER)
|
if (procNumber == INVALID_PROC_NUMBER)
|
||||||
{
|
{
|
||||||
if (forkNumber != MAIN_FORKNUM)
|
if (forkNumber != MAIN_FORKNUM)
|
||||||
path = psprintf("base/%u/%u_%s",
|
{
|
||||||
|
sprintf(rp.str, "base/%u/%u_%s",
|
||||||
dbOid, relNumber,
|
dbOid, relNumber,
|
||||||
forkNames[forkNumber]);
|
forkNames[forkNumber]);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
path = psprintf("base/%u/%u",
|
sprintf(rp.str, "base/%u/%u",
|
||||||
dbOid, relNumber);
|
dbOid, relNumber);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (forkNumber != MAIN_FORKNUM)
|
if (forkNumber != MAIN_FORKNUM)
|
||||||
path = psprintf("base/%u/t%d_%u_%s",
|
sprintf(rp.str, "base/%u/t%d_%u_%s",
|
||||||
dbOid, procNumber, relNumber,
|
dbOid, procNumber, relNumber,
|
||||||
forkNames[forkNumber]);
|
forkNames[forkNumber]);
|
||||||
else
|
else
|
||||||
path = psprintf("base/%u/t%d_%u",
|
sprintf(rp.str, "base/%u/t%d_%u",
|
||||||
dbOid, procNumber, relNumber);
|
dbOid, procNumber, relNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -185,13 +189,13 @@ GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber,
|
|||||||
if (procNumber == INVALID_PROC_NUMBER)
|
if (procNumber == INVALID_PROC_NUMBER)
|
||||||
{
|
{
|
||||||
if (forkNumber != MAIN_FORKNUM)
|
if (forkNumber != MAIN_FORKNUM)
|
||||||
path = psprintf("%s/%u/%s/%u/%u_%s",
|
sprintf(rp.str, "%s/%u/%s/%u/%u_%s",
|
||||||
PG_TBLSPC_DIR, spcOid,
|
PG_TBLSPC_DIR, spcOid,
|
||||||
TABLESPACE_VERSION_DIRECTORY,
|
TABLESPACE_VERSION_DIRECTORY,
|
||||||
dbOid, relNumber,
|
dbOid, relNumber,
|
||||||
forkNames[forkNumber]);
|
forkNames[forkNumber]);
|
||||||
else
|
else
|
||||||
path = psprintf("%s/%u/%s/%u/%u",
|
sprintf(rp.str, "%s/%u/%s/%u/%u",
|
||||||
PG_TBLSPC_DIR, spcOid,
|
PG_TBLSPC_DIR, spcOid,
|
||||||
TABLESPACE_VERSION_DIRECTORY,
|
TABLESPACE_VERSION_DIRECTORY,
|
||||||
dbOid, relNumber);
|
dbOid, relNumber);
|
||||||
@ -199,17 +203,20 @@ GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (forkNumber != MAIN_FORKNUM)
|
if (forkNumber != MAIN_FORKNUM)
|
||||||
path = psprintf("%s/%u/%s/%u/t%d_%u_%s",
|
sprintf(rp.str, "%s/%u/%s/%u/t%d_%u_%s",
|
||||||
PG_TBLSPC_DIR, spcOid,
|
PG_TBLSPC_DIR, spcOid,
|
||||||
TABLESPACE_VERSION_DIRECTORY,
|
TABLESPACE_VERSION_DIRECTORY,
|
||||||
dbOid, procNumber, relNumber,
|
dbOid, procNumber, relNumber,
|
||||||
forkNames[forkNumber]);
|
forkNames[forkNumber]);
|
||||||
else
|
else
|
||||||
path = psprintf("%s/%u/%s/%u/t%d_%u",
|
sprintf(rp.str, "%s/%u/%s/%u/t%d_%u",
|
||||||
PG_TBLSPC_DIR, spcOid,
|
PG_TBLSPC_DIR, spcOid,
|
||||||
TABLESPACE_VERSION_DIRECTORY,
|
TABLESPACE_VERSION_DIRECTORY,
|
||||||
dbOid, procNumber, relNumber);
|
dbOid, procNumber, relNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return path;
|
|
||||||
|
Assert(strnlen(rp.str, REL_PATH_STR_MAXLEN + 1) <= REL_PATH_STR_MAXLEN);
|
||||||
|
|
||||||
|
return rp;
|
||||||
}
|
}
|
||||||
|
@ -77,12 +77,60 @@ extern PGDLLIMPORT const char *const forkNames[];
|
|||||||
extern ForkNumber forkname_to_number(const char *forkName);
|
extern ForkNumber forkname_to_number(const char *forkName);
|
||||||
extern int forkname_chars(const char *str, ForkNumber *fork);
|
extern int forkname_chars(const char *str, ForkNumber *fork);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unfortunately, there's no easy way to derive PROCNUMBER_CHARS from
|
||||||
|
* MAX_BACKENDS. MAX_BACKENDS is 2^18-1. Crosschecked in test_relpath().
|
||||||
|
*/
|
||||||
|
#define PROCNUMBER_CHARS 6
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The longest possible relation path lengths is from the following format:
|
||||||
|
* sprintf(rp.path, "%s/%u/%s/%u/t%d_%u",
|
||||||
|
* PG_TBLSPC_DIR, spcOid,
|
||||||
|
* TABLESPACE_VERSION_DIRECTORY,
|
||||||
|
* dbOid, procNumber, relNumber);
|
||||||
|
*
|
||||||
|
* Note this does *not* include the trailing null-byte, to make it easier to
|
||||||
|
* combine it with other lengths.
|
||||||
|
*/
|
||||||
|
#define REL_PATH_STR_MAXLEN \
|
||||||
|
( \
|
||||||
|
sizeof(PG_TBLSPC_DIR) - 1 \
|
||||||
|
+ sizeof((char)'/') \
|
||||||
|
+ OIDCHARS /* spcOid */ \
|
||||||
|
+ sizeof((char)'/') \
|
||||||
|
+ sizeof(TABLESPACE_VERSION_DIRECTORY) - 1 \
|
||||||
|
+ sizeof((char)'/') \
|
||||||
|
+ OIDCHARS /* dbOid */ \
|
||||||
|
+ sizeof((char)'/') \
|
||||||
|
+ sizeof((char)'t') /* temporary table indicator */ \
|
||||||
|
+ PROCNUMBER_CHARS /* procNumber */ \
|
||||||
|
+ sizeof((char)'_') \
|
||||||
|
+ OIDCHARS /* relNumber */ \
|
||||||
|
+ sizeof((char)'_') \
|
||||||
|
+ FORKNAMECHARS /* forkNames[forkNumber] */ \
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* String of the exact length required to represent a relation path. We return
|
||||||
|
* this struct, instead of char[REL_PATH_STR_MAXLEN + 1], as the pointer would
|
||||||
|
* decay to a plain char * too easily, possibly preventing the compiler from
|
||||||
|
* detecting invalid references to the on-stack return value of
|
||||||
|
* GetRelationPath().
|
||||||
|
*/
|
||||||
|
typedef struct RelPathStr
|
||||||
|
{
|
||||||
|
char str[REL_PATH_STR_MAXLEN + 1];
|
||||||
|
} RelPathStr;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stuff for computing filesystem pathnames for relations.
|
* Stuff for computing filesystem pathnames for relations.
|
||||||
*/
|
*/
|
||||||
extern char *GetDatabasePath(Oid dbOid, Oid spcOid);
|
extern char *GetDatabasePath(Oid dbOid, Oid spcOid);
|
||||||
|
|
||||||
extern char *GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber,
|
extern RelPathStr GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber,
|
||||||
int procNumber, ForkNumber forkNumber);
|
int procNumber, ForkNumber forkNumber);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -903,3 +903,14 @@ SELECT gist_stratnum_common(3);
|
|||||||
18
|
18
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
-- relpath tests
|
||||||
|
CREATE FUNCTION test_relpath()
|
||||||
|
RETURNS void
|
||||||
|
AS :'regresslib'
|
||||||
|
LANGUAGE C;
|
||||||
|
SELECT test_relpath();
|
||||||
|
test_relpath
|
||||||
|
--------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "optimizer/plancat.h"
|
#include "optimizer/plancat.h"
|
||||||
#include "parser/parse_coerce.h"
|
#include "parser/parse_coerce.h"
|
||||||
#include "port/atomics.h"
|
#include "port/atomics.h"
|
||||||
|
#include "postmaster/postmaster.h" /* for MAX_BACKENDS */
|
||||||
#include "storage/spin.h"
|
#include "storage/spin.h"
|
||||||
#include "utils/array.h"
|
#include "utils/array.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
@ -1208,3 +1209,31 @@ binary_coercible(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
PG_RETURN_BOOL(IsBinaryCoercible(srctype, targettype));
|
PG_RETURN_BOOL(IsBinaryCoercible(srctype, targettype));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sanity checks for functions in relpath.h
|
||||||
|
*/
|
||||||
|
PG_FUNCTION_INFO_V1(test_relpath);
|
||||||
|
Datum
|
||||||
|
test_relpath(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
|
RelPathStr rpath;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify that PROCNUMBER_CHARS and MAX_BACKENDS stay in sync.
|
||||||
|
* Unfortunately I don't know how to express that in a way suitable for a
|
||||||
|
* static assert.
|
||||||
|
*/
|
||||||
|
if ((int) ceil(log10(MAX_BACKENDS)) != PROCNUMBER_CHARS)
|
||||||
|
elog(WARNING, "mismatch between MAX_BACKENDS and PROCNUMBER_CHARS");
|
||||||
|
|
||||||
|
/* verify that the max-length relpath is generated ok */
|
||||||
|
rpath = GetRelationPath(OID_MAX, OID_MAX, OID_MAX, MAX_BACKENDS - 1,
|
||||||
|
INIT_FORKNUM);
|
||||||
|
|
||||||
|
if (strlen(rpath.str) != REL_PATH_STR_MAXLEN)
|
||||||
|
elog(WARNING, "maximum length relpath is if length %zu instead of %zu",
|
||||||
|
strlen(rpath.str), REL_PATH_STR_MAXLEN);
|
||||||
|
|
||||||
|
PG_RETURN_VOID();
|
||||||
|
}
|
||||||
|
@ -403,3 +403,11 @@ DROP FUNCTION explain_mask_costs(text, bool, bool, bool, bool);
|
|||||||
-- test stratnum support functions
|
-- test stratnum support functions
|
||||||
SELECT gist_stratnum_common(7);
|
SELECT gist_stratnum_common(7);
|
||||||
SELECT gist_stratnum_common(3);
|
SELECT gist_stratnum_common(3);
|
||||||
|
|
||||||
|
|
||||||
|
-- relpath tests
|
||||||
|
CREATE FUNCTION test_relpath()
|
||||||
|
RETURNS void
|
||||||
|
AS :'regresslib'
|
||||||
|
LANGUAGE C;
|
||||||
|
SELECT test_relpath();
|
||||||
|
@ -2410,6 +2410,7 @@ RelMapFile
|
|||||||
RelMapping
|
RelMapping
|
||||||
RelOptInfo
|
RelOptInfo
|
||||||
RelOptKind
|
RelOptKind
|
||||||
|
RelPathStr
|
||||||
RelStatsInfo
|
RelStatsInfo
|
||||||
RelToCheck
|
RelToCheck
|
||||||
RelToCluster
|
RelToCluster
|
||||||
|
Loading…
x
Reference in New Issue
Block a user