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

Go to the source code of this file.

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 char * excludeFiles []
 

Function Documentation

◆ action_to_str()

static const char* action_to_str ( file_action_t  action)
static

Definition at line 581 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().

582 {
583  switch (action)
584  {
585  case FILE_ACTION_NONE:
586  return "NONE";
587  case FILE_ACTION_COPY:
588  return "COPY";
590  return "TRUNCATE";
592  return "COPY_TAIL";
593  case FILE_ACTION_CREATE:
594  return "CREATE";
595  case FILE_ACTION_REMOVE:
596  return "REMOVE";
597 
598  default:
599  return "unknown";
600  }
601 }

◆ calculate_totals()

void calculate_totals ( void  )

Definition at line 607 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().

608 {
609  file_entry_t *entry;
610  int i;
611  filemap_t *map = filemap;
612 
613  map->total_size = 0;
614  map->fetch_size = 0;
615 
616  for (i = 0; i < map->narray; i++)
617  {
618  entry = map->array[i];
619 
620  if (entry->type != FILE_TYPE_REGULAR)
621  continue;
622 
623  map->total_size += entry->newsize;
624 
625  if (entry->action == FILE_ACTION_COPY)
626  {
627  map->fetch_size += entry->newsize;
628  continue;
629  }
630 
631  if (entry->action == FILE_ACTION_COPY_TAIL)
632  map->fetch_size += (entry->newsize - entry->oldsize);
633 
634  if (entry->pagemap.bitmapsize > 0)
635  {
637  BlockNumber blk;
638 
639  iter = datapagemap_iterate(&entry->pagemap);
640  while (datapagemap_next(iter, &blk))
641  map->fetch_size += BLCKSZ;
642 
643  pg_free(iter);
644  }
645  }
646 }
file_entry_t ** array
Definition: filemap.h:79
size_t newsize
Definition: filemap.h:51
uint32 BlockNumber
Definition: block.h:31
datapagemap_t pagemap
Definition: filemap.h:54
int narray
Definition: filemap.h:80
uint64 fetch_size
Definition: filemap.h:87
file_type_t type
Definition: filemap.h:45
bool datapagemap_next(datapagemap_iterator_t *iter, BlockNumber *blkno)
Definition: datapagemap.c:88
file_action_t action
Definition: filemap.h:47
filemap_t * filemap
Definition: filemap.c:24
size_t oldsize
Definition: filemap.h:50
uint64 total_size
Definition: filemap.h:86
int bitmapsize
Definition: datapagemap.h:19
datapagemap_iterator_t * datapagemap_iterate(datapagemap_t *map)
Definition: datapagemap.c:76
void pg_free(void *ptr)
Definition: fe_memutils.c:105
int i
Definition: filemap.h:42

◆ check_file_excluded()

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

Definition at line 493 of file filemap.c.

References excludeDirContents, excludeFiles, filename, last_dir_separator(), MAXPGPATH, pg_log_debug, and snprintf.

Referenced by process_source_file().

494 {
495  char localpath[MAXPGPATH];
496  int excludeIdx;
497  const char *filename;
498 
499  /* check individual files... */
500  for (excludeIdx = 0; excludeFiles[excludeIdx] != NULL; excludeIdx++)
501  {
502  filename = last_dir_separator(path);
503  if (filename == NULL)
504  filename = path;
505  else
506  filename++;
507  if (strcmp(filename, excludeFiles[excludeIdx]) == 0)
508  {
509  if (is_source)
510  pg_log_debug("entry \"%s\" excluded from source file list",
511  path);
512  else
513  pg_log_debug("entry \"%s\" excluded from target file list",
514  path);
515  return true;
516  }
517  }
518 
519  /*
520  * ... And check some directories. Note that this includes any contents
521  * within the directories themselves.
522  */
523  for (excludeIdx = 0; excludeDirContents[excludeIdx] != NULL; excludeIdx++)
524  {
525  snprintf(localpath, sizeof(localpath), "%s/",
526  excludeDirContents[excludeIdx]);
527  if (strstr(path, localpath) == path)
528  {
529  if (is_source)
530  pg_log_debug("entry \"%s\" excluded from source file list",
531  path);
532  else
533  pg_log_debug("entry \"%s\" excluded from target file list",
534  path);
535  return true;
536  }
537  }
538 
539  return false;
540 }
#define pg_log_debug(...)
Definition: logging.h:91
#define MAXPGPATH
static const char * excludeFiles[]
Definition: filemap.c:84
char * last_dir_separator(const char *filename)
Definition: path.c:138
static char * filename
Definition: pg_dumpall.c:91
static const char * excludeDirContents[]
Definition: filemap.c:43
#define snprintf
Definition: port.h:192

◆ datasegpath()

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

Definition at line 763 of file filemap.c.

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

Referenced by isRelDataFile(), and process_block_change().

764 {
765  char *path;
766  char *segpath;
767 
768  path = relpathperm(rnode, forknum);
769  if (segno > 0)
770  {
771  segpath = psprintf("%s.%u", path, segno);
772  pfree(path);
773  return segpath;
774  }
775  else
776  return path;
777 }
#define relpathperm(rnode, forknum)
Definition: relpath.h:83
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
void pfree(void *pointer)
Definition: mcxt.c:1056

