PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
relfilenumber.c File Reference
#include "postgres_fe.h"
#include <sys/stat.h>
#include "common/file_perm.h"
#include "common/file_utils.h"
#include "common/int.h"
#include "common/logging.h"
#include "pg_upgrade.h"
Include dependency graph for relfilenumber.c:

Go to the source code of this file.

Macros

#define SYNC_QUEUE_MAX_LEN   (1024)
 

Functions

static void transfer_single_new_db (FileNameMap *maps, int size, char *old_tablespace)
 
static void transfer_relfile (FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit)
 
static void sync_queue_init (void)
 
static void sync_queue_sync_all (void)
 
static void sync_queue_push (const char *fname)
 
static void sync_queue_destroy (void)
 
void transfer_all_new_tablespaces (DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata)
 
void transfer_all_new_dbs (DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata, char *old_tablespace)
 
static bool prepare_for_swap (const char *old_tablespace, Oid db_oid, char *old_catalog_dir, char *new_db_dir, char *moved_db_dir)
 
static int FileNameMapCmp (const void *a, const void *b)
 
static RelFileNumber parse_relfilenumber (const char *filename)
 
static void swap_catalog_files (FileNameMap *maps, int size, const char *old_catalog_dir, const char *new_db_dir, const char *moved_db_dir)
 
static void do_swap (FileNameMap *maps, int size, char *old_tablespace)
 

Variables

static char * sync_queue [SYNC_QUEUE_MAX_LEN]
 
static bool sync_queue_inited
 
static int sync_queue_len
 

Macro Definition Documentation

◆ SYNC_QUEUE_MAX_LEN

#define SYNC_QUEUE_MAX_LEN   (1024)

Definition at line 42 of file relfilenumber.c.

Function Documentation

◆ do_swap()

static void do_swap ( FileNameMap maps,
int  size,
char *  old_tablespace 
)
static

Definition at line 453 of file relfilenumber.c.

454{
455 char old_catalog_dir[MAXPGPATH];
456 char new_db_dir[MAXPGPATH];
457 char moved_db_dir[MAXPGPATH];
458
459 /*
460 * We perform many lookups on maps by relfilenumber in swap mode, so make
461 * sure it's sorted by relfilenumber. maps should already be sorted by
462 * OID, so in general this shouldn't have much work to do.
463 */
464 qsort(maps, size, sizeof(FileNameMap), FileNameMapCmp);
465
466 /*
467 * If an old tablespace is given, we only need to process that one. If no
468 * old tablespace is specified, we need to process all the tablespaces on
469 * the system.
470 */
471 if (old_tablespace)
472 {
473 if (prepare_for_swap(old_tablespace, maps[0].db_oid,
474 old_catalog_dir, new_db_dir, moved_db_dir))
476 old_catalog_dir, new_db_dir, moved_db_dir);
477 }
478 else
479 {
481 old_catalog_dir, new_db_dir, moved_db_dir))
483 old_catalog_dir, new_db_dir, moved_db_dir);
484
485 for (int tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
486 {
487 if (prepare_for_swap(os_info.old_tablespaces[tblnum], maps[0].db_oid,
488 old_catalog_dir, new_db_dir, moved_db_dir))
490 old_catalog_dir, new_db_dir, moved_db_dir);
491 }
492 }
493}
#define MAXPGPATH
OSInfo os_info
Definition: pg_upgrade.c:73
ClusterInfo old_cluster
Definition: pg_upgrade.c:71
#define qsort(a, b, c, d)
Definition: port.h:479
static bool prepare_for_swap(const char *old_tablespace, Oid db_oid, char *old_catalog_dir, char *new_db_dir, char *moved_db_dir)
static void swap_catalog_files(FileNameMap *maps, int size, const char *old_catalog_dir, const char *new_db_dir, const char *moved_db_dir)
static int FileNameMapCmp(const void *a, const void *b)
char * pgdata
Definition: pg_upgrade.h:292
int num_old_tablespaces
Definition: pg_upgrade.h:358
char ** old_tablespaces
Definition: pg_upgrade.h:357
static const pg_conv_map maps[]

