mirror of
https://github.com/postgres/postgres.git
synced 2025-07-08 11:42:09 +03:00
Move relpath() to libpgcommon
This enables non-backend code, such as pg_xlogdump, to use it easily. The previous location, in src/backend/catalog/catalog.c, made that essentially impossible because that file depends on many backend-only facilities; so this needs to live separately.
This commit is contained in:
162
src/common/relpath.c
Normal file
162
src/common/relpath.c
Normal file
@ -0,0 +1,162 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
* relpath.c
|
||||
* Shared frontend/backend code to find out pathnames of relation files
|
||||
*
|
||||
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/common/relpath.c
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef FRONTEND
|
||||
#include "postgres.h"
|
||||
#else
|
||||
#include "postgres_fe.h"
|
||||
#endif
|
||||
|
||||
#include "catalog/pg_tablespace.h"
|
||||
#include "common/relpath.h"
|
||||
#include "storage/backendid.h"
|
||||
|
||||
#define FORKNAMECHARS 4 /* max chars for a fork name */
|
||||
|
||||
/*
|
||||
* Lookup table of fork name by fork number.
|
||||
*
|
||||
* If you add a new entry, remember to update the errhint below, and the
|
||||
* documentation for pg_relation_size(). Also keep FORKNAMECHARS above
|
||||
* up-to-date.
|
||||
*/
|
||||
const char *forkNames[] = {
|
||||
"main", /* MAIN_FORKNUM */
|
||||
"fsm", /* FSM_FORKNUM */
|
||||
"vm", /* VISIBILITYMAP_FORKNUM */
|
||||
"init" /* INIT_FORKNUM */
|
||||
};
|
||||
|
||||
/*
|
||||
* forkname_chars
|
||||
* We use this to figure out whether a filename could be a relation
|
||||
* fork (as opposed to an oddly named stray file that somehow ended
|
||||
* up in the database directory). If the passed string begins with
|
||||
* a fork name (other than the main fork name), we return its length,
|
||||
* and set *fork (if not NULL) to the fork number. If not, we return 0.
|
||||
*
|
||||
* Note that the present coding assumes that there are no fork names which
|
||||
* are prefixes of other fork names.
|
||||
*/
|
||||
int
|
||||
forkname_chars(const char *str, ForkNumber *fork)
|
||||
{
|
||||
ForkNumber forkNum;
|
||||
|
||||
for (forkNum = 1; forkNum <= MAX_FORKNUM; forkNum++)
|
||||
{
|
||||
int len = strlen(forkNames[forkNum]);
|
||||
|
||||
if (strncmp(forkNames[forkNum], str, len) == 0)
|
||||
{
|
||||
if (fork)
|
||||
*fork = forkNum;
|
||||
return len;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* relpathbackend - construct path to a relation's file
|
||||
*
|
||||
* Result is a palloc'd string.
|
||||
*/
|
||||
char *
|
||||
relpathbackend(RelFileNode rnode, BackendId backend, ForkNumber forknum)
|
||||
{
|
||||
int pathlen;
|
||||
char *path;
|
||||
|
||||
if (rnode.spcNode == GLOBALTABLESPACE_OID)
|
||||
{
|
||||
/* Shared system relations live in {datadir}/global */
|
||||
Assert(rnode.dbNode == 0);
|
||||
Assert(backend == InvalidBackendId);
|
||||
pathlen = 7 + OIDCHARS + 1 + FORKNAMECHARS + 1;
|
||||
path = (char *) palloc(pathlen);
|
||||
if (forknum != MAIN_FORKNUM)
|
||||
snprintf(path, pathlen, "global/%u_%s",
|
||||
rnode.relNode, forkNames[forknum]);
|
||||
else
|
||||
snprintf(path, pathlen, "global/%u", rnode.relNode);
|
||||
}
|
||||
else if (rnode.spcNode == DEFAULTTABLESPACE_OID)
|
||||
{
|
||||
/* The default tablespace is {datadir}/base */
|
||||
if (backend == InvalidBackendId)
|
||||
{
|
||||
pathlen = 5 + OIDCHARS + 1 + OIDCHARS + 1 + FORKNAMECHARS + 1;
|
||||
path = (char *) palloc(pathlen);
|
||||
if (forknum != MAIN_FORKNUM)
|
||||
snprintf(path, pathlen, "base/%u/%u_%s",
|
||||
rnode.dbNode, rnode.relNode,
|
||||
forkNames[forknum]);
|
||||
else
|
||||
snprintf(path, pathlen, "base/%u/%u",
|
||||
rnode.dbNode, rnode.relNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* OIDCHARS will suffice for an integer, too */
|
||||
pathlen = 5 + OIDCHARS + 2 + OIDCHARS + 1 + OIDCHARS + 1
|
||||
+ FORKNAMECHARS + 1;
|
||||
path = (char *) palloc(pathlen);
|
||||
if (forknum != MAIN_FORKNUM)
|
||||
snprintf(path, pathlen, "base/%u/t%d_%u_%s",
|
||||
rnode.dbNode, backend, rnode.relNode,
|
||||
forkNames[forknum]);
|
||||
else
|
||||
snprintf(path, pathlen, "base/%u/t%d_%u",
|
||||
rnode.dbNode, backend, rnode.relNode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* All other tablespaces are accessed via symlinks */
|
||||
if (backend == InvalidBackendId)
|
||||
{
|
||||
pathlen = 9 + 1 + OIDCHARS + 1
|
||||
+ strlen(TABLESPACE_VERSION_DIRECTORY) + 1 + OIDCHARS + 1
|
||||
+ OIDCHARS + 1 + FORKNAMECHARS + 1;
|
||||
path = (char *) palloc(pathlen);
|
||||
if (forknum != MAIN_FORKNUM)
|
||||
snprintf(path, pathlen, "pg_tblspc/%u/%s/%u/%u_%s",
|
||||
rnode.spcNode, TABLESPACE_VERSION_DIRECTORY,
|
||||
rnode.dbNode, rnode.relNode,
|
||||
forkNames[forknum]);
|
||||
else
|
||||
snprintf(path, pathlen, "pg_tblspc/%u/%s/%u/%u",
|
||||
rnode.spcNode, TABLESPACE_VERSION_DIRECTORY,
|
||||
rnode.dbNode, rnode.relNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* OIDCHARS will suffice for an integer, too */
|
||||
pathlen = 9 + 1 + OIDCHARS + 1
|
||||
+ strlen(TABLESPACE_VERSION_DIRECTORY) + 1 + OIDCHARS + 2
|
||||
+ OIDCHARS + 1 + OIDCHARS + 1 + FORKNAMECHARS + 1;
|
||||
path = (char *) palloc(pathlen);
|
||||
if (forknum != MAIN_FORKNUM)
|
||||
snprintf(path, pathlen, "pg_tblspc/%u/%s/%u/t%d_%u_%s",
|
||||
rnode.spcNode, TABLESPACE_VERSION_DIRECTORY,
|
||||
rnode.dbNode, backend, rnode.relNode,
|
||||
forkNames[forknum]);
|
||||
else
|
||||
snprintf(path, pathlen, "pg_tblspc/%u/%s/%u/t%d_%u",
|
||||
rnode.spcNode, TABLESPACE_VERSION_DIRECTORY,
|
||||
rnode.dbNode, backend, rnode.relNode);
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
Reference in New Issue
Block a user