@@ -1021,16 +1021,57 @@ do_delete_instance(void)
10211021 return 0 ;
10221022}
10231023
1024+ /* checks that backup childs has status like parent */
1025+ bool checkChilds (parray * backup_list , time_t backup_id )
1026+ {
1027+ int i ;
1028+ pgBackup * target_backup = NULL ;
1029+ pgBackup * backup ;
1030+ /* search target bakcup */
1031+ for (i = 0 ; i < parray_num (backup_list ); i ++ )
1032+ {
1033+ backup = (pgBackup * )parray_get (backup_list , i );
1034+ if (backup -> start_time == backup_id )
1035+ {
1036+ target_backup = backup ;
1037+ break ;
1038+ }
1039+ }
1040+ if (target_backup == NULL ) return false;
1041+
1042+ /* check childs */
1043+ for (i = 0 ; i < parray_num (backup_list ); i ++ )
1044+ {
1045+ backup = (pgBackup * )parray_get (backup_list , i );
1046+ /* check if backup is descendant of delete target */
1047+ if (is_parent (target_backup -> start_time , backup , false))
1048+ {
1049+ if (backup -> status != target_backup -> status ){
1050+ elog (INFO , "Skip deleting the backup %s because the backup has children with a different status" ,
1051+ base36enc (target_backup -> start_time ));
1052+ return false;
1053+ }
1054+ /* recursive call */
1055+ if (!checkChilds (backup_list , backup -> start_time )) return false;
1056+ }
1057+ }
1058+ return true;
1059+ }
1060+
10241061/* Delete all backups of given status in instance */
10251062void
10261063do_delete_status (InstanceConfig * instance_config , const char * status )
10271064{
1028- parray * backup_list ;
1065+ parray * backup_list , * delete_list ; ;
10291066 int i ;
10301067 const char * pretty_status ;
1031- int n_deleted = 0 ;
1068+ int n_deleted = 0 , n_found = 0 ;
1069+ size_t size_to_delete = 0 ;
1070+ char size_to_delete_pretty [20 ];
1071+ pgBackup * backup ;
10321072
10331073 BackupStatus status_for_delete = str2status (status );
1074+ delete_list = parray_new ();
10341075
10351076 if (status_for_delete == BACKUP_STATUS_INVALID )
10361077 elog (ERROR , "Unknown value for '--status' option: '%s'" , status );
@@ -1052,28 +1093,63 @@ do_delete_status(InstanceConfig *instance_config, const char *status)
10521093
10531094 elog (INFO , "Deleting all backups with status '%s'" , pretty_status );
10541095
1055- /* Delete all backups with specified status */
1096+ /* Selects backups for deleting to delete_list array. Will delete all backups with specified status */
10561097 for (i = 0 ; i < parray_num (backup_list ); i ++ )
10571098 {
1058- pgBackup * backup = (pgBackup * ) parray_get (backup_list , i );
1099+ backup = (pgBackup * ) parray_get (backup_list , i );
10591100
10601101 if (backup -> status == status_for_delete )
10611102 {
1062- lock_backup (backup );
1063- delete_backup_files (backup );
1103+
1104+ n_found ++ ;
1105+ if (!checkChilds (backup_list , backup -> start_time )) continue ;
1106+
1107+ elog (dry_run ? INFO : LOG , "Backup %s %s be deleted" ,
1108+ base36enc (backup -> start_time ), dry_run ? "can" : "will" );
1109+ size_to_delete += backup -> data_bytes ;
1110+ if (backup -> stream )
1111+ size_to_delete += backup -> wal_bytes ;
1112+ if (!dry_run ){
1113+ parray_append (delete_list , backup );
1114+ }
10641115 n_deleted ++ ;
1116+
10651117 }
10661118 }
10671119
1068- if (n_deleted > 0 )
1120+ /* Inform about data size to free */
1121+ if (size_to_delete >= 0 )
1122+ {
1123+ pretty_size (size_to_delete , size_to_delete_pretty , lengthof (size_to_delete_pretty ));
1124+ elog (INFO , "Resident data size to free by delete of %i backups: %s" ,
1125+ n_deleted , size_to_delete_pretty );
1126+ }
1127+
1128+ /* delete selected backups */
1129+ if (!dry_run )
1130+ {
1131+ for (i = 0 ; i < parray_num (delete_list ); i ++ )
1132+ {
1133+ backup = (pgBackup * )parray_get (delete_list , i );
1134+ if (lock_backup (backup ))
1135+ {
1136+ delete_backup_files (backup );
1137+ }
1138+ else n_deleted -- ;
1139+ }
10691140 elog (INFO , "Successfully deleted %i %s with status '%s' from instance '%s'" ,
10701141 n_deleted , n_deleted == 1 ? "backup" : "backups" ,
10711142 pretty_status , instance_config -> name );
1072- else
1143+
1144+ }
1145+
1146+
1147+ if (n_found == 0 )
10731148 elog (WARNING , "Instance '%s' has no backups with status '%s'" ,
10741149 instance_config -> name , pretty_status );
10751150
10761151 /* Cleanup */
1152+ parray_free (delete_list );
10771153 parray_walk (backup_list , pgBackupFree );
10781154 parray_free (backup_list );
10791155}
0 commit comments