LCOV - differential code coverage report
Current view: top level - src/bin/pg_upgrade - relfilenumber.c (source / functions) Coverage Total Hit UNC UIC GIC GNC
Current: Differential Code Coverage HEAD vs 15 Lines: 68.3 % 82 56 5 21 55 1
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 4 4 4
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*
       2                 :  *  relfilenumber.c
       3                 :  *
       4                 :  *  relfilenumber functions
       5                 :  *
       6                 :  *  Copyright (c) 2010-2023, PostgreSQL Global Development Group
       7                 :  *  src/bin/pg_upgrade/relfilenumber.c
       8                 :  */
       9                 : 
      10                 : #include "postgres_fe.h"
      11                 : 
      12                 : #include <sys/stat.h>
      13                 : 
      14                 : #include "access/transam.h"
      15                 : #include "catalog/pg_class_d.h"
      16                 : #include "pg_upgrade.h"
      17                 : 
      18                 : static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace);
      19                 : static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit);
      20                 : 
      21                 : 
      22                 : /*
      23                 :  * transfer_all_new_tablespaces()
      24                 :  *
      25                 :  * Responsible for upgrading all database. invokes routines to generate mappings and then
      26                 :  * physically link the databases.
      27                 :  */
      28                 : void
      29 GIC           1 : transfer_all_new_tablespaces(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
      30                 :                              char *old_pgdata, char *new_pgdata)
      31                 : {
      32               1 :     switch (user_opts.transfer_mode)
      33                 :     {
      34 UIC           0 :         case TRANSFER_MODE_CLONE:
      35               0 :             prep_status_progress("Cloning user relation files");
      36               0 :             break;
      37 GIC           1 :         case TRANSFER_MODE_COPY:
      38               1 :             prep_status_progress("Copying user relation files");
      39               1 :             break;
      40 UIC           0 :         case TRANSFER_MODE_LINK:
      41               0 :             prep_status_progress("Linking user relation files");
      42               0 :             break;
      43                 :     }
      44                 : 
      45                 :     /*
      46                 :      * Transferring files by tablespace is tricky because a single database
      47                 :      * can use multiple tablespaces.  For non-parallel mode, we just pass a
      48                 :      * NULL tablespace path, which matches all tablespaces.  In parallel mode,
      49                 :      * we pass the default tablespace and all user-created tablespaces and let
      50                 :      * those operations happen in parallel.
      51                 :      */
      52 GIC           1 :     if (user_opts.jobs <= 1)
      53               1 :         parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
      54                 :                                       new_pgdata, NULL);
      55                 :     else
      56                 :     {
      57                 :         int         tblnum;
      58                 : 
      59                 :         /* transfer default tablespace */
      60 UIC           0 :         parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
      61                 :                                       new_pgdata, old_pgdata);
      62                 : 
      63               0 :         for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
      64               0 :             parallel_transfer_all_new_dbs(old_db_arr,
      65                 :                                           new_db_arr,
      66                 :                                           old_pgdata,
      67                 :                                           new_pgdata,
      68               0 :                                           os_info.old_tablespaces[tblnum]);
      69                 :         /* reap all children */
      70               0 :         while (reap_child(true) == true)
      71                 :             ;
      72                 :     }
      73                 : 
      74 GIC           1 :     end_progress_output();
      75               1 :     check_ok();
      76               1 : }
      77                 : 
      78                 : 
      79                 : /*
      80                 :  * transfer_all_new_dbs()
      81                 :  *
      82                 :  * Responsible for upgrading all database. invokes routines to generate mappings and then
      83                 :  * physically link the databases.
      84                 :  */
      85                 : void
      86               1 : transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
      87                 :                      char *old_pgdata, char *new_pgdata, char *old_tablespace)
      88                 : {
      89                 :     int         old_dbnum,
      90                 :                 new_dbnum;
      91                 : 
      92                 :     /* Scan the old cluster databases and transfer their files */
      93               1 :     for (old_dbnum = new_dbnum = 0;
      94               7 :          old_dbnum < old_db_arr->ndbs;
      95               6 :          old_dbnum++, new_dbnum++)
      96                 :     {
      97               6 :         DbInfo     *old_db = &old_db_arr->dbs[old_dbnum],
      98               6 :                    *new_db = NULL;
      99                 :         FileNameMap *mappings;
     100                 :         int         n_maps;
     101                 : 
     102                 :         /*
     103                 :          * Advance past any databases that exist in the new cluster but not in
     104                 :          * the old, e.g. "postgres".  (The user might have removed the
     105                 :          * 'postgres' database from the old cluster.)
     106                 :          */
     107               6 :         for (; new_dbnum < new_db_arr->ndbs; new_dbnum++)
     108                 :         {
     109               6 :             new_db = &new_db_arr->dbs[new_dbnum];
     110               6 :             if (strcmp(old_db->db_name, new_db->db_name) == 0)
     111               6 :                 break;
     112                 :         }
     113                 : 
     114               6 :         if (new_dbnum >= new_db_arr->ndbs)
     115 UNC           0 :             pg_fatal("old database \"%s\" not found in the new cluster",
     116                 :                      old_db->db_name);
     117                 : 
     118 GIC           6 :         mappings = gen_db_file_maps(old_db, new_db, &n_maps, old_pgdata,
     119                 :                                     new_pgdata);
     120               6 :         if (n_maps)
     121                 :         {
     122               6 :             transfer_single_new_db(mappings, n_maps, old_tablespace);
     123                 :         }
     124                 :         /* We allocate something even for n_maps == 0 */
     125               6 :         pg_free(mappings);
     126                 :     }
     127               1 : }
     128                 : 
     129                 : /*
     130                 :  * transfer_single_new_db()
     131                 :  *
     132                 :  * create links for mappings stored in "maps" array.
     133                 :  */
     134                 : static void
     135               6 : transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace)
     136                 : {
     137                 :     int         mapnum;
     138               6 :     bool        vm_must_add_frozenbit = false;
     139                 : 
     140                 :     /*
     141                 :      * Do we need to rewrite visibilitymap?
     142                 :      */
     143               6 :     if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_FROZEN_BIT_CAT_VER &&
     144 UIC           0 :         new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER)
     145               0 :         vm_must_add_frozenbit = true;
     146                 : 
     147 GIC        1264 :     for (mapnum = 0; mapnum < size; mapnum++)
     148                 :     {
     149            1258 :         if (old_tablespace == NULL ||
     150 UIC           0 :             strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0)
     151                 :         {
     152                 :             /* transfer primary file */
     153 GIC        1258 :             transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit);
     154                 : 
     155                 :             /*
     156                 :              * Copy/link any fsm and vm files, if they exist
     157                 :              */
     158            1258 :             transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit);
     159            1258 :             transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit);
     160                 :         }
     161                 :     }
     162               6 : }
     163                 : 
     164                 : 
     165                 : /*
     166                 :  * transfer_relfile()
     167                 :  *
     168                 :  * Copy or link file from old cluster to new one.  If vm_must_add_frozenbit
     169                 :  * is true, visibility map forks are converted and rewritten, even in link
     170                 :  * mode.
     171                 :  */
     172                 : static void
     173            3774 : transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit)
     174                 : {
     175                 :     char        old_file[MAXPGPATH];
     176                 :     char        new_file[MAXPGPATH];
     177                 :     int         segno;
     178                 :     char        extent_suffix[65];
     179                 :     struct stat statbuf;
     180                 : 
     181                 :     /*
     182                 :      * Now copy/link any related segments as well. Remember, PG breaks large
     183                 :      * files into 1GB segments, the first segment has no extension, subsequent
     184                 :      * segments are named relfilenumber.1, relfilenumber.2, relfilenumber.3.
     185                 :      */
     186            5335 :     for (segno = 0;; segno++)
     187                 :     {
     188            5335 :         if (segno == 0)
     189            3774 :             extent_suffix[0] = '\0';
     190                 :         else
     191            1561 :             snprintf(extent_suffix, sizeof(extent_suffix), ".%d", segno);
     192                 : 
     193            5335 :         snprintf(old_file, sizeof(old_file), "%s%s/%u/%u%s%s",
     194                 :                  map->old_tablespace,
     195                 :                  map->old_tablespace_suffix,
     196                 :                  map->db_oid,
     197                 :                  map->relfilenumber,
     198                 :                  type_suffix,
     199                 :                  extent_suffix);
     200            5335 :         snprintf(new_file, sizeof(new_file), "%s%s/%u/%u%s%s",
     201                 :                  map->new_tablespace,
     202                 :                  map->new_tablespace_suffix,
     203                 :                  map->db_oid,
     204                 :                  map->relfilenumber,
     205                 :                  type_suffix,
     206                 :                  extent_suffix);
     207                 : 
     208                 :         /* Is it an extent, fsm, or vm file? */
     209            5335 :         if (type_suffix[0] != '\0' || segno != 0)
     210                 :         {
     211                 :             /* Did file open fail? */
     212            4077 :             if (stat(old_file, &statbuf) != 0)
     213                 :             {
     214                 :                 /* File does not exist?  That's OK, just return */
     215            3773 :                 if (errno == ENOENT)
     216            3773 :                     return;
     217                 :                 else
     218 UNC           0 :                     pg_fatal("error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %s",
     219                 :                              map->nspname, map->relname, old_file, new_file,
     220 UIC           0 :                              strerror(errno));
     221                 :             }
     222                 : 
     223                 :             /* If file is empty, just return */
     224 GIC         304 :             if (statbuf.st_size == 0)
     225               1 :                 return;
     226                 :         }
     227                 : 
     228            1561 :         unlink(new_file);
     229                 : 
     230                 :         /* Copying files might take some time, so give feedback. */
     231            1561 :         pg_log(PG_STATUS, "%s", old_file);
     232                 : 
     233            1561 :         if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0)
     234                 :         {
     235                 :             /* Need to rewrite visibility map format */
     236 UNC           0 :             pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"",
     237                 :                    old_file, new_file);
     238 UIC           0 :             rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname);
     239                 :         }
     240                 :         else
     241 GIC        1561 :             switch (user_opts.transfer_mode)
     242                 :             {
     243 UIC           0 :                 case TRANSFER_MODE_CLONE:
     244 UNC           0 :                     pg_log(PG_VERBOSE, "cloning \"%s\" to \"%s\"",
     245                 :                            old_file, new_file);
     246 UIC           0 :                     cloneFile(old_file, new_file, map->nspname, map->relname);
     247               0 :                     break;
     248 GIC        1561 :                 case TRANSFER_MODE_COPY:
     249 GNC        1561 :                     pg_log(PG_VERBOSE, "copying \"%s\" to \"%s\"",
     250                 :                            old_file, new_file);
     251 GIC        1561 :                     copyFile(old_file, new_file, map->nspname, map->relname);
     252            1561 :                     break;
     253 UIC           0 :                 case TRANSFER_MODE_LINK:
     254 UNC           0 :                     pg_log(PG_VERBOSE, "linking \"%s\" to \"%s\"",
     255                 :                            old_file, new_file);
     256 UIC           0 :                     linkFile(old_file, new_file, map->nspname, map->relname);
     257                 :             }
     258                 :     }
     259                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a