LCOV - code coverage report
Current view: top level - src/common - relpath.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 25 45 55.6 %
Date: 2017-09-29 13:40:31 Functions: 2 4 50.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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-2017, 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/catalog.h"
      22             : #include "catalog/pg_tablespace.h"
      23             : #include "common/relpath.h"
      24             : #include "storage/backendid.h"
      25             : 
      26             : 
      27             : /*
      28             :  * Lookup table of fork name by fork number.
      29             :  *
      30             :  * If you add a new entry, remember to update the errhint in
      31             :  * forkname_to_number() below, and update the SGML documentation for
      32             :  * pg_relation_size().
      33             :  */
      34             : const char *const forkNames[] = {
      35             :     "main",                       /* MAIN_FORKNUM */
      36             :     "fsm",                        /* FSM_FORKNUM */
      37             :     "vm",                     /* VISIBILITYMAP_FORKNUM */
      38             :     "init"                        /* INIT_FORKNUM */
      39             : };
      40             : 
      41             : /*
      42             :  * forkname_to_number - look up fork number by name
      43             :  *
      44             :  * In backend, we throw an error for no match; in frontend, we just
      45             :  * return InvalidForkNumber.
      46             :  */
      47             : ForkNumber
      48           0 : forkname_to_number(const char *forkName)
      49             : {
      50             :     ForkNumber  forkNum;
      51             : 
      52           0 :     for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
      53           0 :         if (strcmp(forkNames[forkNum], forkName) == 0)
      54           0 :             return forkNum;
      55             : 
      56             : #ifndef FRONTEND
      57           0 :     ereport(ERROR,
      58             :             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
      59             :              errmsg("invalid fork name"),
      60             :              errhint("Valid fork names are \"main\", \"fsm\", "
      61             :                      "\"vm\", and \"init\".")));
      62             : #endif
      63             : 
      64             :     return InvalidForkNumber;
      65             : }
      66             : 
      67             : /*
      68             :  * forkname_chars
      69             :  *      We use this to figure out whether a filename could be a relation
      70             :  *      fork (as opposed to an oddly named stray file that somehow ended
      71             :  *      up in the database directory).  If the passed string begins with
      72             :  *      a fork name (other than the main fork name), we return its length,
      73             :  *      and set *fork (if not NULL) to the fork number.  If not, we return 0.
      74             :  *
      75             :  * Note that the present coding assumes that there are no fork names which
      76             :  * are prefixes of other fork names.
      77             :  */
      78             : int
      79           0 : forkname_chars(const char *str, ForkNumber *fork)
      80             : {
      81             :     ForkNumber  forkNum;
      82             : 
      83           0 :     for (forkNum = 1; forkNum <= MAX_FORKNUM; forkNum++)
      84             :     {
      85           0 :         int         len = strlen(forkNames[forkNum]);
      86             : 
      87           0 :         if (strncmp(forkNames[forkNum], str, len) == 0)
      88             :         {
      89           0 :             if (fork)
      90           0 :                 *fork = forkNum;
      91           0 :             return len;
      92             :         }
      93             :     }
      94           0 :     if (fork)
      95           0 :         *fork = InvalidForkNumber;
      96           0 :     return 0;
      97             : }
      98             : 
      99             : 
     100             : /*
     101             :  * GetDatabasePath - construct path to a database directory
     102             :  *
     103             :  * Result is a palloc'd string.
     104             :  *
     105             :  * XXX this must agree with GetRelationPath()!
     106             :  */
     107             : char *
     108        4759 : GetDatabasePath(Oid dbNode, Oid spcNode)
     109             : {
     110        4759 :     if (spcNode == GLOBALTABLESPACE_OID)
     111             :     {
     112             :         /* Shared system relations live in {datadir}/global */
     113           0 :         Assert(dbNode == 0);
     114           0 :         return pstrdup("global");
     115             :     }
     116        4759 :     else if (spcNode == DEFAULTTABLESPACE_OID)
     117             :     {
     118             :         /* The default tablespace is {datadir}/base */
     119        4740 :         return psprintf("base/%u", dbNode);
     120             :     }
     121             :     else
     122             :     {
     123             :         /* All other tablespaces are accessed via symlinks */
     124          19 :         return psprintf("pg_tblspc/%u/%s/%u",
     125             :                         spcNode, TABLESPACE_VERSION_DIRECTORY, dbNode);
     126             :     }
     127             : }
     128             : 
     129             : /*
     130             :  * GetRelationPath - construct path to a relation's file
     131             :  *
     132             :  * Result is a palloc'd string.
     133             :  *
     134             :  * Note: ideally, backendId would be declared as type BackendId, but relpath.h
     135             :  * would have to include a backend-only header to do that; doesn't seem worth
     136             :  * the trouble considering BackendId is just int anyway.
     137             :  */
     138             : char *
     139       45642 : GetRelationPath(Oid dbNode, Oid spcNode, Oid relNode,
     140             :                 int backendId, ForkNumber forkNumber)
     141             : {
     142             :     char       *path;
     143             : 
     144       45642 :     if (spcNode == GLOBALTABLESPACE_OID)
     145             :     {
     146             :         /* Shared system relations live in {datadir}/global */
     147         931 :         Assert(dbNode == 0);
     148         931 :         Assert(backendId == InvalidBackendId);
     149         931 :         if (forkNumber != MAIN_FORKNUM)
     150         394 :             path = psprintf("global/%u_%s",
     151             :                             relNode, forkNames[forkNumber]);
     152             :         else
     153         537 :             path = psprintf("global/%u", relNode);
     154             :     }
     155       44711 :     else if (spcNode == DEFAULTTABLESPACE_OID)
     156             :     {
     157             :         /* The default tablespace is {datadir}/base */
     158       44502 :         if (backendId == InvalidBackendId)
     159             :         {
     160       39322 :             if (forkNumber != MAIN_FORKNUM)
     161       17419 :                 path = psprintf("base/%u/%u_%s",
     162             :                                 dbNode, relNode,
     163             :                                 forkNames[forkNumber]);
     164             :             else
     165       21903 :                 path = psprintf("base/%u/%u",
     166             :                                 dbNode, relNode);
     167             :         }
     168             :         else
     169             :         {
     170        5180 :             if (forkNumber != MAIN_FORKNUM)
     171        2445 :                 path = psprintf("base/%u/t%d_%u_%s",
     172             :                                 dbNode, backendId, relNode,
     173             :                                 forkNames[forkNumber]);
     174             :             else
     175        2735 :                 path = psprintf("base/%u/t%d_%u",
     176             :                                 dbNode, backendId, relNode);
     177             :         }
     178             :     }
     179             :     else
     180             :     {
     181             :         /* All other tablespaces are accessed via symlinks */
     182         209 :         if (backendId == InvalidBackendId)
     183             :         {
     184         209 :             if (forkNumber != MAIN_FORKNUM)
     185          91 :                 path = psprintf("pg_tblspc/%u/%s/%u/%u_%s",
     186             :                                 spcNode, TABLESPACE_VERSION_DIRECTORY,
     187             :                                 dbNode, relNode,
     188             :                                 forkNames[forkNumber]);
     189             :             else
     190         118 :                 path = psprintf("pg_tblspc/%u/%s/%u/%u",
     191             :                                 spcNode, TABLESPACE_VERSION_DIRECTORY,
     192             :                                 dbNode, relNode);
     193             :         }
     194             :         else
     195             :         {
     196           0 :             if (forkNumber != MAIN_FORKNUM)
     197           0 :                 path = psprintf("pg_tblspc/%u/%s/%u/t%d_%u_%s",
     198             :                                 spcNode, TABLESPACE_VERSION_DIRECTORY,
     199             :                                 dbNode, backendId, relNode,
     200             :                                 forkNames[forkNumber]);
     201             :             else
     202           0 :                 path = psprintf("pg_tblspc/%u/%s/%u/t%d_%u",
     203             :                                 spcNode, TABLESPACE_VERSION_DIRECTORY,
     204             :                                 dbNode, backendId, relNode);
     205             :         }
     206             :     }
     207       45642 :     return path;
     208             : }

Generated by: LCOV version 1.11