PostgreSQL Source Code  git master
filemap.c File Reference
#include "postgres_fe.h"
#include <sys/stat.h>
#include <unistd.h>
#include "catalog/pg_tablespace_d.h"
#include "common/string.h"
#include "datapagemap.h"
#include "filemap.h"
#include "pg_rewind.h"
#include "storage/fd.h"
Include dependency graph for filemap.c:

Go to the source code of this file.

Data Structures

struct  exclude_list_item
 

Functions

static bool isRelDataFile (const char *path)
 
static char * datasegpath (RelFileNode rnode, ForkNumber forknum, BlockNumber segno)
 
static int path_cmp (const void *a, const void *b)
 
static int final_filemap_cmp (const void *a, const void *b)
 
static void filemap_list_to_array (filemap_t *map)
 
static bool check_file_excluded (const char *path, bool is_source)
 
void filemap_create (void)
 
void process_source_file (const char *path, file_type_t type, size_t newsize, const char *link_target)
 
void process_target_file (const char *path, file_type_t type, size_t oldsize, const char *link_target)
 
void process_block_change (ForkNumber forknum, RelFileNode rnode, BlockNumber blkno)
 
void filemap_finalize (void)
 
static const char * action_to_str (file_action_t action)
 
void calculate_totals (void)
 
void print_filemap (void)
 

Variables

filemap_tfilemap = NULL
 
static const char * excludeDirContents []
 
static const struct exclude_list_item excludeFiles []
 

Function Documentation

◆ action_to_str()

static const char* action_to_str ( file_action_t  action)
static

Definition at line 595 of file filemap.c.

References FILE_ACTION_COPY, FILE_ACTION_COPY_TAIL, FILE_ACTION_CREATE, FILE_ACTION_NONE, FILE_ACTION_REMOVE, and FILE_ACTION_TRUNCATE.

Referenced by print_filemap().

596 {
597  switch (action)
598  {
599  case FILE_ACTION_NONE:
600  return "NONE";
601  case FILE_ACTION_COPY:
602  return "COPY";
604  return "TRUNCATE";
606  return "COPY_TAIL";
607  case FILE_ACTION_CREATE:
608  return "CREATE";
609  case FILE_ACTION_REMOVE:
610  return "REMOVE";
611 
612  default:
613  return "unknown";
614  }
615 }

◆ calculate_totals()

void calculate_totals ( void  )

Definition at line 621 of file filemap.c.

References file_entry_t::action, filemap_t::array, datapagemap::bitmapsize, datapagemap_iterate(), datapagemap_next(), filemap_t::fetch_size, FILE_ACTION_COPY, FILE_ACTION_COPY_TAIL, FILE_TYPE_REGULAR, filemap, i, filemap_t::narray, file_entry_t::newsize, file_entry_t::oldsize, file_entry_t::pagemap, pg_free(), filemap_t::total_size, and file_entry_t::type.

Referenced by main().

622 {
623  file_entry_t *entry;
624  int i;
625  filemap_t *map = filemap;
626 
627  map->total_size = 0;
628  map->fetch_size = 0;
629 
630  for (i = 0; i < map->narray; i++)
631  {
632  entry = map->array[i];
633 
634  if (entry->type != FILE_TYPE_REGULAR)
635  continue;
636 
637  map->total_size += entry->newsize;
638 
639  if (entry->action == FILE_ACTION_COPY)
640  {
641  map->fetch_size += entry->newsize;
642  continue;
643  }
644 
645  if (entry->action == FILE_ACTION_COPY_TAIL)
646  map->fetch_size += (entry->newsize - entry->oldsize);
647 
648  if (entry->pagemap.bitmapsize > 0)
649  {
651  BlockNumber blk;
652 
653  iter = datapagemap_iterate(&entry->pagemap);
654  while (datapagemap_next(iter, &blk))
655  map->fetch_size += BLCKSZ;
656 
657  pg_free(iter);
658  }
659  }
660 }
file_entry_t ** array
Definition: filemap.h:78
size_t newsize
Definition: filemap.h:50
uint32 BlockNumber
Definition: block.h:31
datapagemap_t pagemap
Definition: filemap.h:53
int narray
Definition: filemap.h:79
uint64 fetch_size
Definition: filemap.h:86
file_type_t type
Definition: filemap.h:44
bool datapagemap_next(datapagemap_iterator_t *iter, BlockNumber *blkno)
Definition: datapagemap.c:87
file_action_t action
Definition: filemap.h:46
filemap_t * filemap
Definition: filemap.c:23
size_t oldsize
Definition: filemap.h:49
uint64 total_size
Definition: filemap.h:85
int bitmapsize
Definition: datapagemap.h:18
datapagemap_iterator_t * datapagemap_iterate(datapagemap_t *map)
Definition: datapagemap.c:75
void pg_free(void *ptr)
Definition: fe_memutils.c:105
int i
Definition: filemap.h:41

