1
/*-------------------------------------------------------------------------
3
* Shared frontend/backend code to compute pathnames of relation files
5
* This module also contains some logic associated with fork names.
7
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
8
* Portions Copyright (c) 1994, Regents of the University of California
11
* src/common/relpath.c
13
*-------------------------------------------------------------------------
18
#include "postgres_fe.h"
21
#include "catalog/pg_tablespace_d.h"
22
#include "common/relpath.h"
23
#include "storage/backendid.h"
27
* Lookup table of fork name by fork number.
29
* If you add a new entry, remember to update the errhint in
30
* forkname_to_number() below, and update the SGML documentation for
33
const char *const forkNames[] = {
34
"main", /* MAIN_FORKNUM */
35
"fsm", /* FSM_FORKNUM */
36
"vm", /* VISIBILITYMAP_FORKNUM */
37
"init" /* INIT_FORKNUM */
41
* forkname_to_number - look up fork number by name
43
* In backend, we throw an error for no match; in frontend, we just
44
* return InvalidForkNumber.
47
forkname_to_number(const char *forkName)
51
for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
52
if (strcmp(forkNames[forkNum], forkName) == 0)
57
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
58
errmsg("invalid fork name"),
59
errhint("Valid fork names are \"main\", \"fsm\", "
60
"\"vm\", and \"init\".")));
63
return InvalidForkNumber;
68
* We use this to figure out whether a filename could be a relation
69
* fork (as opposed to an oddly named stray file that somehow ended
70
* up in the database directory). If the passed string begins with
71
* a fork name (other than the main fork name), we return its length,
72
* and set *fork (if not NULL) to the fork number. If not, we return 0.
74
* Note that the present coding assumes that there are no fork names which
75
* are prefixes of other fork names.
78
forkname_chars(const char *str, ForkNumber *fork)
82
for (forkNum = 1; forkNum <= MAX_FORKNUM; forkNum++)
84
int len = strlen(forkNames[forkNum]);
86
if (strncmp(forkNames[forkNum], str, len) == 0)
94
*fork = InvalidForkNumber;
100
* GetDatabasePath - construct path to a database directory
102
* Result is a palloc'd string.
104
* XXX this must agree with GetRelationPath()!
107
GetDatabasePath(Oid dbNode, Oid spcNode)
109
if (spcNode == GLOBALTABLESPACE_OID)
111
/* Shared system relations live in {datadir}/global */
113
return pstrdup("global");
115
else if (spcNode == DEFAULTTABLESPACE_OID)
117
/* The default tablespace is {datadir}/base */
118
return psprintf("base/%u", dbNode);
122
/* All other tablespaces are accessed via symlinks */
123
return psprintf("pg_tblspc/%u/%s/%u",
124
spcNode, TABLESPACE_VERSION_DIRECTORY, dbNode);
129
* GetRelationPath - construct path to a relation's file
131
* Result is a palloc'd string.
133
* Note: ideally, backendId would be declared as type BackendId, but relpath.h
134
* would have to include a backend-only header to do that; doesn't seem worth
135
* the trouble considering BackendId is just int anyway.
138
GetRelationPath(Oid dbNode, Oid spcNode, Oid relNode,
139
int backendId, ForkNumber forkNumber)
143
if (spcNode == GLOBALTABLESPACE_OID)
145
/* Shared system relations live in {datadir}/global */
147
Assert(backendId == InvalidBackendId);
148
if (forkNumber != MAIN_FORKNUM)
149
path = psprintf("global/%u_%s",
150
relNode, forkNames[forkNumber]);
152
path = psprintf("global/%u", relNode);
154
else if (spcNode == DEFAULTTABLESPACE_OID)
156
/* The default tablespace is {datadir}/base */
157
if (backendId == InvalidBackendId)
159
if (forkNumber != MAIN_FORKNUM)
160
path = psprintf("base/%u/%u_%s",
162
forkNames[forkNumber]);
164
path = psprintf("base/%u/%u",
169
if (forkNumber != MAIN_FORKNUM)
170
path = psprintf("base/%u/t%d_%u_%s",
171
dbNode, backendId, relNode,
172
forkNames[forkNumber]);
174
path = psprintf("base/%u/t%d_%u",
175
dbNode, backendId, relNode);
180
/* All other tablespaces are accessed via symlinks */
181
if (backendId == InvalidBackendId)
183
if (forkNumber != MAIN_FORKNUM)
184
path = psprintf("pg_tblspc/%u/%s/%u/%u_%s",
185
spcNode, TABLESPACE_VERSION_DIRECTORY,
187
forkNames[forkNumber]);
189
path = psprintf("pg_tblspc/%u/%s/%u/%u",
190
spcNode, TABLESPACE_VERSION_DIRECTORY,
195
if (forkNumber != MAIN_FORKNUM)
196
path = psprintf("pg_tblspc/%u/%s/%u/t%d_%u_%s",
197
spcNode, TABLESPACE_VERSION_DIRECTORY,
198
dbNode, backendId, relNode,
199
forkNames[forkNumber]);
201
path = psprintf("pg_tblspc/%u/%s/%u/t%d_%u",
202
spcNode, TABLESPACE_VERSION_DIRECTORY,
203
dbNode, backendId, relNode);