@@ -1198,6 +1198,93 @@ def test_continue_failed_merge_with_corrupted_delta_backup(self):
1198
1198
# Clean after yourself
1199
1199
self .del_test_dir (module_name ,fname )
1200
1200
1201
+ def test_continue_failed_merge_2 (self ):
1202
+ """
1203
+ Check that failed MERGE on delete can be continued
1204
+ """
1205
+ fname = self .id ().split ('.' )[3 ]
1206
+ backup_dir = os .path .join (self .tmp_path ,module_name ,fname ,'backup' )
1207
+ node = self .make_simple_node (
1208
+ base_dir = os .path .join (module_name ,fname ,'node' ),
1209
+ set_replication = True ,initdb_params = ['--data-checksums' ],
1210
+ pg_options = {
1211
+ 'wal_level' :'replica'
1212
+ }
1213
+ )
1214
+
1215
+ self .init_pb (backup_dir )
1216
+ self .add_instance (backup_dir ,'node' ,node )
1217
+ self .set_archiving (backup_dir ,'node' ,node )
1218
+ node .slow_start ()
1219
+
1220
+ # FULL backup
1221
+ self .backup_node (backup_dir ,'node' ,node )
1222
+
1223
+ node .safe_psql (
1224
+ "postgres" ,
1225
+ "create table t_heap as select i as id,"
1226
+ " md5(i::text) as text, md5(i::text)::tsvector as tsvector"
1227
+ " from generate_series(0,1000) i"
1228
+ )
1229
+
1230
+ # DELTA BACKUP
1231
+ self .backup_node (
1232
+ backup_dir ,'node' ,node ,backup_type = 'delta'
1233
+ )
1234
+
1235
+ node .safe_psql (
1236
+ "postgres" ,
1237
+ "delete from t_heap"
1238
+ )
1239
+
1240
+ node .safe_psql (
1241
+ "postgres" ,
1242
+ "vacuum t_heap"
1243
+ )
1244
+
1245
+ # DELTA BACKUP
1246
+ self .backup_node (
1247
+ backup_dir ,'node' ,node ,backup_type = 'delta'
1248
+ )
1249
+
1250
+ if self .paranoia :
1251
+ pgdata = self .pgdata_content (node .data_dir )
1252
+
1253
+ backup_id = self .show_pb (backup_dir ,"node" )[2 ]["id" ]
1254
+
1255
+ gdb = self .merge_backup (backup_dir ,"node" ,backup_id ,gdb = True )
1256
+
1257
+ gdb .set_breakpoint ('pgFileDelete' )
1258
+ gdb .run_until_break ()
1259
+
1260
+ if gdb .continue_execution_until_break (20 )!= 'breakpoint-hit' :
1261
+ print ('Failed to hit breakpoint' )
1262
+ exit (1 )
1263
+
1264
+ gdb ._execute ('signal SIGKILL' )
1265
+
1266
+ print (self .show_pb (backup_dir ,as_text = True ,as_json = False ))
1267
+
1268
+ backup_id_deleted = self .show_pb (backup_dir ,"node" )[1 ]["id" ]
1269
+
1270
+ # Try to continue failed MERGE
1271
+ try :
1272
+ self .merge_backup (backup_dir ,"node" ,backup_id )
1273
+ self .assertEqual (
1274
+ 1 ,0 ,
1275
+ "Expecting Error because of backup corruption.\n "
1276
+ "Output: {0}\n CMD: {1}" .format (
1277
+ repr (self .output ),self .cmd ))
1278
+ except ProbackupException as e :
1279
+ self .assertTrue (
1280
+ "ERROR: Backup {0} has status: DELETING" .format (
1281
+ backup_id_deleted )in e .message ,
1282
+ '\n Unexpected Error Message: {0}\n CMD: {1}' .format (
1283
+ repr (e .message ),self .cmd ))
1284
+
1285
+ # Clean after yourself
1286
+ self .del_test_dir (module_name ,fname )
1287
+
1201
1288
# 1. always use parent link when merging (intermediates may be from different chain)
1202
1289
# 2. page backup we are merging with may disappear after failed merge,
1203
1290
# it should not be possible to continue merge after that