~ubuntu-branches/debian/experimental/postgresql-11/experimental

« back to all changes in this revision

Viewing changes to src/common/relpath.c

  • Committer: Package Import Robot
  • Author(s): Christoph Berg
  • Date: 2018-05-22 14:19:08 UTC
  • Revision ID: package-import@ubuntu.com-20180522141908-0oy9ujs1b5vrda74
Tags: upstream-11~beta1
ImportĀ upstreamĀ versionĀ 11~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 * relpath.c
 
3
 *              Shared frontend/backend code to compute pathnames of relation files
 
4
 *
 
5
 * This module also contains some logic associated with fork names.
 
6
 *
 
7
 * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
 
8
 * Portions Copyright (c) 1994, Regents of the University of California
 
9
 *
 
10
 * IDENTIFICATION
 
11
 *        src/common/relpath.c
 
12
 *
 
13
 *-------------------------------------------------------------------------
 
14
 */
 
15
#ifndef FRONTEND
 
16
#include "postgres.h"
 
17
#else
 
18
#include "postgres_fe.h"
 
19
#endif
 
20
 
 
21
#include "catalog/pg_tablespace_d.h"
 
22
#include "common/relpath.h"
 
23
#include "storage/backendid.h"
 
24
 
 
25
 
 
26
/*
 
27
 * Lookup table of fork name by fork number.
 
28
 *
 
29
 * If you add a new entry, remember to update the errhint in
 
30
 * forkname_to_number() below, and update the SGML documentation for
 
31
 * pg_relation_size().
 
32
 */
 
33
const char *const forkNames[] = {
 
34
        "main",                                         /* MAIN_FORKNUM */
 
35
        "fsm",                                          /* FSM_FORKNUM */
 
36
        "vm",                                           /* VISIBILITYMAP_FORKNUM */
 
37
        "init"                                          /* INIT_FORKNUM */
 
38
};
 
39
 
 
40
/*
 
41
 * forkname_to_number - look up fork number by name
 
42
 *
 
43
 * In backend, we throw an error for no match; in frontend, we just
 
44
 * return InvalidForkNumber.
 
45
 */
 
46
ForkNumber
 
47
forkname_to_number(const char *forkName)
 
48
{
 
49
        ForkNumber      forkNum;
 
50
 
 
51
        for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
 
52
                if (strcmp(forkNames[forkNum], forkName) == 0)
 
53
                        return forkNum;
 
54
 
 
55
#ifndef FRONTEND
 
56
        ereport(ERROR,
 
57
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
58
                         errmsg("invalid fork name"),
 
59
                         errhint("Valid fork names are \"main\", \"fsm\", "
 
60
                                         "\"vm\", and \"init\".")));
 
61
#endif
 
62
 
 
63
        return InvalidForkNumber;
 
64
}
 
65
 
 
66
/*
 
67
 * forkname_chars
 
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.
 
73
 *
 
74
 * Note that the present coding assumes that there are no fork names which
 
75
 * are prefixes of other fork names.
 
76
 */
 
77
int
 
78
forkname_chars(const char *str, ForkNumber *fork)
 
79
{
 
80
        ForkNumber      forkNum;
 
81
 
 
82
        for (forkNum = 1; forkNum <= MAX_FORKNUM; forkNum++)
 
83
        {
 
84
                int                     len = strlen(forkNames[forkNum]);
 
85
 
 
86
                if (strncmp(forkNames[forkNum], str, len) == 0)
 
87
                {
 
88
                        if (fork)
 
89
                                *fork = forkNum;
 
90
                        return len;
 
91
                }
 
92
        }
 
93
        if (fork)
 
94
                *fork = InvalidForkNumber;
 
95
        return 0;
 
96
}
 
97
 
 
98
 
 
99
/*
 
100
 * GetDatabasePath - construct path to a database directory
 
101
 *
 
102
 * Result is a palloc'd string.
 
103
 *
 
104
 * XXX this must agree with GetRelationPath()!
 
105
 */
 
106
char *
 
