00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "postgres_fe.h"
00011
00012 #include "pg_upgrade.h"
00013
00014 #include "catalog/pg_class.h"
00015 #include "access/transam.h"
00016
00017
00018 static void transfer_single_new_db(pageCnvCtx *pageConverter,
00019 FileNameMap *maps, int size, char *old_tablespace);
00020 static void transfer_relfile(pageCnvCtx *pageConverter, FileNameMap *map,
00021 const char *suffix);
00022
00023
00024
00025
00026
00027
00028
00029
00030 void
00031 transfer_all_new_tablespaces(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
00032 char *old_pgdata, char *new_pgdata)
00033 {
00034 pg_log(PG_REPORT, "%s user relation files\n",
00035 user_opts.transfer_mode == TRANSFER_MODE_LINK ? "Linking" : "Copying");
00036
00037
00038
00039
00040
00041
00042
00043
00044 if (user_opts.jobs <= 1)
00045 parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
00046 new_pgdata, NULL);
00047 else
00048 {
00049 int tblnum;
00050
00051
00052 parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
00053 new_pgdata, old_pgdata);
00054
00055 for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
00056 parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
00057 new_pgdata, os_info.old_tablespaces[tblnum]);
00058
00059 while (reap_child(true) == true)
00060 ;
00061 }
00062
00063 end_progress_output();
00064 check_ok();
00065
00066 return;
00067 }
00068
00069
00070
00071
00072
00073
00074
00075
00076 void
00077 transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
00078 char *old_pgdata, char *new_pgdata, char *old_tablespace)
00079 {
00080 int old_dbnum,
00081 new_dbnum;
00082
00083
00084 for (old_dbnum = new_dbnum = 0;
00085 old_dbnum < old_db_arr->ndbs;
00086 old_dbnum++, new_dbnum++)
00087 {
00088 DbInfo *old_db = &old_db_arr->dbs[old_dbnum],
00089 *new_db = NULL;
00090 FileNameMap *mappings;
00091 int n_maps;
00092 pageCnvCtx *pageConverter = NULL;
00093
00094
00095
00096
00097
00098
00099 for (; new_dbnum < new_db_arr->ndbs; new_dbnum++)
00100 {
00101 new_db = &new_db_arr->dbs[new_dbnum];
00102 if (strcmp(old_db->db_name, new_db->db_name) == 0)
00103 break;
00104 }
00105
00106 if (new_dbnum >= new_db_arr->ndbs)
00107 pg_log(PG_FATAL, "old database \"%s\" not found in the new cluster\n",
00108 old_db->db_name);
00109
00110 n_maps = 0;
00111 mappings = gen_db_file_maps(old_db, new_db, &n_maps, old_pgdata,
00112 new_pgdata);
00113
00114 if (n_maps)
00115 {
00116 print_maps(mappings, n_maps, new_db->db_name);
00117
00118 #ifdef PAGE_CONVERSION
00119 pageConverter = setupPageConverter();
00120 #endif
00121 transfer_single_new_db(pageConverter, mappings, n_maps,
00122 old_tablespace);
00123
00124 pg_free(mappings);
00125 }
00126 }
00127
00128 return;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138 void
00139 get_pg_database_relfilenode(ClusterInfo *cluster)
00140 {
00141 PGconn *conn = connectToServer(cluster, "template1");
00142 PGresult *res;
00143 int i_relfile;
00144
00145 res = executeQueryOrDie(conn,
00146 "SELECT c.relname, c.relfilenode "
00147 "FROM pg_catalog.pg_class c, "
00148 " pg_catalog.pg_namespace n "
00149 "WHERE c.relnamespace = n.oid AND "
00150 " n.nspname = 'pg_catalog' AND "
00151 " c.relname = 'pg_database' "
00152 "ORDER BY c.relname");
00153
00154 i_relfile = PQfnumber(res, "relfilenode");
00155 cluster->pg_database_oid = atooid(PQgetvalue(res, 0, i_relfile));
00156
00157 PQclear(res);
00158 PQfinish(conn);
00159 }
00160
00161
00162
00163
00164
00165
00166
00167 static void
00168 transfer_single_new_db(pageCnvCtx *pageConverter,
00169 FileNameMap *maps, int size, char *old_tablespace)
00170 {
00171 int mapnum;
00172 bool vm_crashsafe_match = true;
00173
00174
00175
00176
00177
00178 if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_CRASHSAFE_CAT_VER &&
00179 new_cluster.controldata.cat_ver >= VISIBILITY_MAP_CRASHSAFE_CAT_VER)
00180 vm_crashsafe_match = false;
00181
00182 for (mapnum = 0; mapnum < size; mapnum++)
00183 {
00184 if (old_tablespace == NULL ||
00185 strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0)
00186 {
00187
00188 transfer_relfile(pageConverter, &maps[mapnum], "");
00189
00190
00191 if (GET_MAJOR_VERSION(old_cluster.major_version) >= 804)
00192 {
00193
00194
00195
00196 transfer_relfile(pageConverter, &maps[mapnum], "_fsm");
00197 if (vm_crashsafe_match)
00198 transfer_relfile(pageConverter, &maps[mapnum], "_vm");
00199 }
00200 }
00201 }
00202 }
00203
00204
00205
00206
00207
00208
00209
00210 static void
00211 transfer_relfile(pageCnvCtx *pageConverter, FileNameMap *map,
00212 const char *type_suffix)
00213 {
00214 const char *msg;
00215 char old_file[MAXPGPATH];
00216 char new_file[MAXPGPATH];
00217 int fd;
00218 int segno;
00219 char extent_suffix[65];
00220
00221
00222
00223
00224
00225
00226
00227
00228 for (segno = 0;; segno++)
00229 {
00230 if (segno == 0)
00231 extent_suffix[0] = '\0';
00232 else
00233 snprintf(extent_suffix, sizeof(extent_suffix), ".%d", segno);
00234
00235 snprintf(old_file, sizeof(old_file), "%s%s/%u/%u%s%s", map->old_tablespace,
00236 map->old_tablespace_suffix, map->old_db_oid, map->old_relfilenode,
00237 type_suffix, extent_suffix);
00238 snprintf(new_file, sizeof(new_file), "%s%s/%u/%u%s%s", map->new_tablespace,
00239 map->new_tablespace_suffix, map->new_db_oid, map->new_relfilenode,
00240 type_suffix, extent_suffix);
00241
00242
00243 if (type_suffix[0] != '\0' || segno != 0)
00244 {
00245
00246 if ((fd = open(old_file, O_RDONLY, 0)) == -1)
00247 {
00248
00249 if (errno == ENOENT)
00250 return;
00251 else
00252 pg_log(PG_FATAL, "error while checking for file existance \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
00253 map->nspname, map->relname, old_file, new_file,
00254 getErrorText(errno));
00255 }
00256 close(fd);
00257 }
00258
00259 unlink(new_file);
00260
00261
00262 pg_log(PG_STATUS, "%s", old_file);
00263
00264 if ((user_opts.transfer_mode == TRANSFER_MODE_LINK) && (pageConverter != NULL))
00265 pg_log(PG_FATAL, "This upgrade requires page-by-page conversion, "
00266 "you must use copy mode instead of link mode.\n");
00267
00268 if (user_opts.transfer_mode == TRANSFER_MODE_COPY)
00269 {
00270 pg_log(PG_VERBOSE, "copying \"%s\" to \"%s\"\n", old_file, new_file);
00271
00272 if ((msg = copyAndUpdateFile(pageConverter, old_file, new_file, true)) != NULL)
00273 pg_log(PG_FATAL, "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
00274 map->nspname, map->relname, old_file, new_file, msg);
00275 }
00276 else
00277 {
00278 pg_log(PG_VERBOSE, "linking \"%s\" to \"%s\"\n", old_file, new_file);
00279
00280 if ((msg = linkAndUpdateFile(pageConverter, old_file, new_file)) != NULL)
00281 pg_log(PG_FATAL,
00282 "error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
00283 map->nspname, map->relname, old_file, new_file, msg);
00284 }
00285 }
00286
00287 return;
00288 }
00289