◆ filemap_create()

void filemap_create ( void  )

Definition at line 114 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().

115 {
116  filemap_t *map;
117 
118  map = pg_malloc(sizeof(filemap_t));
119  map->first = map->last = NULL;
120  map->nlist = 0;
121  map->array = NULL;
122  map->narray = 0;
123 
124  Assert(filemap == NULL);
125  filemap = map;
126 }
file_entry_t * first
Definition: filemap.h:68
file_entry_t ** array
Definition: filemap.h:79
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
int narray
Definition: filemap.h:80
int nlist
Definition: filemap.h:70
filemap_t * filemap
Definition: filemap.c:24
#define Assert(condition)
Definition: c.h:732
file_entry_t * last
Definition: filemap.h:69

◆ filemap_finalize()

void filemap_finalize ( void  )

Definition at line 571 of file filemap.c.

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

Referenced by main().

572 {
573  filemap_t *map = filemap;
574 
576  qsort(map->array, map->narray, sizeof(file_entry_t *),
578 }
static int final_filemap_cmp(const void *a, const void *b)
Definition: filemap.c:799
file_entry_t ** array
Definition: filemap.h:79
int narray
Definition: filemap.h:80
filemap_t * filemap
Definition: filemap.c:24
static void filemap_list_to_array(filemap_t *map)
Definition: filemap.c:547
Definition: filemap.h:42
#define qsort(a, b, c, d)
Definition: port.h:492

◆ filemap_list_to_array()

static void filemap_list_to_array ( filemap_t map)
static

Definition at line 547 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().

548 {
549  int narray;
550  file_entry_t *entry,
551  *next;
552 
553  map->array = (file_entry_t **)
554  pg_realloc(map->array,
555  (map->nlist + map->narray) * sizeof(file_entry_t *));
556 
557  narray = map->narray;
558  for (entry = map->first; entry != NULL; entry = next)
559  {
560  map->array[narray++] = entry;
561  next = entry->next;
562  entry->next = NULL;
563  }
564  Assert(narray == map->nlist + map->narray);
565  map->narray = narray;
566  map->nlist = 0;
567  map->first = map->last = NULL;
568 }
static int32 next
Definition: blutils.c:215
file_entry_t * first
Definition: filemap.h:68
file_entry_t ** array
Definition: filemap.h:79
int narray
Definition: filemap.h:80
int nlist
Definition: filemap.h:70
struct file_entry_t * next
Definition: filemap.h:59
void * pg_realloc(void *ptr, size_t size)
Definition: fe_memutils.c:65
#define Assert(condition)
Definition: c.h:732
file_entry_t * last
Definition: filemap.h:69
Definition: filemap.h:42

◆ final_filemap_cmp()

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

Definition at line 799 of file filemap.c.

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

Referenced by filemap_finalize().

800 {
801  file_entry_t *fa = *((file_entry_t **) a);
802  file_entry_t *fb = *((file_entry_t **) b);
803 
804  if (fa->action > fb->action)
805  return 1;
806  if (fa->action < fb->action)
807  return -1;
808 
809  if (fa->action == FILE_ACTION_REMOVE)
810  return strcmp(fb->path, fa->path);
811  else
812  return strcmp(fa->path, fb->path);
813 }
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:47
char * path
Definition: filemap.h:44
Definition: filemap.h:42

◆ isRelDataFile()

static bool isRelDataFile ( const char *  path)
static

Definition at line 680 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().

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

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

Referenced by process_block_change(), and process_target_file().

781 {
782  file_entry_t *fa = *((file_entry_t **) a);
783  file_entry_t *fb = *((file_entry_t **) b);
784 
785  return strcmp(fa->path, fb->path);
786 }
static int fa(void)
Definition: preproc-init.c:85
static int fb(int x)
Definition: preproc-init.c:92
char * path
Definition: filemap.h:44
Definition: filemap.h:42

◆ print_filemap()

void print_filemap ( void  )

Definition at line 649 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().

650 {
651  filemap_t *map = filemap;
652  file_entry_t *entry;
653  int i;
654 
655  for (i = 0; i < map->narray; i++)
656  {
657  entry = map->array[i];
658  if (entry->action != FILE_ACTION_NONE ||
659  entry->pagemap.bitmapsize > 0)
660  {
661  pg_log_debug("%s (%s)", entry->path,
662  action_to_str(entry->action));
663 
664  if (entry->pagemap.bitmapsize > 0)
665  datapagemap_print(&entry->pagemap);
666  }
667  }
668  fflush(stdout);
669 }
file_entry_t ** array
Definition: filemap.h:79
datapagemap_t pagemap
Definition: filemap.h:54
int narray
Definition: filemap.h:80
#define pg_log_debug(...)
Definition: logging.h:91
file_action_t action
Definition: filemap.h:47
filemap_t * filemap
Definition: filemap.c:24
static const char * action_to_str(file_action_t action)
Definition: filemap.c:581
void datapagemap_print(datapagemap_t *map)
Definition: datapagemap.c:118
int bitmapsize
Definition: datapagemap.h:19
char * path
Definition: filemap.h:44
int i
Definition: filemap.h:42

◆ process_block_change()

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

Definition at line 418 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().

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

◆ process_source_file()

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

Definition at line 136 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, file_entry_t::type, and generate_unaccent_rules::type.

Referenced by fetchSourceFileList(), and libpqProcessFileList().

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

References file_entry_t::action, filemap_t::array, Assert, datapagemap::bitmap, datapagemap::bitmapsize, datadir_target, 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, lstat, MAXPGPATH, 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, snprintf, stat, file_entry_t::type, and generate_unaccent_rules::type.

Referenced by main().

329 {
330  bool exists;
331  char localpath[MAXPGPATH];
332  struct stat statbuf;
334  file_entry_t *key_ptr;
335  filemap_t *map = filemap;
336  file_entry_t *entry;
337 
338  /*
339  * Do not apply any exclusion filters here. This has advantage to remove
340  * from the target data folder all paths which have been filtered out from
341  * the source data folder when processing the source files.
342  */
343 
344  snprintf(localpath, sizeof(localpath), "%s/%s", datadir_target, path);
345  if (lstat(localpath, &statbuf) < 0)
346  {
347  if (errno != ENOENT)
348  pg_fatal("could not stat file \"%s\": %m",
349  localpath);
350 
351  exists = false;
352  }
353 
354  if (map->array == NULL)
355  {
356  /* on first call, initialize lookup array */
357  if (map->nlist == 0)
358  {
359  /* should not happen */
360  pg_fatal("source file list is empty");
361  }
362 
364 
365  Assert(map->array != NULL);
366 
367  qsort(map->array, map->narray, sizeof(file_entry_t *), path_cmp);
368  }
369 
370  /*
371  * Like in process_source_file, pretend that xlog is always a directory.
372  */
373  if (strcmp(path, "pg_wal") == 0 && type == FILE_TYPE_SYMLINK)
375 
376  key.path = (char *) path;
377  key_ptr = &key;
378  exists = (bsearch(&key_ptr, map->array, map->narray, sizeof(file_entry_t *),
379  path_cmp) != NULL);
380 
381  /* Remove any file or folder that doesn't exist in the source system. */
382  if (!exists)
383  {
384  entry = pg_malloc(sizeof(file_entry_t));
385  entry->path = pg_strdup(path);
386  entry->type = type;
387  entry->action = FILE_ACTION_REMOVE;
388  entry->oldsize = oldsize;
389  entry->newsize = 0;
390  entry->link_target = link_target ? pg_strdup(link_target) : NULL;
391  entry->next = NULL;
392  entry->pagemap.bitmap = NULL;
393  entry->pagemap.bitmapsize = 0;
394  entry->isrelfile = isRelDataFile(path);
395 
396  if (map->last == NULL)
397  map->first = entry;
398  else
399  map->last->next = entry;
400  map->last = entry;
401  map->nlist++;
402  }
403  else
404  {
405  /*
406  * We already handled all files that exist in the source system in
407  * process_source_file().
408  */
409  }
410 }
char * datadir_target
Definition: pg_rewind.c:54
file_entry_t * first
Definition: filemap.h:68
file_entry_t ** array
Definition: filemap.h:79
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
size_t newsize
Definition: filemap.h:51
#define pg_fatal(...)
Definition: pg_rewind.h:43
char * bitmap
Definition: datapagemap.h:18
datapagemap_t pagemap
Definition: filemap.h:54
int narray
Definition: filemap.h:80
file_type_t type
Definition: filemap.h:45
bool isrelfile
Definition: filemap.h:52
int nlist
Definition: filemap.h:70
#define MAXPGPATH
file_action_t action
Definition: filemap.h:47
char * link_target
Definition: filemap.h:57
struct file_entry_t * next
Definition: filemap.h:59
filemap_t * filemap
Definition: filemap.c:24
size_t oldsize
Definition: filemap.h:50
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
#define stat(a, b)
Definition: win32_port.h:255
int bitmapsize
Definition: datapagemap.h:19
#define Assert(condition)
Definition: c.h:732
static bool isRelDataFile(const char *path)
Definition: filemap.c:680
char * path
Definition: filemap.h:44
static void filemap_list_to_array(filemap_t *map)
Definition: filemap.c:547
#define lstat(path, sb)
Definition: win32_port.h:244
file_entry_t * last
Definition: filemap.h:69
Definition: filemap.h:42
static int path_cmp(const void *a, const void *b)
Definition: filemap.c:780
#define qsort(a, b, c, d)
Definition: port.h:492
#define snprintf
Definition: port.h:192

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 43 of file filemap.c.

Referenced by check_file_excluded().

◆ excludeFiles

const char* excludeFiles[]
static
Initial value:
=
{
"postgresql.auto.conf.tmp",
"current_logfiles.tmp",
"pg_internal.init",
"backup_label",
"tablespace_map",
"postmaster.pid",
"postmaster.opts",
NULL
}

Definition at line 84 of file filemap.c.

Referenced by check_file_excluded().

◆ filemap