◆ check_file_excluded()

static bool check_file_excluded ( const char *  path,
bool  is_source 
)
static

Definition at line 502 of file filemap.c.

References excludeDirContents, filename, last_dir_separator(), exclude_list_item::match_prefix, MAXPGPATH, exclude_list_item::name, pg_log_debug, and snprintf.

Referenced by process_source_file().

503 {
504  char localpath[MAXPGPATH];
505  int excludeIdx;
506  const char *filename;
507 
508  /* check individual files... */
509  for (excludeIdx = 0; excludeFiles[excludeIdx].name != NULL; excludeIdx++)
510  {
511  int cmplen = strlen(excludeFiles[excludeIdx].name);
512 
513  filename = last_dir_separator(path);
514  if (filename == NULL)
515  filename = path;
516  else
517  filename++;
518 
519  if (!excludeFiles[excludeIdx].match_prefix)
520  cmplen++;
521  if (strncmp(filename, excludeFiles[excludeIdx].name, cmplen) == 0)
522  {
523  if (is_source)
524  pg_log_debug("entry \"%s\" excluded from source file list",
525  path);
526  else
527  pg_log_debug("entry \"%s\" excluded from target file list",
528  path);
529  return true;
530  }
531  }
532 
533  /*
534  * ... And check some directories. Note that this includes any contents
535  * within the directories themselves.
536  */
537  for (excludeIdx = 0; excludeDirContents[excludeIdx] != NULL; excludeIdx++)
538  {
539  snprintf(localpath, sizeof(localpath), "%s/",
540  excludeDirContents[excludeIdx]);
541  if (strstr(path, localpath) == path)
542  {
543  if (is_source)
544  pg_log_debug("entry \"%s\" excluded from source file list",
545  path);
546  else
547  pg_log_debug("entry \"%s\" excluded from target file list",
548  path);
549  return true;
550  }
551  }
552 
553  return false;
554 }
#define pg_log_debug(...)
Definition: logging.h:92
#define MAXPGPATH
static const struct exclude_list_item excludeFiles[]
Definition: filemap.c:96
char * last_dir_separator(const char *filename)
Definition: path.c:138
const char * name
Definition: encode.c:561
const char * name
Definition: basebackup.c:141
static char * filename
Definition: pg_dumpall.c:91
static const char * excludeDirContents[]
Definition: filemap.c:54
#define snprintf
Definition: port.h:215

◆ datasegpath()

static char * datasegpath ( RelFileNode  rnode,
ForkNumber  forknum,
BlockNumber  segno 
)
static

Definition at line 777 of file filemap.c.

References pfree(), psprintf(), and relpathperm.

Referenced by isRelDataFile(), and process_block_change().

778 {
779  char *path;
780  char *segpath;
781 
782  path = relpathperm(rnode, forknum);
783  if (segno > 0)
784  {
785  segpath = psprintf("%s.%u", path, segno);
786  pfree(path);
787  return segpath;
788  }
789  else
790  return path;
791 }
#define relpathperm(rnode, forknum)
Definition: relpath.h:83
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
void pfree(void *pointer)
Definition: mcxt.c:1057

◆ filemap_create()

void filemap_create ( void  )

Definition at line 135 of file filemap.c.

References filemap_t::array, Assert, filemap_t::first, filemap_t::last, filemap_t::narray, filemap_t::nlist, and pg_malloc().

Referenced by main().

136 {
137  filemap_t *map;
138 
139  map = pg_malloc(sizeof(filemap_t));
140  map->first = map->last = NULL;
141  map->nlist = 0;
142  map->array = NULL;
143  map->narray = 0;
144 
145  Assert(filemap == NULL);
146  filemap = map;
147 }
file_entry_t * first
Definition: filemap.h:67
file_entry_t ** array
Definition: filemap.h:78
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
int narray
Definition: filemap.h:79
int nlist
Definition: filemap.h:69
filemap_t * filemap
Definition: filemap.c:23
#define Assert(condition)
Definition: c.h:746
file_entry_t * last
Definition: filemap.h:68

