summaryrefslogtreecommitdiff
path: root/src/common/relpath.c
diff options
context:
space:
mode:
authorPavan Deolasee2015-05-05 09:19:18 +0000
committerPavan Deolasee2015-05-05 09:19:18 +0000
commit73fa25c67cbfa24c03e28c96bf356f2592671730 (patch)
tree10ded7e26abd78d93658cb72fc5cb9d4672eff2a /src/common/relpath.c
parentda4d108859bcd7a308ca75aba54281e32968822c (diff)
parent4a9ab6d8619817f9e3989c99b65140e19041dab7 (diff)
Merge branch 'XL_MASTER_MERGE_9_4' into XL_NEW_MASTER
Conflicts: src/test/regress/expected/aggregates.out src/test/regress/expected/create_index.out src/test/regress/expected/inherit.out src/test/regress/expected/join.out src/test/regress/expected/window.out src/test/regress/expected/with.out
Diffstat (limited to 'src/common/relpath.c')
-rw-r--r--src/common/relpath.c251
1 files changed, 251 insertions, 0 deletions
diff --git a/src/common/relpath.c b/src/common/relpath.c
new file mode 100644
index 0000000000..e4c64f685d
--- /dev/null
+++ b/src/common/relpath.c
@@ -0,0 +1,251 @@
+/*-------------------------------------------------------------------------
+ * relpath.c
+ * Shared frontend/backend code to compute pathnames of relation files
+ *
+ * This module also contains some logic associated with fork names.
+ *
+ * Portions Copyright (c) 1996-2014, 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/catalog.h"
+#include "catalog/pg_tablespace.h"
+#include "common/relpath.h"
+#include "storage/backendid.h"
+
+#ifdef PGXC
+#include "pgxc/pgxc.h"
+#endif
+
+/*
+ * Lookup table of fork name by fork number.
+ *
+ * If you add a new entry, remember to update the errhint in
+ * forkname_to_number() below, and update the SGML documentation for
+ * pg_relation_size().
+ */
+const char *const forkNames[] = {
+ "main", /* MAIN_FORKNUM */
+ "fsm", /* FSM_FORKNUM */
+ "vm", /* VISIBILITYMAP_FORKNUM */
+ "init" /* INIT_FORKNUM */
+};
+
+/*
+ * forkname_to_number - look up fork number by name
+ *
+ * In backend, we throw an error for no match; in frontend, we just
+ * return InvalidForkNumber.
+ */
+ForkNumber
+forkname_to_number(const char *forkName)
+{
+ ForkNumber forkNum;
+
+ for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
+ if (strcmp(forkNames[forkNum], forkName) == 0)
+ return forkNum;
+
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid fork name"),
+ errhint("Valid fork names are \"main\", \"fsm\", "
+ "\"vm\", and \"init\".")));
+#endif
+
+ return InvalidForkNumber;
+}
+
+/*
+ * 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;
+ }
+ }
+ if (fork)
+ *fork = InvalidForkNumber;
+ return 0;
+}
+
+
+/*
+ * GetDatabasePath - construct path to a database directory
+ *
+ * Result is a palloc'd string.
+ *
+ * XXX this must agree with GetRelationPath()!
+ */
+char *
+GetDatabasePath(Oid dbNode, Oid spcNode)
+{
+ if (spcNode == GLOBALTABLESPACE_OID)
+ {
+ /* Shared system relations live in {datadir}/global */
+ Assert(dbNode == 0);
+ return pstrdup("global");
+ }
+ else if (spcNode == DEFAULTTABLESPACE_OID)
+ {
+ /* The default tablespace is {datadir}/base */
+ return psprintf("base/%u", dbNode);
+ }
+ else
+ {
+ /* All other tablespaces are accessed via symlinks */
+#ifdef PGXC
+ return psprintf("pg_tblspc/%u/%s_%s/%u",
+ spcNode, TABLESPACE_VERSION_DIRECTORY,
+ PGXCNodeName,
+ dbNode);
+#else
+ return psprintf("pg_tblspc/%u/%s/%u",
+ spcNode, TABLESPACE_VERSION_DIRECTORY, dbNode);
+#endif
+ }
+}
+
+/*
+ * GetRelationPath - construct path to a relation's file
+ *
+ * Result is a palloc'd string.
+ *
+ * Note: ideally, backendId would be declared as type BackendId, but relpath.h
+ * would have to include a backend-only header to do that; doesn't seem worth
+ * the trouble considering BackendId is just int anyway.
+ */
+char *
+GetRelationPath(Oid dbNode, Oid spcNode, Oid relNode,
+ int backendId, ForkNumber forkNumber)
+{
+ char *path;
+
+ if (spcNode == GLOBALTABLESPACE_OID)
+ {
+ /* Shared system relations live in {datadir}/global */
+ Assert(dbNode == 0);
+ Assert(backendId == InvalidBackendId);
+ if (forkNumber != MAIN_FORKNUM)
+ path = psprintf("global/%u_%s",
+ relNode, forkNames[forkNumber]);
+ else
+ path = psprintf("global/%u", relNode);
+ }
+ else if (spcNode == DEFAULTTABLESPACE_OID)
+ {
+ /* The default tablespace is {datadir}/base */
+ if (backendId == InvalidBackendId)
+ {
+ if (forkNumber != MAIN_FORKNUM)
+ path = psprintf("base/%u/%u_%s",
+ dbNode, relNode,
+ forkNames[forkNumber]);
+ else
+ path = psprintf("base/%u/%u",
+ dbNode, relNode);
+ }
+ else
+ {
+ if (forkNumber != MAIN_FORKNUM)
+ path = psprintf("base/%u/t%d_%u_%s",
+ dbNode, backendId, relNode,
+ forkNames[forkNumber]);
+ else
+ path = psprintf("base/%u/t%d_%u",
+ dbNode, backendId, relNode);
+ }
+ }
+ else
+ {
+ /* All other tablespaces are accessed via symlinks */
+ if (backendId == InvalidBackendId)
+ {
+ if (forkNumber != MAIN_FORKNUM)
+#ifdef PGXC
+ path = psprintf("pg_tblspc/%u/%s_%s/%u/%u_%s",
+#else
+ path = psprintf("pg_tblspc/%u/%s/%u/%u_%s",
+#endif
+ spcNode, TABLESPACE_VERSION_DIRECTORY,
+#ifdef PGXC
+ /* Postgres-XC tablespaces include node name */
+ PGXCNodeName,
+#endif
+ dbNode,
+ relNode,
+ forkNames[forkNumber]);
+ else
+#ifdef PGXC
+ path = psprintf("pg_tblspc/%u/%s_%s/%u/%u",
+#else
+ path = psprintf("pg_tblspc/%u/%s/%u/%u",
+#endif
+ spcNode, TABLESPACE_VERSION_DIRECTORY,
+#ifdef PGXC
+ /* Postgres-XC tablespaces include node name */
+ PGXCNodeName,
+#endif
+ dbNode, relNode);
+ }
+ else
+ {
+ if (forkNumber != MAIN_FORKNUM)
+#ifdef PGXC
+ path = psprintf("pg_tblspc/%u/%s_%s/%u/t%d_%u_%s",
+#else
+ path = psprintf("pg_tblspc/%u/%s/%u/t%d_%u_%s",
+#endif
+ spcNode, TABLESPACE_VERSION_DIRECTORY,
+#ifdef PGXC
+ /* Postgres-XC tablespaces include node name */
+ PGXCNodeName,
+#endif
+ dbNode, backendId, relNode,
+ forkNames[forkNumber]);
+ else
+#ifdef PGXC
+ path = psprintf("pg_tblspc/%u/%s_%s/%u/t%d_%u",
+#else
+ path = psprintf("pg_tblspc/%u/%s/%u/t%d_%u",
+#endif
+ spcNode, TABLESPACE_VERSION_DIRECTORY,
+#ifdef PGXC
+ /* Postgres-XC tablespaces include node name */
+ PGXCNodeName,
+#endif
+ dbNode, backendId, relNode);
+ }
+ }
+ return path;
+}