References FileNameMapCmp(), maps, MAXPGPATH, OSInfo::num_old_tablespaces, old_cluster, OSInfo::old_tablespaces, os_info, ClusterInfo::pgdata, prepare_for_swap(), qsort, and swap_catalog_files().

Referenced by transfer_single_new_db().

◆ FileNameMapCmp()

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

Definition at line 316 of file relfilenumber.c.

317{
318 const FileNameMap *map1 = (const FileNameMap *) a;
319 const FileNameMap *map2 = (const FileNameMap *) b;
320
321 return pg_cmp_u32(map1->relfilenumber, map2->relfilenumber);
322}
static int pg_cmp_u32(uint32 a, uint32 b)
Definition: int.h:652
int b
Definition: isn.c:74
int a
Definition: isn.c:73
RelFileNumber relfilenumber
Definition: pg_upgrade.h:187

References a, b, pg_cmp_u32(), and FileNameMap::relfilenumber.

Referenced by do_swap(), and swap_catalog_files().

◆ parse_relfilenumber()

static RelFileNumber parse_relfilenumber ( const char *  filename)
static

Definition at line 332 of file relfilenumber.c.

333{
334 char *endp;
335 unsigned long n;
336
337 if (filename[0] < '1' || filename[0] > '9')
339
340 errno = 0;
341 n = strtoul(filename, &endp, 10);
342 if (errno || filename == endp || n <= 0 || n > PG_UINT32_MAX)
344
345 return (RelFileNumber) n;
346}
#define PG_UINT32_MAX
Definition: c.h:561
static char * filename
Definition: pg_dumpall.c:123
Oid RelFileNumber
Definition: relpath.h:25
#define InvalidRelFileNumber
Definition: relpath.h:26

References filename, InvalidRelFileNumber, and PG_UINT32_MAX.

Referenced by swap_catalog_files().

◆ prepare_for_swap()

static bool prepare_for_swap ( const char *  old_tablespace,
Oid  db_oid,
char *  old_catalog_dir,
char *  new_db_dir,
char *  moved_db_dir 
)
static

Definition at line 237 of file relfilenumber.c.