◆ filemap_finalize()

void filemap_finalize ( void  )

Definition at line 585 of file filemap.c.

References filemap_t::array, filemap, filemap_list_to_array(), final_filemap_cmp(), filemap_t::narray, and qsort.

Referenced by main().

586 {
587  filemap_t *map = filemap;
588 
590  qsort(map->array, map->narray, sizeof(file_entry_t *),
592 }
static int final_filemap_cmp(const void *a, const void *b)
Definition: filemap.c:813
file_entry_t ** array
Definition: filemap.h:78
int narray
Definition: filemap.h:79
filemap_t * filemap
Definition: filemap.c:23
static void filemap_list_to_array(filemap_t *map)
Definition: filemap.c:561
Definition: filemap.h:41
#define qsort(a, b, c, d)
Definition: port.h:497

◆ filemap_list_to_array()

static void filemap_list_to_array ( filemap_t map)
static

Definition at line 561 of file filemap.c.

References filemap_t::array, Assert, filemap_t::first, filemap_t::last, filemap_t::narray, file_entry_t::next, next, filemap_t::nlist, and pg_realloc().

Referenced by filemap_finalize(), and process_target_file().

562 {
563  int narray;
564  file_entry_t *entry,
565  *next;
566 
567  map->array = (file_entry_t **)
568  pg_realloc(map->array,
569  (map->nlist + map->narray) * sizeof(file_entry_t *));
570 
571  narray = map->narray;
572  for (entry = map->first; entry != NULL; entry = next)
573  {
574  map->array[narray++] = entry;
575  next = entry->next;
576  entry->next = NULL;
577  }
578  Assert(narray == map->nlist + map->narray);
579  map->narray = narray;
580  map->nlist = 0;
581  map->first = map->last = NULL;
582 }
static int32 next
Definition: blutils.c:219
file_entry_t * first
Definition: filemap.h:67
file_entry_t ** array
Definition: filemap.h:78
int narray
Definition: filemap.h:79
int nlist
Definition: filemap.h:69
struct file_entry_t * next
Definition: filemap.h:58
void * pg_realloc(void *ptr, size_t size)
Definition: fe_memutils.c:65
#define Assert(condition)
Definition: c.h:746
file_entry_t * last
Definition: filemap.h:68
Definition: filemap.h:41

◆ final_filemap_cmp()

static int final_filemap_cmp ( const void *  a,
const void *  b 
)
static

Definition at line 813 of file filemap.c.

References file_entry_t::action, fa(), fb(), FILE_ACTION_REMOVE, and file_entry_t::path.

Referenced by filemap_finalize().

814 {
815  file_entry_t *fa = *((file_entry_t **) a);
816  file_entry_t *fb = *((file_entry_t **) b);
817 
818  if (fa->action > fb->action)
819  return 1;
820  if (fa->action < fb->action)
821  return -1;
822 
823  if (fa->action == FILE_ACTION_REMOVE)
824  return strcmp(fb->path, fa->path);
825  else
826  return strcmp(fa->path, fb->path);
827 }
static int fa(void)
Definition: preproc-init.c:85
static int fb(int x)
Definition: preproc-init.c:92
file_action_t action
Definition: filemap.h:46
char * path
Definition: filemap.h:43
Definition: filemap.h:41

◆ isRelDataFile()

static bool isRelDataFile ( const char *  path)
static

Definition at line 694 of file filemap.c.

References datasegpath(), RelFileNode::dbNode, InvalidOid, MAIN_FORKNUM, pfree(), RelFileNode::relNode, RelFileNode::spcNode, and TABLESPACE_VERSION_DIRECTORY.

Referenced by process_source_file(), and process_target_file().

695 {
696  RelFileNode rnode;
697  unsigned int segNo;
698  int nmatch;
699  bool matched;
700 
701  /*----
702  * Relation data files can be in one of the following directories:
703  *
704  * global/
705  * shared relations
706  *
707  * base/<db oid>/
708  * regular relations, default tablespace
709  *
710  * pg_tblspc/<tblspc oid>/<tblspc version>/
711  * within a non-default tablespace (the name of the directory
712  * depends on version)
713  *
714  * And the relation data files themselves have a filename like:
715  *
716  * <oid>.<segment number>
717  *
718  *----
719  */
720  rnode.spcNode = InvalidOid;
721  rnode.dbNode = InvalidOid;
722  rnode.relNode = InvalidOid;
723  segNo = 0;
724  matched = false;
725 
726  nmatch = sscanf(path, "global/%u.%u", &rnode.relNode, &segNo);
727  if (nmatch == 1 || nmatch == 2)
728  {
729  rnode.spcNode = GLOBALTABLESPACE_OID;
730  rnode.dbNode = 0;
731  matched = true;
732  }
733  else
734  {
735  nmatch = sscanf(path, "base/%u/%u.%u",
736  &rnode.dbNode, &rnode.relNode, &segNo);
737  if (nmatch == 2 || nmatch == 3)
738  {
739  rnode.spcNode = DEFAULTTABLESPACE_OID;
740  matched = true;
741  }
742  else
743  {
744  nmatch = sscanf(path, "pg_tblspc/%u/" TABLESPACE_VERSION_DIRECTORY "/%u/%u.%u",
745  &rnode.spcNode, &rnode.dbNode, &rnode.relNode,
746  &segNo);
747  if (nmatch == 3 || nmatch == 4)
748  matched = true;
749  }
750  }
751 
752  /*
753  * The sscanf tests above can match files that have extra characters at
754  * the end. To eliminate such cases, cross-check that GetRelationPath
755  * creates the exact same filename, when passed the RelFileNode
756  * information we extracted from the filename.
757  */
758  if (matched)
759  {
760  char *check_path = datasegpath(rnode, MAIN_FORKNUM, segNo);
761 
762  if (strcmp(check_path, path) != 0)
763  matched = false;
764 
765  pfree(check_path);
766  }
767 
768  return matched;
769 }
static char * datasegpath(RelFileNode rnode, ForkNumber forknum, BlockNumber segno)
Definition: filemap.c:777
void pfree(void *pointer)
Definition: mcxt.c:1057
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
#define InvalidOid
Definition: postgres_ext.h:36

◆ path_cmp()

static int path_cmp ( const void *  a,
const void *  b 
)
static

Definition at line 794 of file filemap.c.

References fa(), fb(), and file_entry_t::path.

Referenced by process_block_change(), and process_target_file().

795 {
796  file_entry_t *fa = *((file_entry_t **) a);
797  file_entry_t *fb = *((file_entry_t **) b);
798 
799  return strcmp(fa->path, fb->path);
800 }
static int fa(void)
Definition: preproc-init.c:85
static int fb(int x)
Definition: preproc-init.c:92
char * path
Definition: filemap.h:43
Definition: filemap.h:41

◆ print_filemap()

void print_filemap ( void  )

Definition at line 663 of file filemap.c.

References file_entry_t::action, action_to_str(), filemap_t::array, datapagemap::bitmapsize, datapagemap_print(), FILE_ACTION_NONE, filemap, i, filemap_t::narray, file_entry_t::pagemap, file_entry_t::path, pg_log_debug, and generate_unaccent_rules::stdout.

Referenced by main().

664 {
665  filemap_t *map = filemap;
666  file_entry_t *entry;
667  int i;
668 
669  for (i = 0; i < map->narray; i++)
670  {
671  entry = map->array[i];
672  if (entry->action != FILE_ACTION_NONE ||
673  entry->pagemap.bitmapsize > 0)
674  {
675  pg_log_debug("%s (%s)", entry->path,
676  action_to_str(entry->action));
677 
678  if (entry->pagemap.bitmapsize > 0)
679  datapagemap_print(&entry->pagemap);
680  }
681  }
682  fflush(stdout);
683 }
file_entry_t ** array
Definition: filemap.h:78
datapagemap_t pagemap
Definition: filemap.h:53
int narray
Definition: filemap.h:79
#define pg_log_debug(...)
Definition: logging.h:92
file_action_t action
Definition: filemap.h:46
filemap_t * filemap
Definition: filemap.c:23
static const char * action_to_str(file_action_t action)
Definition: filemap.c:595
void datapagemap_print(datapagemap_t *map)
Definition: datapagemap.c:117
int bitmapsize
Definition: datapagemap.h:18
char * path
Definition: filemap.h:43
int i
Definition: filemap.h:41

◆ process_block_change()

void process_block_change ( ForkNumber  forknum,
RelFileNode  rnode,
BlockNumber  blkno 
)

Definition at line 427 of file filemap.c.

References file_entry_t::action, filemap_t::array, Assert, datapagemap_add(), datasegpath(), FILE_ACTION_COPY, FILE_ACTION_COPY_TAIL, FILE_ACTION_CREATE, FILE_ACTION_NONE, FILE_ACTION_REMOVE, FILE_ACTION_TRUNCATE, filemap, file_entry_t::isrelfile, sort-test::key, filemap_t::narray, file_entry_t::pagemap, file_entry_t::path, path_cmp(), pfree(), and pg_fatal.

Referenced by extractPageInfo().

428 {
429  char *path;
431  file_entry_t *key_ptr;
432  file_entry_t *entry;
433  BlockNumber blkno_inseg;
434  int segno;
435  filemap_t *map = filemap;
436  file_entry_t **e;
437 
438  Assert(map->array);
439 
440  segno = blkno / RELSEG_SIZE;
441  blkno_inseg = blkno % RELSEG_SIZE;
442 
443  path = datasegpath(rnode, forknum, segno);
444 
445  key.path = (char *) path;
446  key_ptr = &key;
447 
448  e = bsearch(&key_ptr, map->array, map->narray, sizeof(file_entry_t *),
449  path_cmp);
450  if (e)
451  entry = *e;
452  else
453  entry = NULL;
454  pfree(path);
455 
456  if (entry)
457  {
458  Assert(entry->isrelfile);
459 
460  switch (entry->action)
461  {
462  case FILE_ACTION_NONE:
464  /* skip if we're truncating away the modified block anyway */
465  if ((blkno_inseg + 1) * BLCKSZ <= entry->newsize)
466  datapagemap_add(&entry->pagemap, blkno_inseg);
467  break;
468 
470 
471  /*
472  * skip the modified block if it is part of the "tail" that
473  * we're copying anyway.
474  */
475  if ((blkno_inseg + 1) * BLCKSZ <= entry->oldsize)
476  datapagemap_add(&entry->pagemap, blkno_inseg);
477  break;
478 
479  case FILE_ACTION_COPY:
480  case FILE_ACTION_REMOVE:
481  break;
482 
483  case FILE_ACTION_CREATE:
484  pg_fatal("unexpected page modification for directory or symbolic link \"%s\"", entry->path);
485  }
486  }
487  else
488  {
489  /*
490  * If we don't have any record of this file in the file map, it means
491  * that it's a relation that doesn't exist in the source system, and
492  * it was subsequently removed in the target system, too. We can
493  * safely ignore it.
494  */
495  }
496 }
void datapagemap_add(datapagemap_t *map, BlockNumber blkno)
Definition: datapagemap.c:32
file_entry_t ** array
Definition: filemap.h:78
#define pg_fatal(...)
Definition: pg_rewind.h:41
uint32 BlockNumber
Definition: block.h:31
datapagemap_t pagemap
Definition: filemap.h:53
int narray
Definition: filemap.h:79
static char * datasegpath(RelFileNode rnode, ForkNumber forknum, BlockNumber segno)
Definition: filemap.c:777
bool isrelfile
Definition: filemap.h:51
void pfree(void *pointer)
Definition: mcxt.c:1057
file_action_t action
Definition: filemap.h:46
filemap_t * filemap
Definition: filemap.c:23
#define Assert(condition)
Definition: c.h:746
char * path
Definition: filemap.h:43
e
Definition: preproc-init.c:82
Definition: filemap.h:41
static int path_cmp(const void *a, const void *b)
Definition: filemap.c:794

◆ process_source_file()

void process_source_file ( const char *  path,
file_type_t  type,
size_t  newsize,
const char *  link_target 
)

Definition at line 157 of file filemap.c.

References file_entry_t::action, generate_unaccent_rules::action, Assert, datapagemap::bitmap, datapagemap::bitmapsize, check_file_excluded(), datadir_target, FILE_ACTION_COPY, FILE_ACTION_COPY_TAIL, FILE_ACTION_CREATE, FILE_ACTION_NONE, FILE_ACTION_TRUNCATE, FILE_TYPE_DIRECTORY, FILE_TYPE_REGULAR, FILE_TYPE_SYMLINK, filemap, isRelDataFile(), file_entry_t::isrelfile, file_entry_t::link_target, lstat, MAXPGPATH, file_entry_t::newsize, file_entry_t::next, file_entry_t::oldsize, file_entry_t::pagemap, file_entry_t::path, pg_fatal, pg_malloc(), pg_str_endswith(), pg_strdup(), PG_TEMP_FILE_PREFIX, PG_TEMP_FILES_DIR, pgwin32_is_junction(), S_ISDIR, S_ISREG, snprintf, stat::st_mode, stat::st_size, file_entry_t::type, and generate_unaccent_rules::type.

Referenced by fetchSourceFileList(), and libpqProcessFileList().

159 {
160  bool exists;
161  char localpath[MAXPGPATH];
162  struct stat statbuf;
163  filemap_t *map = filemap;
165  size_t oldsize = 0;
166  file_entry_t *entry;
167 
168  Assert(map->array == NULL);
169 
170  /*
171  * Skip any files matching the exclusion filters. This has the effect to
172  * remove all those files on the target.
173  */
174  if (check_file_excluded(path, true))
175  return;
176 
177  /*
178  * Pretend that pg_wal is a directory, even if it's really a symlink. We
179  * don't want to mess with the symlink itself, nor complain if it's a
180  * symlink in source but not in target or vice versa.
181  */
182  if (strcmp(path, "pg_wal") == 0 && type == FILE_TYPE_SYMLINK)
184 
185  /*
186  * Skip temporary files, .../pgsql_tmp/... and .../pgsql_tmp.* in source.
187  * This has the effect that all temporary files in the destination will be
188  * removed.
189  */
190  if (strstr(path, "/" PG_TEMP_FILE_PREFIX) != NULL)
191  return;
192  if (strstr(path, "/" PG_TEMP_FILES_DIR "/") != NULL)
193  return;
194 
195  /*
196  * sanity check: a filename that looks like a data file better be a
197  * regular file
198  */
199  if (type != FILE_TYPE_REGULAR && isRelDataFile(path))
200  pg_fatal("data file \"%s\" in source is not a regular file", path);
201 
202  snprintf(localpath, sizeof(localpath), "%s/%s", datadir_target, path);
203 
204  /* Does the corresponding file exist in the target data dir? */
205  if (lstat(localpath, &statbuf) < 0)
206  {
207  if (errno != ENOENT)
208  pg_fatal("could not stat file \"%s\": %m",
209  localpath);
210 
211  exists = false;
212  }
213  else
214  exists = true;
215 
216  switch (type)
217  {
218  case FILE_TYPE_DIRECTORY:
219  if (exists && !S_ISDIR(statbuf.st_mode) && strcmp(path, "pg_wal") != 0)
220  {
221  /* it's a directory in source, but not in target. Strange.. */
222  pg_fatal("\"%s\" is not a directory", localpath);
223  }
224 
225  if (!exists)
226  action = FILE_ACTION_CREATE;
227  else
228  action = FILE_ACTION_NONE;
229  oldsize = 0;
230  break;
231 
232  case FILE_TYPE_SYMLINK:
233  if (exists &&
234 #ifndef WIN32
235  !S_ISLNK(statbuf.st_mode)
236 #else
237  !pgwin32_is_junction(localpath)
238 #endif
239  )
240  {
241  /*
242  * It's a symbolic link in source, but not in target.
243  * Strange..
244  */
245  pg_fatal("\"%s\" is not a symbolic link", localpath);
246  }
247 
248  if (!exists)
249  action = FILE_ACTION_CREATE;
250  else
251  action = FILE_ACTION_NONE;
252  oldsize = 0;
253  break;
254 
255  case FILE_TYPE_REGULAR:
256  if (exists && !S_ISREG(statbuf.st_mode))
257  pg_fatal("\"%s\" is not a regular file", localpath);
258 
259  if (!exists || !isRelDataFile(path))
260  {
261  /*
262  * File exists in source, but not in target. Or it's a
263  * non-data file that we have no special processing for. Copy
264  * it in toto.
265  *
266  * An exception: PG_VERSIONs should be identical, but avoid
267  * overwriting it for paranoia.
268  */
269  if (pg_str_endswith(path, "PG_VERSION"))
270  {
271  action = FILE_ACTION_NONE;
272  oldsize = statbuf.st_size;
273  }
274  else
275  {
276  action = FILE_ACTION_COPY;
277  oldsize = 0;
278  }
279  }
280  else
281  {
282  /*
283  * It's a data file that exists in both.
284  *
285  * If it's larger in target, we can truncate it. There will
286  * also be a WAL record of the truncation in the source
287  * system, so WAL replay would eventually truncate the target
288  * too, but we might as well do it now.
289  *
290  * If it's smaller in the target, it means that it has been
291  * truncated in the target, or enlarged in the source, or
292  * both. If it was truncated in the target, we need to copy
293  * the missing tail from the source system. If it was enlarged
294  * in the source system, there will be WAL records in the
295  * source system for the new blocks, so we wouldn't need to
296  * copy them here. But we don't know which scenario we're
297  * dealing with, and there's no harm in copying the missing
298  * blocks now, so do it now.
299  *
300  * If it's the same size, do nothing here. Any blocks modified
301  * in the target will be copied based on parsing the target
302  * system's WAL, and any blocks modified in the source will be
303  * updated after rewinding, when the source system's WAL is
304  * replayed.
305  */
306  oldsize = statbuf.st_size;
307  if (oldsize < newsize)
308  action = FILE_ACTION_COPY_TAIL;
309  else if (oldsize > newsize)
310  action = FILE_ACTION_TRUNCATE;
311  else
312  action = FILE_ACTION_NONE;
313  }
314  break;
315  }
316 
317  /* Create a new entry for this file */
318  entry = pg_malloc(sizeof(file_entry_t));
319  entry->path = pg_strdup(path);
320  entry->type = type;
321  entry->action = action;
322  entry->oldsize = oldsize;
323  entry->newsize = newsize;
324  entry->link_target = link_target ? pg_strdup(link_target) : NULL;
325  entry->next = NULL;
326  entry->pagemap.bitmap = NULL;
327  entry->pagemap.bitmapsize = 0;
328  entry->isrelfile = isRelDataFile(path);
329 
330  if (map->last)
331  {
332  map->last->next = entry;
333  map->last = entry;
334  }
335  else
336  map->first = map->last = entry;
337  map->nlist++;
338 }
char * datadir_target
Definition: pg_rewind.c:55
bool pg_str_endswith(const char *str, const char *end)
Definition: string.c:31
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
size_t newsize
Definition: filemap.h:50
#define PG_TEMP_FILES_DIR
Definition: pg_checksums.c:58
#define pg_fatal(...)
Definition: pg_rewind.h:41
char * bitmap
Definition: datapagemap.h:17
static bool check_file_excluded(const char *path, bool is_source)
Definition: filemap.c:502
datapagemap_t pagemap
Definition: filemap.h:53
file_type_t type
Definition: filemap.h:44
bool isrelfile
Definition: filemap.h:51
#define PG_TEMP_FILE_PREFIX
Definition: pg_checksums.c:59
#define MAXPGPATH
file_action_t action
Definition: filemap.h:46
char * link_target
Definition: filemap.h:56
struct file_entry_t * next
Definition: filemap.h:58
filemap_t * filemap
Definition: filemap.c:23
size_t oldsize
Definition: filemap.h:49
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
#define S_ISREG(m)
Definition: win32_port.h:319
int bitmapsize
Definition: datapagemap.h:18
#define Assert(condition)
Definition: c.h:746
file_action_t
Definition: filemap.h:23
static bool isRelDataFile(const char *path)
Definition: filemap.c:694
char * path
Definition: filemap.h:43
#define S_ISDIR(m)
Definition: win32_port.h:316
#define lstat(path, sb)
Definition: win32_port.h:276
Definition: filemap.h:41
#define snprintf
Definition: port.h:215
bool pgwin32_is_junction(const char *path)

◆ process_target_file()

void process_target_file ( const char *  path,
file_type_t  type,
size_t  oldsize,
const char *  link_target 
)

Definition at line 348 of file filemap.c.

References file_entry_t::action, filemap_t::array, Assert, datapagemap::bitmap, datapagemap::bitmapsize, FILE_ACTION_REMOVE, FILE_TYPE_DIRECTORY, FILE_TYPE_SYMLINK, filemap, filemap_list_to_array(), filemap_t::first, isRelDataFile(), file_entry_t::isrelfile, sort-test::key, filemap_t::last, file_entry_t::link_target, filemap_t::narray, file_entry_t::newsize, file_entry_t::next, filemap_t::nlist, file_entry_t::oldsize, file_entry_t::pagemap, file_entry_t::path, path_cmp(), pg_fatal, pg_malloc(), pg_strdup(), qsort, file_entry_t::type, and generate_unaccent_rules::type.

Referenced by main().

350 {
351  bool exists;
353  file_entry_t *key_ptr;
354  filemap_t *map = filemap;
355  file_entry_t *entry;
356 
357  /*
358  * Do not apply any exclusion filters here. This has advantage to remove
359  * from the target data folder all paths which have been filtered out from
360  * the source data folder when processing the source files.
361  */
362 
363  if (map->array == NULL)
364  {
365  /* on first call, initialize lookup array */
366  if (map->nlist == 0)
367  {
368  /* should not happen */
369  pg_fatal("source file list is empty");
370  }
371 
373 
374  Assert(map->array != NULL);
375 
376  qsort(map->array, map->narray, sizeof(file_entry_t *), path_cmp);
377  }
378 
379  /*
380  * Like in process_source_file, pretend that xlog is always a directory.
381  */
382  if (strcmp(path, "pg_wal") == 0 && type == FILE_TYPE_SYMLINK)
384 
385  key.path = (char *) path;
386  key_ptr = &key;
387  exists = (bsearch(&key_ptr, map->array, map->narray, sizeof(file_entry_t *),
388  path_cmp) != NULL);
389 
390  /* Remove any file or folder that doesn't exist in the source system. */
391  if (!exists)
392  {
393  entry = pg_malloc(sizeof(file_entry_t));
394  entry->path = pg_strdup(path);
395  entry->type = type;
396  entry->action = FILE_ACTION_REMOVE;
397  entry->oldsize = oldsize;
398  entry->newsize = 0;
399  entry->link_target = link_target ? pg_strdup(link_target) : NULL;
400  entry->next = NULL;
401  entry->pagemap.bitmap = NULL;
402  entry->pagemap.bitmapsize = 0;
403  entry->isrelfile = isRelDataFile(path);
404 
405  if (map->last == NULL)
406  map->first = entry;
407  else
408  map->last->next = entry;
409  map->last = entry;
410  map->nlist++;
411  }
412  else
413  {
414  /*
415  * We already handled all files that exist in the source system in
416  * process_source_file().
417  */
418  }
419 }
file_entry_t * first
Definition: filemap.h:67
file_entry_t ** array
Definition: filemap.h:78
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
size_t newsize
Definition: filemap.h:50
#define pg_fatal(...)
Definition: pg_rewind.h:41
char * bitmap
Definition: datapagemap.h:17
datapagemap_t pagemap
Definition: filemap.h:53
int narray
Definition: filemap.h:79
file_type_t type
Definition: filemap.h:44
bool isrelfile
Definition: filemap.h:51
int nlist
Definition: filemap.h:69
file_action_t action
Definition: filemap.h:46
char * link_target
Definition: filemap.h:56
struct file_entry_t * next
Definition: filemap.h:58
filemap_t * filemap
Definition: filemap.c:23
size_t oldsize
Definition: filemap.h:49
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
int bitmapsize
Definition: datapagemap.h:18
#define Assert(condition)
Definition: c.h:746
static bool isRelDataFile(const char *path)
Definition: filemap.c:694
char * path
Definition: filemap.h:43
static void filemap_list_to_array(filemap_t *map)
Definition: filemap.c:561
file_entry_t * last
Definition: filemap.h:68
Definition: filemap.h:41
static int path_cmp(const void *a, const void *b)
Definition: filemap.c:794
#define qsort(a, b, c, d)
Definition: port.h:497

Variable Documentation

◆ excludeDirContents

const char* excludeDirContents[]
static
Initial value:
=
{
"pg_stat_tmp",
"pg_replslot",
"pg_dynshmem",
"pg_notify",
"pg_serial",
"pg_snapshots",
"pg_subtrans",
NULL
}

Definition at line 54 of file filemap.c.

Referenced by check_file_excluded().

◆ excludeFiles

const struct exclude_list_item excludeFiles[]
static
Initial value:
=
{
{"postgresql.auto.conf.tmp", false},
{"current_logfiles.tmp", false},
{"pg_internal.init", true},
{"backup_label", false},
{"tablespace_map", false},
{"backup_manifest", false},
{"postmaster.pid", false},
{"postmaster.opts", false},
{NULL, false}
}

Definition at line 96 of file filemap.c.

◆ filemap