/Users/deen/code/yugabyte-db/src/postgres/src/common/relpath.c
Line | Count | Source (jump to first uncovered line) |
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 | 20 | { |
49 | 20 | ForkNumber forkNum; |
50 | | |
51 | 20 | for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) |
52 | 20 | if (strcmp(forkNames[forkNum], forkName) == 0) |
53 | 20 | return forkNum; |
54 | | |
55 | 20 | #ifndef FRONTEND |
56 | 0 | ereport(ERROR, |
57 | 0 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
58 | 0 | errmsg("invalid fork name"), |
59 | 0 | errhint("Valid fork names are \"main\", \"fsm\", " |
60 | 0 | "\"vm\", and \"init\"."))); |
61 | 0 | #endif |
62 | |
|
63 | 0 | return InvalidForkNumber; |
64 | 0 | } |
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 | 0 | { |
80 | 0 | ForkNumber forkNum; |
81 | |
|
82 | 0 | for (forkNum = 1; forkNum <= MAX_FORKNUM; forkNum++) |
83 | 0 | { |
84 | 0 | int len = strlen(forkNames[forkNum]); |
85 | |
|
86 | 0 | if (strncmp(forkNames[forkNum], str, len) == 0) |
87 | 0 | { |
88 | 0 | if (fork) |
89 | 0 | *fork = forkNum; |
90 | 0 | return len; |
91 | 0 | } |
92 | 0 | } |
93 | 0 | if (fork) |
94 | 0 | *fork = InvalidForkNumber; |
95 | 0 | return 0; |
96 | 0 | } |
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 | 1.02k | { |
109 | 1.02k | if (spcNode == GLOBALTABLESPACE_OID) |
110 | 0 | { |
111 | | /* Shared system relations live in {datadir}/global */ |
112 | 0 | Assert(dbNode == 0); |
113 | 0 | return pstrdup("global"); |
114 | 1.02k | } |
115 | 1.02k | else if (spcNode == DEFAULTTABLESPACE_OID) |
116 | 1.02k | { |
117 | | /* The default tablespace is {datadir}/base */ |
118 | 1.02k | return psprintf("base/%u", dbNode); |
119 | 1.02k | } |
120 | 0 | else |
121 | 0 | { |
122 | | /* All other tablespaces are accessed via symlinks */ |
123 | 0 | return psprintf("pg_tblspc/%u/%s/%u", |
124 | 0 | spcNode, TABLESPACE_VERSION_DIRECTORY, dbNode); |
125 | 0 | } |
126 | 1.02k | } |
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 | 4.02k | { |
141 | 4.02k | char *path; |
142 | | |
143 | 4.02k | if (spcNode == GLOBALTABLESPACE_OID) |
144 | 8 | { |
145 | | /* Shared system relations live in {datadir}/global */ |
146 | 8 | Assert(dbNode == 0); |
147 | 8 | Assert(backendId == InvalidBackendId); |
148 | 8 | if (forkNumber != MAIN_FORKNUM) |
149 | 8 | path = psprintf("global/%u_%s", |
150 | 8 | relNode, forkNames[forkNumber]); |
151 | 0 | else |
152 | 0 | path = psprintf("global/%u", relNode); |
153 | 8 | } |
154 | 4.02k | else if (spcNode == DEFAULTTABLESPACE_OID) |
155 | 4.02k | { |
156 | | /* The default tablespace is {datadir}/base */ |
157 | 4.02k | if (backendId == InvalidBackendId) |
158 | 3.22k | { |
159 | 3.22k | if (forkNumber != MAIN_FORKNUM) |
160 | 846 | path = psprintf("base/%u/%u_%s", |
161 | 846 | dbNode, relNode, |
162 | 846 | forkNames[forkNumber]); |
163 | 2.37k | else |
164 | 2.37k | path = psprintf("base/%u/%u", |
165 | 2.37k | dbNode, relNode); |
166 | 3.22k | } |
167 | 796 | else |
168 | 796 | { |
169 | 796 | if (forkNumber != MAIN_FORKNUM) |
170 | 491 | path = psprintf("base/%u/t%d_%u_%s", |
171 | 491 | dbNode, backendId, relNode, |
172 | 491 | forkNames[forkNumber]); |
173 | 305 | else |
174 | 305 | path = psprintf("base/%u/t%d_%u", |
175 | 305 | dbNode, backendId, relNode); |
176 | 796 | } |
177 | 4.02k | } |
178 | 0 | else |
179 | 0 | { |
180 | | /* All other tablespaces are accessed via symlinks */ |
181 | 0 | if (backendId == InvalidBackendId) |
182 | 0 | { |
183 | 0 | if (forkNumber != MAIN_FORKNUM) |
184 | 0 | path = psprintf("pg_tblspc/%u/%s/%u/%u_%s", |
185 | 0 | spcNode, TABLESPACE_VERSION_DIRECTORY, |
186 | 0 | dbNode, relNode, |
187 | 0 | forkNames[forkNumber]); |
188 | 0 | else |
189 | 0 | path = psprintf("pg_tblspc/%u/%s/%u/%u", |
190 | 0 | spcNode, TABLESPACE_VERSION_DIRECTORY, |
191 | 0 | dbNode, relNode); |
192 | 0 | } |
193 | 0 | else |
194 | 0 | { |
195 | 0 | if (forkNumber != MAIN_FORKNUM) |
196 | 0 | path = psprintf("pg_tblspc/%u/%s/%u/t%d_%u_%s", |
197 | 0 | spcNode, TABLESPACE_VERSION_DIRECTORY, |
198 | 0 | dbNode, backendId, relNode, |
199 | 0 | forkNames[forkNumber]); |
200 | 0 | else |
201 | 0 | path = psprintf("pg_tblspc/%u/%s/%u/t%d_%u", |
202 | 0 | spcNode, TABLESPACE_VERSION_DIRECTORY, |
203 | 0 | dbNode, backendId, relNode); |
204 | 0 | } |
205 | 0 | } |
206 | 4.02k | return path; |
207 | 4.02k | } |