107
GetDatabasePath(Oid dbNode, Oid spcNode)
 
108
{
 
109
        if (spcNode == GLOBALTABLESPACE_OID)
 
110
        {
 
111
                /* Shared system relations live in {datadir}/global */
 
112
                Assert(dbNode == 0);
 
113
                return pstrdup("global");
 
114
        }
 
115
        else if (spcNode == DEFAULTTABLESPACE_OID)
 
116
        {
 
117
                /* The default tablespace is {datadir}/base */
 
118
                return psprintf("base/%u", dbNode);
 
119
        }
 
120
        else
 
121
        {
 
122
                /* All other tablespaces are accessed via symlinks */
 
123
                return psprintf("pg_tblspc/%u/%s/%u",
 
124
                                                spcNode, TABLESPACE_VERSION_DIRECTORY, dbNode);
 
125
        }
 
126
}
 
127
 
 
128
/*
 
129
 * GetRelationPath - construct path to a relation's file
 
130
 *
 
131
 * Result is a palloc'd string.
 
132
 *
 
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.
 
136
 */
 
137
char *
 
138
GetRelationPath(Oid dbNode, Oid spcNode, Oid relNode,
 
139
                                int backendId, ForkNumber forkNumber)
 
140
{
 
141
        char       *path;
 
142
 
 
143
        if (spcNode == GLOBALTABLESPACE_OID)
 
144
        {
 
145
                /* Shared system relations live in {datadir}/global */
 
146
                Assert(dbNode == 0);
 
147
                Assert(backendId == InvalidBackendId);
 
148
                if (forkNumber != MAIN_FORKNUM)
 
149
                        path = psprintf("global/%u_%s",
 
150
                                                        relNode, forkNames[forkNumber]);
 
151
                else
 
152
                        path = psprintf("global/%u", relNode);
 
153
        }
 
154
        else if (spcNode == DEFAULTTABLESPACE_OID)
 
155
        {
 
156
                /* The default tablespace is {datadir}/base */
 
157
                if (backendId == InvalidBackendId)
 
158
                {
 
159
                        if (forkNumber != MAIN_FORKNUM)
 
160
                                path = psprintf("base/%u/%u_%s",
 
161
                                                                dbNode, relNode,
 
162
                                                                forkNames[forkNumber]);
 
163
                        else
 
164
                                path = psprintf("base/%u/%u",
 
165
                                                                dbNode, relNode);
 
166
                }
 
167
                else
 
168
                {
 
169
                        if (forkNumber != MAIN_FORKNUM)
 
170
                                path = psprintf("base/%u/t%d_%u_%s",
 
171
                                                                dbNode, backendId, relNode,
 
172
                                                                forkNames[forkNumber]);
 
173
                        else
 
174
                                path = psprintf("base/%u/t%d_%u",
 
175
                                                                dbNode, backendId, relNode);
 
176
                }
 
177
        }
 
178
        else
 
179
        {
 
180
                /* All other tablespaces are accessed via symlinks */
 
181
                if (backendId == InvalidBackendId)
 
182
                {
 
183
                        if (forkNumber != MAIN_FORKNUM)
 
184
                                path = psprintf("pg_tblspc/%u/%s/%u/%u_%s",
 
185
                                                                spcNode, TABLESPACE_VERSION_DIRECTORY,
 
186
                                                                dbNode, relNode,
 
187
                                                                forkNames[forkNumber]);
 
188
                        else
 
189
                                path = psprintf("pg_tblspc/%u/%s/%u/%u",
 
190
                                                                spcNode, TABLESPACE_VERSION_DIRECTORY,
 
191
                                                                dbNode, relNode);
 
192
                }
 
193
                else
 
194
                {
 
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]);
 
200
                        else
 
201
                                path = psprintf("pg_tblspc/%u/%s/%u/t%d_%u",
 
202
                                                                spcNode, TABLESPACE_VERSION_DIRECTORY,
 
203
                                                                dbNode, backendId, relNode);
 
204
                }
 
205
        }
 
206
        return path;
 
207
}