239{
240 const char *new_tablespace;
241 const char *old_tblspc_suffix;
242 const char *new_tblspc_suffix;
243 char old_tblspc[MAXPGPATH];
244 char new_tblspc[MAXPGPATH];
245 char moved_tblspc[MAXPGPATH];
246 char old_db_dir[MAXPGPATH];
247 struct stat st;
248
249 if (strcmp(old_tablespace, old_cluster.pgdata) == 0)
250 {
251 new_tablespace = new_cluster.pgdata;
252 new_tblspc_suffix = "/base";
253 old_tblspc_suffix = "/base";
254 }
255 else
256 {
257 /*
258 * XXX: The below line is a hack to deal with the fact that we
259 * presently don't have an easy way to find the corresponding new
260 * tablespace's path. This will need to be fixed if/when we add
261 * pg_upgrade support for in-place tablespaces.
262 */
263 new_tablespace = old_tablespace;
264
265 new_tblspc_suffix = new_cluster.tablespace_suffix;
266 old_tblspc_suffix = old_cluster.tablespace_suffix;
267 }
268
269 /* Old and new cluster paths. */
270 snprintf(old_tblspc, sizeof(old_tblspc), "%s%s", old_tablespace, old_tblspc_suffix);
271 snprintf(new_tblspc, sizeof(new_tblspc), "%s%s", new_tablespace, new_tblspc_suffix);
272 snprintf(old_db_dir, sizeof(old_db_dir), "%s/%u", old_tblspc, db_oid);
273 snprintf(new_db_dir, MAXPGPATH, "%s/%u", new_tblspc, db_oid);
274
275 /*
276 * Paths for "moved aside" stuff. We intentionally put these in the old
277 * cluster so that the delete_old_cluster.{sh,bat} script handles them.
278 */
279 snprintf(moved_tblspc, sizeof(moved_tblspc), "%s/moved_for_upgrade", old_tblspc);
280 snprintf(old_catalog_dir, MAXPGPATH, "%s/%u_old_catalogs", moved_tblspc, db_oid);
281 snprintf(moved_db_dir, MAXPGPATH, "%s/%u", moved_tblspc, db_oid);
282
283 /* Check that the database directory exists in the given tablespace. */
284 if (stat(old_db_dir, &st) != 0)
285 {
286 if (errno != ENOENT)
287 pg_fatal("could not stat file \"%s\": %m", old_db_dir);
288 return false;
289 }
290
291 /* Create directory for stuff that is moved aside. */
292 if (pg_mkdir_p(moved_tblspc, pg_dir_create_mode) != 0 && errno != EEXIST)
293 pg_fatal("could not create directory \"%s\"", moved_tblspc);
294
295 /* Create directory for old catalog files. */
296 if (pg_mkdir_p(old_catalog_dir, pg_dir_create_mode) != 0)
297 pg_fatal("could not create directory \"%s\"", old_catalog_dir);
298
299 /* Move the new cluster's database directory aside. */
300 if (rename(new_db_dir, moved_db_dir) != 0)
301 pg_fatal("could not rename \"%s\" to \"%s\"", new_db_dir, moved_db_dir);
302
303 /* Move the old cluster's database directory into place. */
304 if (rename(old_db_dir, new_db_dir) != 0)
305 pg_fatal("could not rename \"%s\" to \"%s\"", old_db_dir, new_db_dir);
306
307 return true;
308}
int pg_dir_create_mode
Definition: file_perm.c:18
#define pg_fatal(...)
ClusterInfo new_cluster
Definition: pg_upgrade.c:72
int pg_mkdir_p(char *path, int omode)
Definition: pgmkdirp.c:57
#define snprintf
Definition: port.h:239
const char * tablespace_suffix
Definition: pg_upgrade.h:303
#define stat
Definition: win32_port.h:274

References MAXPGPATH, new_cluster, old_cluster, pg_dir_create_mode, pg_fatal, pg_mkdir_p(), ClusterInfo::pgdata, snprintf, stat, and ClusterInfo::tablespace_suffix.

Referenced by do_swap().

◆ swap_catalog_files()

static void swap_catalog_files ( FileNameMap maps,
int  size,
const char *  old_catalog_dir,
const char *  new_db_dir,
const char *  moved_db_dir 
)
static

Definition at line 363 of file relfilenumber.c.

