|
29 | 29 | static PGconn *catchup_collect_info(PGNodeInfo *source_node_info, const char *source_pgdata, const char *dest_pgdata);
|
30 | 30 | static void catchup_preflight_checks(PGNodeInfo *source_node_info, PGconn *source_conn, const char *source_pgdata,
|
31 | 31 | const char *dest_pgdata);
|
| 32 | +static void check_tablespaces_existance_in_tbsmapping(PGconn *conn); |
32 | 33 | static void do_catchup_instance(const char *source_pgdata, const char *dest_pgdata, PGconn *source_conn,
|
33 | 34 | PGNodeInfo *nodeInfo, bool no_sync, bool backup_logs);
|
34 | 35 | static void *catchup_thread_runner(void *arg);
|
@@ -126,18 +127,18 @@ catchup_preflight_checks(PGNodeInfo *source_node_info, PGconn *source_conn,
|
126 | 127 | * kulaginm -- I think this is a harmful feature. If user requested an incremental catchup, then
|
127 | 128 | * he expects that this will be done quickly and efficiently. If, for example, he made a mistake
|
128 | 129 | * with dest_dir, then he will receive a second full copy instead of an error message, and I think
|
129 |
| - * that in some cases he would prefer the error. |
| 130 | + * that in some cases he would prefer the error. |
130 | 131 | * I propose in future versions to offer a backup_mode auto, in which we will look to the dest_dir
|
131 | 132 | * and decide which of the modes will be the most effective.
|
132 | 133 | * I.e.:
|
133 | 134 | * if(requested_backup_mode == BACKUP_MODE_DIFF_AUTO)
|
134 | 135 | * {
|
135 | 136 | * if(dest_pgdata_is_empty)
|
136 | 137 | * backup_mode = BACKUP_MODE_FULL;
|
137 |
| - * else |
138 |
| - * if(ptrack supported and applicable) |
| 138 | + * else |
| 139 | + * if(ptrack supported and applicable) |
139 | 140 | * backup_mode = BACKUP_MODE_DIFF_PTRACK;
|
140 |
| - * else |
| 141 | + * else |
141 | 142 | * backup_mode = BACKUP_MODE_DIFF_DELTA;
|
142 | 143 | * }
|
143 | 144 | */
|
@@ -179,8 +180,48 @@ catchup_preflight_checks(PGNodeInfo *source_node_info, PGconn *source_conn,
|
179 | 180 | if (current.from_replica && exclusive_backup)
|
180 | 181 | elog(ERROR, "Catchup from standby is available only for PG >= 9.6");
|
181 | 182 |
|
182 |
| - //REVIEW FIXME Let's fix it before release. This one seems like a potential bug. |
183 |
| - // TODO check if it is local catchup and source contain tablespaces |
| 183 | + if (!fio_is_remote(FIO_DB_HOST)) |
| 184 | + check_tablespaces_existance_in_tbsmapping(source_conn); |
| 185 | +} |
| 186 | + |
| 187 | +/* |
| 188 | + * Check that all tablespaces exists in tablespace mapping (--tablespace-mapping option) |
| 189 | + * Emit fatal error if that tablespace found |
| 190 | + */ |
| 191 | +static void |
| 192 | +check_tablespaces_existance_in_tbsmapping(PGconn *conn) |
| 193 | +{ |
| 194 | + PGresult *res; |
| 195 | + int i; |
| 196 | + char *tablespace_path = NULL; |
| 197 | + const char *linked_path = NULL; |
| 198 | + char *query = "SELECT pg_catalog.pg_tablespace_location(oid) " |
| 199 | + "FROM pg_catalog.pg_tablespace " |
| 200 | + "WHERE pg_catalog.pg_tablespace_location(oid) <> '';"; |
| 201 | + |
| 202 | + res = pgut_execute(conn, query, 0, NULL); |
| 203 | + |
| 204 | + if (!res) |
| 205 | + elog(ERROR, "Failed to get list of tablespaces"); |
| 206 | + |
| 207 | + for (i = 0; i < res->ntups; i++) |
| 208 | + { |
| 209 | + tablespace_path = PQgetvalue(res, i, 0); |
| 210 | + Assert (strlen(tablespace_path) > 0); |
| 211 | + |
| 212 | + canonicalize_path(tablespace_path); |
| 213 | + linked_path = leaked_abstraction_get_tablespace_mapping(tablespace_path); |
| 214 | + |
| 215 | + if (strcmp(tablespace_path, linked_path) == 0) |
| 216 | + /* same result -> not found in mapping */ |
| 217 | + elog(ERROR, "Local catchup executed, but source database contains " |
| 218 | + "tablespace (\"%s\"), that are not listed in the map", tablespace_path); |
| 219 | + |
| 220 | + if (!is_absolute_path(linked_path)) |
| 221 | + elog(ERROR, "Tablespace directory path must be an absolute path: %s\n", |
| 222 | + linked_path); |
| 223 | + } |
| 224 | + PQclear(res); |
184 | 225 | }
|
185 | 226 |
|
186 | 227 | /*
|
|
0 commit comments