Header And Logo

PostgreSQL
| The world's most advanced open source database.

relpath.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  * relpath.c
00003  *      Shared frontend/backend code to find out pathnames of relation files
00004  *
00005  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00006  * Portions Copyright (c) 1994, Regents of the University of California
00007  *
00008  * IDENTIFICATION
00009  *    src/common/relpath.c
00010  *
00011  *-------------------------------------------------------------------------
00012  */
00013 #ifndef FRONTEND
00014 #include "postgres.h"
00015 #else
00016 #include "postgres_fe.h"
00017 #endif
00018 
00019 #include "catalog/pg_tablespace.h"
00020 #include "common/relpath.h"
00021 #include "storage/backendid.h"
00022 
00023 #define FORKNAMECHARS   4       /* max chars for a fork name */
00024 
00025 /*
00026  * Lookup table of fork name by fork number.
00027  *
00028  * If you add a new entry, remember to update the errhint below, and the
00029  * documentation for pg_relation_size(). Also keep FORKNAMECHARS above
00030  * up-to-date.
00031  */
00032 const char *forkNames[] = {
00033     "main",                     /* MAIN_FORKNUM */
00034     "fsm",                      /* FSM_FORKNUM */
00035     "vm",                       /* VISIBILITYMAP_FORKNUM */
00036     "init"                      /* INIT_FORKNUM */
00037 };
00038 
00039 /*
00040  * forkname_chars
00041  *      We use this to figure out whether a filename could be a relation
00042  *      fork (as opposed to an oddly named stray file that somehow ended
00043  *      up in the database directory).  If the passed string begins with
00044  *      a fork name (other than the main fork name), we return its length,
00045  *      and set *fork (if not NULL) to the fork number.  If not, we return 0.
00046  *
00047  * Note that the present coding assumes that there are no fork names which
00048  * are prefixes of other fork names.
00049  */
00050 int
00051 forkname_chars(const char *str, ForkNumber *fork)
00052 {
00053     ForkNumber  forkNum;
00054 
00055     for (forkNum = 1; forkNum <= MAX_FORKNUM; forkNum++)
00056     {
00057         int         len = strlen(forkNames[forkNum]);
00058 
00059         if (strncmp(forkNames[forkNum], str, len) == 0)
00060         {
00061             if (fork)
00062                 *fork = forkNum;
00063             return len;
00064         }
00065     }
00066     return 0;
00067 }
00068 
00069 /*
00070  * relpathbackend - construct path to a relation's file
00071  *
00072  * Result is a palloc'd string.
00073  */
00074 char *
00075 relpathbackend(RelFileNode rnode, BackendId backend, ForkNumber forknum)
00076 {
00077     int         pathlen;
00078     char       *path;
00079 
00080     if (rnode.spcNode == GLOBALTABLESPACE_OID)
00081     {
00082         /* Shared system relations live in {datadir}/global */
00083         Assert(rnode.dbNode == 0);
00084         Assert(backend == InvalidBackendId);
00085         pathlen = 7 + OIDCHARS + 1 + FORKNAMECHARS + 1;
00086         path = (char *) palloc(pathlen);
00087         if (forknum != MAIN_FORKNUM)
00088             snprintf(path, pathlen, "global/%u_%s",
00089                      rnode.relNode, forkNames[forknum]);
00090         else
00091             snprintf(path, pathlen, "global/%u", rnode.relNode);
00092     }
00093     else if (rnode.spcNode == DEFAULTTABLESPACE_OID)
00094     {
00095         /* The default tablespace is {datadir}/base */
00096         if (backend == InvalidBackendId)
00097         {
00098             pathlen = 5 + OIDCHARS + 1 + OIDCHARS + 1 + FORKNAMECHARS + 1;
00099             path = (char *) palloc(pathlen);
00100             if (forknum != MAIN_FORKNUM)
00101                 snprintf(path, pathlen, "base/%u/%u_%s",
00102                          rnode.dbNode, rnode.relNode,
00103                          forkNames[forknum]);
00104             else
00105                 snprintf(path, pathlen, "base/%u/%u",
00106                          rnode.dbNode, rnode.relNode);
00107         }
00108         else
00109         {
00110             /* OIDCHARS will suffice for an integer, too */
00111             pathlen = 5 + OIDCHARS + 2 + OIDCHARS + 1 + OIDCHARS + 1
00112                 + FORKNAMECHARS + 1;
00113             path = (char *) palloc(pathlen);
00114             if (forknum != MAIN_FORKNUM)
00115                 snprintf(path, pathlen, "base/%u/t%d_%u_%s",
00116                          rnode.dbNode, backend, rnode.relNode,
00117                          forkNames[forknum]);
00118             else
00119                 snprintf(path, pathlen, "base/%u/t%d_%u",
00120                          rnode.dbNode, backend, rnode.relNode);
00121         }
00122     }
00123     else
00124     {
00125         /* All other tablespaces are accessed via symlinks */
00126         if (backend == InvalidBackendId)
00127         {
00128             pathlen = 9 + 1 + OIDCHARS + 1
00129                 + strlen(TABLESPACE_VERSION_DIRECTORY) + 1 + OIDCHARS + 1
00130                 + OIDCHARS + 1 + FORKNAMECHARS + 1;
00131             path = (char *) palloc(pathlen);
00132             if (forknum != MAIN_FORKNUM)
00133                 snprintf(path, pathlen, "pg_tblspc/%u/%s/%u/%u_%s",
00134                          rnode.spcNode, TABLESPACE_VERSION_DIRECTORY,
00135                          rnode.dbNode, rnode.relNode,
00136                          forkNames[forknum]);
00137             else
00138                 snprintf(path, pathlen, "pg_tblspc/%u/%s/%u/%u",
00139                          rnode.spcNode, TABLESPACE_VERSION_DIRECTORY,
00140                          rnode.dbNode, rnode.relNode);
00141         }
00142         else
00143         {
00144             /* OIDCHARS will suffice for an integer, too */
00145             pathlen = 9 + 1 + OIDCHARS + 1
00146                 + strlen(TABLESPACE_VERSION_DIRECTORY) + 1 + OIDCHARS + 2
00147                 + OIDCHARS + 1 + OIDCHARS + 1 + FORKNAMECHARS + 1;
00148             path = (char *) palloc(pathlen);
00149             if (forknum != MAIN_FORKNUM)
00150                 snprintf(path, pathlen, "pg_tblspc/%u/%s/%u/t%d_%u_%s",
00151                          rnode.spcNode, TABLESPACE_VERSION_DIRECTORY,
00152                          rnode.dbNode, backend, rnode.relNode,
00153                          forkNames[forknum]);
00154             else
00155                 snprintf(path, pathlen, "pg_tblspc/%u/%s/%u/t%d_%u",
00156                          rnode.spcNode, TABLESPACE_VERSION_DIRECTORY,
00157                          rnode.dbNode, backend, rnode.relNode);
00158         }
00159     }
00160     return path;
00161 }
00162