365{
366 DIR *dir;
367 struct dirent *de;
368 char path[MAXPGPATH];
369 char dest[MAXPGPATH];
370 RelFileNumber rfn;
371
372 /* Move the old catalog files aside. */
373 dir = opendir(new_db_dir);
374 if (dir == NULL)
375 pg_fatal("could not open directory \"%s\": %m", new_db_dir);
376 while (errno = 0, (de = readdir(dir)) != NULL)
377 {
378 snprintf(path, sizeof(path), "%s/%s", new_db_dir, de->d_name);
379 if (get_dirent_type(path, de, false, PG_LOG_ERROR) != PGFILETYPE_REG)
380 continue;
381
382 rfn = parse_relfilenumber(de->d_name);
383 if (RelFileNumberIsValid(rfn))
384 {
385 FileNameMap key = {.relfilenumber = rfn};
386
387 if (bsearch(&key, maps, size, sizeof(FileNameMap), FileNameMapCmp))
388 continue;
389 }
390
391 snprintf(dest, sizeof(dest), "%s/%s", old_catalog_dir, de->d_name);
392 if (rename(path, dest) != 0)
393 pg_fatal("could not rename \"%s\" to \"%s\": %m", path, dest);
394 }
395 if (errno)
396 pg_fatal("could not read directory \"%s\": %m", new_db_dir);
397 (void) closedir(dir);
398
399 /* Move the new catalog files into place. */
400 dir = opendir(moved_db_dir);
401 if (dir == NULL)
402 pg_fatal("could not open directory \"%s\": %m", moved_db_dir);
403 while (errno = 0, (de = readdir(dir)) != NULL)
404 {
405 snprintf(path, sizeof(path), "%s/%s", moved_db_dir, de->d_name);
406 if (get_dirent_type(path, de, false, PG_LOG_ERROR) != PGFILETYPE_REG)
407 continue;
408
409 rfn = parse_relfilenumber(de->d_name);
410 if (RelFileNumberIsValid(rfn))
411 {
412 FileNameMap key = {.relfilenumber = rfn};
413
414 if (bsearch(&key, maps, size, sizeof(FileNameMap), FileNameMapCmp))
415 continue;
416 }
417
418 snprintf(dest, sizeof(dest), "%s/%s", new_db_dir, de->d_name);
419 if (rename(path, dest) != 0)
420 pg_fatal("could not rename \"%s\" to \"%s\": %m", path, dest);
421
422 /*
423 * We don't fsync() the database files in the file synchronization
424 * stage of pg_upgrade in swap mode, so we need to synchronize them
425 * ourselves. We only do this for the catalog files because they were
426 * created during pg_restore with fsync=off. We assume that the user
427 * data files were properly persisted to disk when the user last shut
428 * it down.
429 */
430 if (user_opts.do_sync)
432 }
433 if (errno)
434 pg_fatal("could not read directory \"%s\": %m", moved_db_dir);
435 (void) closedir(dir);
436
437 /* Ensure the directory entries are persisted to disk. */
438 if (fsync_fname(new_db_dir, true) != 0)
439 pg_fatal("could not synchronize directory \"%s\": %m", new_db_dir);
440 if (fsync_parent_path(new_db_dir) != 0)
441 pg_fatal("could not synchronize parent directory of \"%s\": %m", new_db_dir);
442}
int closedir(DIR *)
Definition: dirent.c:127
struct dirent * readdir(DIR *)
Definition: dirent.c:78
DIR * opendir(const char *)
Definition: dirent.c:33
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:756
static int fsync_parent_path(const char *fname, int elevel)
Definition: fd.c:3938
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition: file_utils.c:547
@ PGFILETYPE_REG
Definition: file_utils.h:22
@ PG_LOG_ERROR
Definition: logging.h:43
static RelFileNumber parse_relfilenumber(const char *filename)
static void sync_queue_push(const char *fname)
Definition: relfilenumber.c:75
#define RelFileNumberIsValid(relnumber)
Definition: relpath.h:27
UserOpts user_opts
Definition: option.c:30
Definition: dirent.c:26
bool do_sync
Definition: pg_upgrade.h:332
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15

References closedir(), dirent::d_name, generate_unaccent_rules::dest, UserOpts::do_sync, FileNameMapCmp(), fsync_fname(), fsync_parent_path(), get_dirent_type(), sort-test::key, maps, MAXPGPATH, opendir(), parse_relfilenumber(), pg_fatal, PG_LOG_ERROR, PGFILETYPE_REG, readdir(), RelFileNumberIsValid, snprintf, sync_queue_push(), and user_opts.

Referenced by do_swap().

◆ sync_queue_destroy()

static void sync_queue_destroy ( void  )
inlinestatic

Definition at line 87 of file relfilenumber.c.

88{
90 return;
91
92 sync_queue_inited = false;
94 for (int i = 0; i < SYNC_QUEUE_MAX_LEN; i++)
95 {
97 sync_queue[i] = NULL;
98 }
99}
int i
Definition: isn.c:77
void pfree(void *pointer)
Definition: mcxt.c:2150
static char * sync_queue[SYNC_QUEUE_MAX_LEN]
Definition: relfilenumber.c:44
static int sync_queue_len
Definition: relfilenumber.c:46
static bool sync_queue_inited
Definition: relfilenumber.c:45
#define SYNC_QUEUE_MAX_LEN
Definition: relfilenumber.c:42

