4 * relfilenode functions
6 * Copyright (c) 2010-2020, PostgreSQL Global Development Group
7 * src/bin/pg_upgrade/relfilenode.c
10 #include "postgres_fe.h"
14 #include "access/transam.h"
15 #include "catalog/pg_class_d.h"
16 #include "pg_upgrade.h"
18 static void transfer_single_new_db(FileNameMap
*maps
, int size
, char *old_tablespace
);
19 static void transfer_relfile(FileNameMap
*map
, const char *suffix
, bool vm_must_add_frozenbit
);
23 * transfer_all_new_tablespaces()
25 * Responsible for upgrading all database. invokes routines to generate mappings and then
26 * physically link the databases.
29 transfer_all_new_tablespaces(DbInfoArr
*old_db_arr
, DbInfoArr
*new_db_arr
,
30 char *old_pgdata
, char *new_pgdata
)
32 switch (user_opts
.transfer_mode
)
34 case TRANSFER_MODE_CLONE
:
35 pg_log(PG_REPORT
, "Cloning user relation files\n");
37 case TRANSFER_MODE_COPY
:
38 pg_log(PG_REPORT
, "Copying user relation files\n");
40 case TRANSFER_MODE_LINK
:
41 pg_log(PG_REPORT
, "Linking user relation files\n");
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.
52 if (user_opts
.jobs
<= 1)
53 parallel_transfer_all_new_dbs(old_db_arr
, new_db_arr
, old_pgdata
,
59 /* transfer default tablespace */
60 parallel_transfer_all_new_dbs(old_db_arr
, new_db_arr
, old_pgdata
,
61 new_pgdata
, old_pgdata
);
63 for (tblnum
= 0; tblnum
< os_info
.num_old_tablespaces
; tblnum
++)
64 parallel_transfer_all_new_dbs(old_db_arr
,
68 os_info
.old_tablespaces
[tblnum
]);
69 /* reap all children */
70 while (reap_child(true) == true)
74 end_progress_output();
80 * transfer_all_new_dbs()
82 * Responsible for upgrading all database. invokes routines to generate mappings and then
83 * physically link the databases.
86 transfer_all_new_dbs(DbInfoArr
*old_db_arr
, DbInfoArr
*new_db_arr
,
87 char *old_pgdata
, char *new_pgdata
, char *old_tablespace
)
92 /* Scan the old cluster databases and transfer their files */
93 for (old_dbnum
= new_dbnum
= 0;
94 old_dbnum
< old_db_arr
->ndbs
;
95 old_dbnum
++, new_dbnum
++)
97 DbInfo
*old_db
= &old_db_arr
->dbs
[old_dbnum
],
99 FileNameMap
*mappings
;
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.)
107 for (; new_dbnum
< new_db_arr
->ndbs
; new_dbnum
++)
109 new_db
= &new_db_arr
->dbs
[new_dbnum
];
110 if (strcmp(old_db
->db_name
, new_db
->db_name
) == 0)
114 if (new_dbnum
>= new_db_arr
->ndbs
)
115 pg_fatal("old database \"%s\" not found in the new cluster\n",
118 mappings
= gen_db_file_maps(old_db
, new_db
, &n_maps
, old_pgdata
,
122 print_maps(mappings
, n_maps
, new_db
->db_name
);
124 transfer_single_new_db(mappings
, n_maps
, old_tablespace
);
126 /* We allocate something even for n_maps == 0 */
132 * transfer_single_new_db()
134 * create links for mappings stored in "maps" array.
137 transfer_single_new_db(FileNameMap
*maps
, int size
, char *old_tablespace
)
140 bool vm_crashsafe_match
= true;
141 bool vm_must_add_frozenbit
= false;
144 * Do the old and new cluster disagree on the crash-safetiness of the vm
145 * files? If so, do not copy them.
147 if (old_cluster
.controldata
.cat_ver
< VISIBILITY_MAP_CRASHSAFE_CAT_VER
&&
148 new_cluster
.controldata
.cat_ver
>= VISIBILITY_MAP_CRASHSAFE_CAT_VER
)
149 vm_crashsafe_match
= false;
152 * Do we need to rewrite visibilitymap?
154 if (old_cluster
.controldata
.cat_ver
< VISIBILITY_MAP_FROZEN_BIT_CAT_VER
&&
155 new_cluster
.controldata
.cat_ver
>= VISIBILITY_MAP_FROZEN_BIT_CAT_VER
)
156 vm_must_add_frozenbit
= true;
158 for (mapnum
= 0; mapnum
< size
; mapnum
++)
160 if (old_tablespace
== NULL
||
161 strcmp(maps
[mapnum
].old_tablespace
, old_tablespace
) == 0)
163 /* transfer primary file */
164 transfer_relfile(&maps
[mapnum
], "", vm_must_add_frozenbit
);
167 * Copy/link any fsm and vm files, if they exist
169 transfer_relfile(&maps
[mapnum
], "_fsm", vm_must_add_frozenbit
);
170 if (vm_crashsafe_match
)
171 transfer_relfile(&maps
[mapnum
], "_vm", vm_must_add_frozenbit
);
180 * Copy or link file from old cluster to new one. If vm_must_add_frozenbit
181 * is true, visibility map forks are converted and rewritten, even in link
185 transfer_relfile(FileNameMap
*map
, const char *type_suffix
, bool vm_must_add_frozenbit
)
187 char old_file
[MAXPGPATH
];
188 char new_file
[MAXPGPATH
];
190 char extent_suffix
[65];
194 * Now copy/link any related segments as well. Remember, PG breaks large
195 * files into 1GB segments, the first segment has no extension, subsequent
196 * segments are named relfilenode.1, relfilenode.2, relfilenode.3.
198 for (segno
= 0;; segno
++)
201 extent_suffix
[0] = '\0';
203 snprintf(extent_suffix
, sizeof(extent_suffix
), ".%d", segno
);
205 snprintf(old_file
, sizeof(old_file
), "%s%s/%u/%u%s%s",
207 map
->old_tablespace_suffix
,
209 map
->old_relfilenode
,
212 snprintf(new_file
, sizeof(new_file
), "%s%s/%u/%u%s%s",
214 map
->new_tablespace_suffix
,
216 map
->new_relfilenode
,
220 /* Is it an extent, fsm, or vm file? */
221 if (type_suffix
[0] != '\0' || segno
!= 0)
223 /* Did file open fail? */
224 if (stat(old_file
, &statbuf
) != 0)
226 /* File does not exist? That's OK, just return */
230 pg_fatal("error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
231 map
->nspname
, map
->relname
, old_file
, new_file
,
235 /* If file is empty, just return */
236 if (statbuf
.st_size
== 0)
242 /* Copying files might take some time, so give feedback. */
243 pg_log(PG_STATUS
, "%s", old_file
);
245 if (vm_must_add_frozenbit
&& strcmp(type_suffix
, "_vm") == 0)
247 /* Need to rewrite visibility map format */
248 pg_log(PG_VERBOSE
, "rewriting \"%s\" to \"%s\"\n",
250 rewriteVisibilityMap(old_file
, new_file
, map
->nspname
, map
->relname
);
253 switch (user_opts
.transfer_mode
)
255 case TRANSFER_MODE_CLONE
:
256 pg_log(PG_VERBOSE
, "cloning \"%s\" to \"%s\"\n",
258 cloneFile(old_file
, new_file
, map
->nspname
, map
->relname
);
260 case TRANSFER_MODE_COPY
:
261 pg_log(PG_VERBOSE
, "copying \"%s\" to \"%s\"\n",
263 copyFile(old_file
, new_file
, map
->nspname
, map
->relname
);
265 case TRANSFER_MODE_LINK
:
266 pg_log(PG_VERBOSE
, "linking \"%s\" to \"%s\"\n",
268 linkFile(old_file
, new_file
, map
->nspname
, map
->relname
);