28
28
*/
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
- const char * dest_pgdata , bool dest_pgdata_is_empty );
31
+ const char * dest_pgdata );
32
32
static void do_catchup_instance (const char * source_pgdata , const char * dest_pgdata , PGconn * source_conn ,
33
- PGNodeInfo * nodeInfo , bool no_sync , bool backup_logs ,
34
- bool dest_pgdata_is_empty );
33
+ PGNodeInfo * nodeInfo , bool no_sync , bool backup_logs );
35
34
static void * catchup_thread_runner (void * arg );
36
35
37
36
/*
@@ -44,13 +43,12 @@ do_catchup(const char *source_pgdata, const char *dest_pgdata, int num_threads)
44
43
PGNodeInfo source_node_info ;
45
44
bool no_sync = false;
46
45
bool backup_logs = false;
47
- bool dest_pgdata_is_empty = dir_is_empty (dest_pgdata , FIO_LOCAL_HOST );
48
46
49
47
source_conn = catchup_collect_info (& source_node_info , source_pgdata , dest_pgdata );
50
- catchup_preflight_checks (& source_node_info , source_conn , source_pgdata , dest_pgdata , dest_pgdata_is_empty );
48
+ catchup_preflight_checks (& source_node_info , source_conn , source_pgdata , dest_pgdata );
51
49
52
50
do_catchup_instance (source_pgdata , dest_pgdata , source_conn , & source_node_info ,
53
- no_sync , backup_logs , dest_pgdata_is_empty );
51
+ no_sync , backup_logs );
54
52
55
53
//REVIEW: Are we going to do that before release?
56
54
/* TODO: show the amount of transfered data in bytes and calculate incremental ratio */
@@ -66,6 +64,7 @@ static PGconn *
66
64
catchup_collect_info (PGNodeInfo * source_node_info , const char * source_pgdata , const char * dest_pgdata )
67
65
{
68
66
PGconn * source_conn ;
67
+
69
68
/* Initialize PGInfonode */
70
69
pgNodeInit (source_node_info );
71
70
@@ -85,8 +84,6 @@ catchup_collect_info(PGNodeInfo *source_node_info, const char *source_pgdata, co
85
84
/* Do some compatibility checks and fill basic info about PG instance */
86
85
source_conn = pgdata_basic_setup (instance_config .conn_opt , source_node_info );
87
86
88
- //REVIEW Please adjust the comment. Do we need this code for catchup at all?
89
- /* below perform checks specific for backup command */
90
87
#if PG_VERSION_NUM >= 110000
91
88
if (!RetrieveWalSegSize (source_conn ))
92
89
elog (ERROR , "Failed to retrieve wal_segment_size" );
@@ -122,10 +119,42 @@ catchup_collect_info(PGNodeInfo *source_node_info, const char *source_pgdata, co
122
119
*/
123
120
static void
124
121
catchup_preflight_checks (PGNodeInfo * source_node_info , PGconn * source_conn ,
125
- const char * source_pgdata , const char * dest_pgdata , bool dest_pgdata_is_empty )
122
+ const char * source_pgdata , const char * dest_pgdata )
126
123
{
127
- //REVIEW Let's fix it before release.
128
- // TODO: add sanity check that source PGDATA is not empty
124
+ /* TODO
125
+ * gsmol - fallback to FULL mode if dest PGDATA is empty
126
+ * kulaginm -- I think this is a harmful feature. If user requested an incremental catchup, then
127
+ * he expects that this will be done quickly and efficiently. If, for example, he made a mistake
128
+ * 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
+ * I propose in future versions to offer a backup_mode auto, in which we will look to the dest_dir
131
+ * and decide which of the modes will be the most effective.
132
+ * I.e.:
133
+ * if(requested_backup_mode == BACKUP_MODE_DIFF_AUTO)
134
+ * {
135
+ * if(dest_pgdata_is_empty)
136
+ * backup_mode = BACKUP_MODE_FULL;
137
+ * else
138
+ * if(ptrack supported and applicable)
139
+ * backup_mode = BACKUP_MODE_DIFF_PTRACK;
140
+ * else
141
+ * backup_mode = BACKUP_MODE_DIFF_DELTA;
142
+ * }
143
+ */
144
+
145
+ if (dir_is_empty (dest_pgdata , FIO_LOCAL_HOST ))
146
+ {
147
+ if (current .backup_mode == BACKUP_MODE_DIFF_PTRACK ||
148
+ current .backup_mode == BACKUP_MODE_DIFF_DELTA )
149
+ elog (ERROR , "\"%s\" is empty but incremental catchup mode requested." ,
150
+ dest_pgdata );
151
+ }
152
+ else /* dest dir not empty */
153
+ {
154
+ if (current .backup_mode == BACKUP_MODE_FULL )
155
+ elog (ERROR , "Can't perform full catchup into not empty directory \"%s\"." ,
156
+ dest_pgdata );
157
+ }
129
158
130
159
/* Check that connected PG instance and source PGDATA are the same */
131
160
check_system_identifiers (source_conn , source_pgdata );
@@ -141,7 +170,7 @@ catchup_preflight_checks(PGNodeInfo *source_node_info, PGconn *source_conn,
141
170
elog (ERROR , "Ptrack is disabled" );
142
171
}
143
172
144
- if (! dest_pgdata_is_empty &&
173
+ if (current . backup_mode != BACKUP_MODE_FULL &&
145
174
check_incremental_compatibility (dest_pgdata ,
146
175
instance_config .system_identifier ,
147
176
INCR_CHECKSUM ) != DEST_OK )
@@ -157,12 +186,10 @@ catchup_preflight_checks(PGNodeInfo *source_node_info, PGconn *source_conn,
157
186
/*
158
187
* TODO:
159
188
* - add description
160
- * - fallback to FULL mode if dest PGDATA is empty
161
189
*/
162
190
static void
163
191
do_catchup_instance (const char * source_pgdata , const char * dest_pgdata , PGconn * source_conn ,
164
- PGNodeInfo * source_node_info , bool no_sync , bool backup_logs ,
165
- bool dest_pgdata_is_empty )
192
+ PGNodeInfo * source_node_info , bool no_sync , bool backup_logs )
166
193
{
167
194
int i ;
168
195
char dest_xlog_path [MAXPGPATH ];
@@ -208,9 +235,8 @@ do_catchup_instance(const char *source_pgdata, const char *dest_pgdata, PGconn *
208
235
209
236
//REVIEW I wonder, if we can move this piece above and call before pg_start backup()?
210
237
//It seems to be a part of setup phase.
211
- if (!dest_pgdata_is_empty &&
212
- (current .backup_mode == BACKUP_MODE_DIFF_PTRACK ||
213
- current .backup_mode == BACKUP_MODE_DIFF_DELTA ))
238
+ if (current .backup_mode == BACKUP_MODE_DIFF_PTRACK ||
239
+ current .backup_mode == BACKUP_MODE_DIFF_DELTA )
214
240
{
215
241
dest_filelist = parray_new ();
216
242
dir_list_file (dest_filelist , dest_pgdata ,
@@ -423,9 +449,8 @@ do_catchup_instance(const char *source_pgdata, const char *dest_pgdata, PGconn *
423
449
* remove absent source files in dest (dropped tables, etc...)
424
450
* note: global/pg_control will also be deleted here
425
451
*/
426
- if (!dest_pgdata_is_empty &&
427
- (current .backup_mode == BACKUP_MODE_DIFF_PTRACK ||
428
- current .backup_mode == BACKUP_MODE_DIFF_DELTA ))
452
+ if (current .backup_mode == BACKUP_MODE_DIFF_PTRACK ||
453
+ current .backup_mode == BACKUP_MODE_DIFF_DELTA )
429
454
{
430
455
elog (INFO , "Removing redundant files in destination directory" );
431
456
parray_qsort (dest_filelist , pgFileCompareRelPathWithExternalDesc );
@@ -676,7 +701,7 @@ do_catchup_instance(const char *source_pgdata, const char *dest_pgdata, PGconn *
676
701
}
677
702
678
703
/* Cleanup */
679
- if (! dest_pgdata_is_empty && dest_filelist )
704
+ if (dest_filelist )
680
705
{
681
706
parray_walk (dest_filelist , pgFileFree );
682
707
parray_free (dest_filelist );
0 commit comments