References i, pfree(), sync_queue, sync_queue_inited, sync_queue_len, and SYNC_QUEUE_MAX_LEN.

Referenced by transfer_all_new_dbs().

◆ sync_queue_init()

static void sync_queue_init ( void  )
inlinestatic

Definition at line 49 of file relfilenumber.c.

50{
52 return;
53
54 sync_queue_inited = true;
55 for (int i = 0; i < SYNC_QUEUE_MAX_LEN; i++)
57}
void * palloc(Size size)
Definition: mcxt.c:1943

References i, MAXPGPATH, palloc(), sync_queue, sync_queue_inited, and SYNC_QUEUE_MAX_LEN.

Referenced by sync_queue_push().

◆ sync_queue_push()

static void sync_queue_push ( const char *  fname)
inlinestatic

Definition at line 75 of file relfilenumber.c.

76{
78
79 pre_sync_fname(fname, false);
80
81 strncpy(sync_queue[sync_queue_len++], fname, MAXPGPATH);
84}
static void sync_queue_init(void)
Definition: relfilenumber.c:49
static void sync_queue_sync_all(void)
Definition: relfilenumber.c:60

References MAXPGPATH, sync_queue, sync_queue_init(), sync_queue_len, SYNC_QUEUE_MAX_LEN, and sync_queue_sync_all().

Referenced by swap_catalog_files().

◆ sync_queue_sync_all()

static void sync_queue_sync_all ( void  )
inlinestatic

Definition at line 60 of file relfilenumber.c.

61{
63 return;
64
65 for (int i = 0; i < sync_queue_len; i++)
66 {
67 if (fsync_fname(sync_queue[i], false) != 0)
68 pg_fatal("could not synchronize file \"%s\": %m", sync_queue[i]);
69 }
70
72}

References fsync_fname(), i, pg_fatal, sync_queue, sync_queue_inited, and sync_queue_len.

Referenced by sync_queue_push(), and transfer_all_new_dbs().

◆ transfer_all_new_dbs()

void transfer_all_new_dbs ( DbInfoArr old_db_arr,
DbInfoArr new_db_arr,
char *  old_pgdata,
char *  new_pgdata,
char *  old_tablespace 
)

Definition at line 171 of file relfilenumber.c.

173{
174 int old_dbnum,
175 new_dbnum;
176
177 /* Scan the old cluster databases and transfer their files */
178 for (old_dbnum = new_dbnum = 0;
179 old_dbnum < old_db_arr->ndbs;
180 old_dbnum++, new_dbnum++)
181 {
182 DbInfo *old_db = &old_db_arr->dbs[old_dbnum],
183 *new_db = NULL;
184 FileNameMap *mappings;
185 int n_maps;
186
187 /*
188 * Advance past any databases that exist in the new cluster but not in
189 * the old, e.g. "postgres". (The user might have removed the
190 * 'postgres' database from the old cluster.)
191 */
192 for (; new_dbnum < new_db_arr->ndbs; new_dbnum++)
193 {
194 new_db = &new_db_arr->dbs[new_dbnum];
195 if (strcmp(old_db->db_name, new_db->db_name) == 0)
196 break;
197 }
198
199 if (new_dbnum >= new_db_arr->ndbs)
200 pg_fatal("old database \"%s\" not found in the new cluster",
201 old_db->db_name);
202
203 mappings = gen_db_file_maps(old_db, new_db, &n_maps, old_pgdata,
204 new_pgdata);
205 if (n_maps)
206 {
207 transfer_single_new_db(mappings, n_maps, old_tablespace);
208 }
209 /* We allocate something even for n_maps == 0 */
210 pg_free(mappings);
211 }
212
213 /*
214 * Make sure anything pending synchronization in swap mode is fully
215 * persisted to disk. This is a no-op for other transfer modes.
216 */
219}
void pg_free(void *ptr)
Definition: fe_memutils.c:105
FileNameMap * gen_db_file_maps(DbInfo *old_db, DbInfo *new_db, int *nmaps, const char *old_pgdata, const char *new_pgdata)
Definition: info.c:45
static void sync_queue_destroy(void)
Definition: relfilenumber.c:87
static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace)
DbInfo * dbs
Definition: pg_upgrade.h:220
char * db_name
Definition: pg_upgrade.h:199

References DbInfo::db_name, DbInfoArr::dbs, gen_db_file_maps(), DbInfoArr::ndbs, pg_fatal, pg_free(), sync_queue_destroy(), sync_queue_sync_all(), and transfer_single_new_db().

Referenced by parallel_transfer_all_new_dbs().

◆ transfer_all_new_tablespaces()

void transfer_all_new_tablespaces ( DbInfoArr old_db_arr,
DbInfoArr new_db_arr,
char *  old_pgdata,
char *  new_pgdata 
)

Definition at line 108 of file relfilenumber.c.

110{
111 switch (user_opts.transfer_mode)
112 {
114 prep_status_progress("Cloning user relation files");
115 break;
117 prep_status_progress("Copying user relation files");
118 break;
120 prep_status_progress("Copying user relation files with copy_file_range");
121 break;
123 prep_status_progress("Linking user relation files");
124 break;
126 prep_status_progress("Swapping data directories");
127 break;
128 }
129
130 /*
131 * Transferring files by tablespace is tricky because a single database
132 * can use multiple tablespaces. For non-parallel mode, we just pass a
133 * NULL tablespace path, which matches all tablespaces. In parallel mode,
134 * we pass the default tablespace and all user-created tablespaces and let
135 * those operations happen in parallel.
136 */
137 if (user_opts.jobs <= 1)
138 parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
139 new_pgdata, NULL);
140 else
141 {
142 int tblnum;
143
144 /* transfer default tablespace */
145 parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
146 new_pgdata, old_pgdata);
147
148 for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
150 new_db_arr,
151 old_pgdata,
152 new_pgdata,
153 os_info.old_tablespaces[tblnum]);
154 /* reap all children */
155 while (reap_child(true) == true)
156 ;
157 }
158
160 check_ok();
161}
void parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata, char *old_tablespace)
Definition: parallel.c:172
bool reap_child(bool wait_for_child)
Definition: parallel.c:278
static void check_ok(void)
Definition: initdb.c:2117
@ TRANSFER_MODE_COPY
Definition: pg_upgrade.h:262
@ TRANSFER_MODE_LINK
Definition: pg_upgrade.h:264
@ TRANSFER_MODE_SWAP
Definition: pg_upgrade.h:265
@ TRANSFER_MODE_CLONE
Definition: pg_upgrade.h:261
@ TRANSFER_MODE_COPY_FILE_RANGE
Definition: pg_upgrade.h:263
void void prep_status_progress(const char *fmt,...) pg_attribute_printf(1
void void pg_noreturn void void end_progress_output(void)
Definition: util.c:43
transferMode transfer_mode
Definition: pg_upgrade.h:333
int jobs
Definition: pg_upgrade.h:334

References check_ok(), end_progress_output(), UserOpts::jobs, OSInfo::num_old_tablespaces, OSInfo::old_tablespaces, os_info, parallel_transfer_all_new_dbs(), prep_status_progress(), reap_child(), UserOpts::transfer_mode, TRANSFER_MODE_CLONE, TRANSFER_MODE_COPY, TRANSFER_MODE_COPY_FILE_RANGE, TRANSFER_MODE_LINK, TRANSFER_MODE_SWAP, and user_opts.

Referenced by main().

◆ transfer_relfile()

static void transfer_relfile ( FileNameMap map,
const char *  type_suffix,
bool  vm_must_add_frozenbit 
)
static

Definition at line 553 of file relfilenumber.c.

554{
555 char old_file[MAXPGPATH];
556 char new_file[MAXPGPATH];
557 int segno;
558 char extent_suffix[65];
559 struct stat statbuf;
560
561 /*
562 * Now copy/link any related segments as well. Remember, PG breaks large
563 * files into 1GB segments, the first segment has no extension, subsequent
564 * segments are named relfilenumber.1, relfilenumber.2, relfilenumber.3.
565 */
566 for (segno = 0;; segno++)
567 {
568 if (segno == 0)
569 extent_suffix[0] = '\0';
570 else
571 snprintf(extent_suffix, sizeof(extent_suffix), ".%d", segno);
572
573 snprintf(old_file, sizeof(old_file), "%s%s/%u/%u%s%s",
574 map->old_tablespace,
576 map->db_oid,
577 map->relfilenumber,
578 type_suffix,
579 extent_suffix);
580 snprintf(new_file, sizeof(new_file), "%s%s/%u/%u%s%s",
581 map->new_tablespace,
583 map->db_oid,
584 map->relfilenumber,
585 type_suffix,
586 extent_suffix);
587
588 /* Is it an extent, fsm, or vm file? */
589 if (type_suffix[0] != '\0' || segno != 0)
590 {
591 /* Did file open fail? */
592 if (stat(old_file, &statbuf) != 0)
593 {
594 /* File does not exist? That's OK, just return */
595 if (errno == ENOENT)
596 return;
597 else
598 pg_fatal("error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %m",
599 map->nspname, map->relname, old_file, new_file);
600 }
601
602 /* If file is empty, just return */
603 if (statbuf.st_size == 0)
604 return;
605 }
606
607 unlink(new_file);
608
609 /* Copying files might take some time, so give feedback. */
610 pg_log(PG_STATUS, "%s", old_file);
611
612 if (vm_must_add_frozenbit && strcmp(type_suffix, "_vm") == 0)
613 {
614 /* Need to rewrite visibility map format */
615 pg_log(PG_VERBOSE, "rewriting \"%s\" to \"%s\"",
616 old_file, new_file);
617 rewriteVisibilityMap(old_file, new_file, map->nspname, map->relname);
618 }
619 else
620 switch (user_opts.transfer_mode)
621 {
623 pg_log(PG_VERBOSE, "cloning \"%s\" to \"%s\"",
624 old_file, new_file);
625 cloneFile(old_file, new_file, map->nspname, map->relname);
626 break;
628 pg_log(PG_VERBOSE, "copying \"%s\" to \"%s\"",
629 old_file, new_file);
630 copyFile(old_file, new_file, map->nspname, map->relname);
631 break;
633 pg_log(PG_VERBOSE, "copying \"%s\" to \"%s\" with copy_file_range",
634 old_file, new_file);
635 copyFileByRange(old_file, new_file, map->nspname, map->relname);
636 break;
638 pg_log(PG_VERBOSE, "linking \"%s\" to \"%s\"",
639 old_file, new_file);
640 linkFile(old_file, new_file, map->nspname, map->relname);
641 break;
643 /* swap mode is handled in its own code path */
644 pg_fatal("should never happen");
645 break;
646 }
647 }
648}
void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName)
Definition: file.c:190
void rewriteVisibilityMap(const char *fromfile, const char *tofile, const char *schemaName, const char *relName)
Definition: file.c:216
void cloneFile(const char *src, const char *dst, const char *schemaName, const char *relName)
Definition: file.c:39
void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName)
Definition: file.c:151
void copyFile(const char *src, const char *dst, const char *schemaName, const char *relName)
Definition: file.c:82
void void pg_log(eLogType type, const char *fmt,...) pg_attribute_printf(2
@ PG_STATUS
Definition: pg_upgrade.h:274
@ PG_VERBOSE
Definition: pg_upgrade.h:273
const char * new_tablespace
Definition: pg_upgrade.h:183
const char * old_tablespace_suffix
Definition: pg_upgrade.h:184
const char * old_tablespace
Definition: pg_upgrade.h:182
char * relname
Definition: pg_upgrade.h:190
char * nspname
Definition: pg_upgrade.h:189
const char * new_tablespace_suffix
Definition: pg_upgrade.h:185

References cloneFile(), copyFile(), copyFileByRange(), FileNameMap::db_oid, linkFile(), MAXPGPATH, FileNameMap::new_tablespace, FileNameMap::new_tablespace_suffix, FileNameMap::nspname, FileNameMap::old_tablespace, FileNameMap::old_tablespace_suffix, pg_fatal, pg_log(), PG_STATUS, PG_VERBOSE, FileNameMap::relfilenumber, FileNameMap::relname, rewriteVisibilityMap(), snprintf, stat::st_size, stat, UserOpts::transfer_mode, TRANSFER_MODE_CLONE, TRANSFER_MODE_COPY, TRANSFER_MODE_COPY_FILE_RANGE, TRANSFER_MODE_LINK, TRANSFER_MODE_SWAP, and user_opts.

Referenced by transfer_single_new_db().

◆ transfer_single_new_db()

static void transfer_single_new_db ( FileNameMap maps,
int  size,
char *  old_tablespace 
)
static

Definition at line 501 of file relfilenumber.c.

502{
503 int mapnum;
504 bool vm_must_add_frozenbit = false;
505
506 /*
507 * Do we need to rewrite visibilitymap?
508 */
511 vm_must_add_frozenbit = true;
512
513 /* --swap has its own subroutine */
515 {
516 /*
517 * We don't support --swap to upgrade from versions that require
518 * rewriting the visibility map. We should've failed already if
519 * someone tries to do that.
520 */
521 Assert(!vm_must_add_frozenbit);
522
523 do_swap(maps, size, old_tablespace);
524 return;
525 }
526
527 for (mapnum = 0; mapnum < size; mapnum++)
528 {
529 if (old_tablespace == NULL ||
530 strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0)
531 {
532 /* transfer primary file */
533 transfer_relfile(&maps[mapnum], "", vm_must_add_frozenbit);
534
535 /*
536 * Copy/link any fsm and vm files, if they exist
537 */
538 transfer_relfile(&maps[mapnum], "_fsm", vm_must_add_frozenbit);
539 transfer_relfile(&maps[mapnum], "_vm", vm_must_add_frozenbit);
540 }
541 }
542}
Assert(PointerIsAligned(start, uint64))
#define VISIBILITY_MAP_FROZEN_BIT_CAT_VER
Definition: pg_upgrade.h:107
static void do_swap(FileNameMap *maps, int size, char *old_tablespace)
static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit)
ControlData controldata
Definition: pg_upgrade.h:289
uint32 cat_ver
Definition: pg_upgrade.h:232

References Assert(), ControlData::cat_ver, ClusterInfo::controldata, do_swap(), maps, new_cluster, old_cluster, UserOpts::transfer_mode, TRANSFER_MODE_SWAP, transfer_relfile(), user_opts, and VISIBILITY_MAP_FROZEN_BIT_CAT_VER.

Referenced by transfer_all_new_dbs().

Variable Documentation

◆ sync_queue

char* sync_queue[SYNC_QUEUE_MAX_LEN]
static

◆ sync_queue_inited

bool sync_queue_inited
static

Definition at line 45 of file relfilenumber.c.

Referenced by sync_queue_destroy(), sync_queue_init(), and sync_queue_sync_all().

◆ sync_queue_len

int sync_queue_len
static

Definition at line 46 of file relfilenumber.c.

Referenced by sync_queue_destroy(), sync_queue_push(), and sync_queue_sync_all().