@@ -21,23 +21,74 @@ static const char *backupModes[] = {"", "PAGE", "PTRACK", "DELTA", "FULL"};
21
21
static pgBackup * readBackupControlFile (const char * path );
22
22
23
23
static bool exit_hook_registered = false;
24
- static char lock_file [ MAXPGPATH ] ;
24
+ static parray * lock_files = NULL ;
25
25
26
26
static void
27
27
unlink_lock_atexit (void )
28
28
{
29
- int res ;
30
- res = unlink (lock_file );
31
- if (res != 0 && res != ENOENT )
32
- elog (WARNING , "%s: %s" , lock_file , strerror (errno ));
29
+ int i ;
30
+
31
+ if (lock_files == NULL )
32
+ return ;
33
+
34
+ for (i = 0 ; i < parray_num (lock_files ); i ++ )
35
+ {
36
+ char * lock_file = (char * ) parray_get (lock_files , i );
37
+ int res ;
38
+
39
+ res = unlink (lock_file );
40
+ if (res != 0 && res != ENOENT )
41
+ elog (WARNING , "%s: %s" , lock_file , strerror (errno ));
42
+ }
43
+
44
+ parray_walk (lock_files , pfree );
45
+ parray_free (lock_files );
46
+ lock_files = NULL ;
33
47
}
34
48
35
49
/*
36
- * Create a lockfile.
50
+ * Read backup meta information from BACKUP_CONTROL_FILE.
51
+ * If no backup matches, return NULL.
52
+ */
53
+ pgBackup *
54
+ read_backup (time_t timestamp )
55
+ {
56
+ pgBackup tmp ;
57
+ char conf_path [MAXPGPATH ];
58
+
59
+ tmp .start_time = timestamp ;
60
+ pgBackupGetPath (& tmp , conf_path , lengthof (conf_path ), BACKUP_CONTROL_FILE );
61
+
62
+ return readBackupControlFile (conf_path );
63
+ }
64
+
65
+ /*
66
+ * Save the backup status into BACKUP_CONTROL_FILE.
67
+ *
68
+ * We need to reread the backup using its ID and save it changing only its
69
+ * status.
37
70
*/
38
71
void
39
- catalog_lock (void )
72
+ write_backup_status (pgBackup * backup , BackupStatus status )
73
+ {
74
+ pgBackup * tmp ;
75
+
76
+ tmp = read_backup (backup -> start_time );
77
+
78
+ backup -> status = status ;
79
+ tmp -> status = backup -> status ;
80
+ write_backup (tmp );
81
+
82
+ pgBackupFree (tmp );
83
+ }
84
+
85
+ /*
86
+ * Create exclusive lockfile in the backup's directory.
87
+ */
88
+ bool
89
+ lock_backup (pgBackup * backup )
40
90
{
91
+ char lock_file [MAXPGPATH ];
41
92
int fd ;
42
93
char buffer [MAXPGPATH * 2 + 256 ];
43
94
int ntries ;
@@ -46,7 +97,7 @@ catalog_lock(void)
46
97
pid_t my_pid ,
47
98
my_p_pid ;
48
99
49
- join_path_components ( lock_file , backup_instance_path , BACKUP_CATALOG_PID );
100
+ pgBackupGetPath ( backup , lock_file , lengthof ( lock_file ) , BACKUP_CATALOG_PID );
50
101
51
102
/*
52
103
* If the PID in the lockfile is our own PID or our parent's or
@@ -99,7 +150,7 @@ catalog_lock(void)
99
150
* Couldn't create the pid file. Probably it already exists.
100
151
*/
101
152
if ((errno != EEXIST && errno != EACCES ) || ntries > 100 )
102
- elog (ERROR , "could not create lock file \"%s\": %s" ,
153
+ elog (ERROR , "Could not create lock file \"%s\": %s" ,
103
154
lock_file , strerror (errno ));
104
155
105
156
/*
@@ -111,22 +162,22 @@ catalog_lock(void)
111
162
{
112
163
if (errno == ENOENT )
113
164
continue ; /* race condition; try again */
114
- elog (ERROR , "could not open lock file \"%s\": %s" ,
165
+ elog (ERROR , "Could not open lock file \"%s\": %s" ,
115
166
lock_file , strerror (errno ));
116
167
}
117
168
if ((len = read (fd , buffer , sizeof (buffer ) - 1 )) < 0 )
118
- elog (ERROR , "could not read lock file \"%s\": %s" ,
169
+ elog (ERROR , "Could not read lock file \"%s\": %s" ,
119
170
lock_file , strerror (errno ));
120
171
close (fd );
121
172
122
173
if (len == 0 )
123
- elog (ERROR , "lock file \"%s\" is empty" , lock_file );
174
+ elog (ERROR , "Lock file \"%s\" is empty" , lock_file );
124
175
125
176
buffer [len ] = '\0' ;
126
177
encoded_pid = atoi (buffer );
127
178
128
179
if (encoded_pid <= 0 )
129
- elog (ERROR , "bogus data in lock file \"%s\": \"%s\"" ,
180
+ elog (ERROR , "Bogus data in lock file \"%s\": \"%s\"" ,
130
181
lock_file , buffer );
131
182
132
183
/*
@@ -140,9 +191,21 @@ catalog_lock(void)
140
191
*/
141
192
if (encoded_pid != my_pid && encoded_pid != my_p_pid )
142
193
{
143
- if (kill (encoded_pid , 0 ) == 0 ||
144
- (errno != ESRCH && errno != EPERM ))
145
- elog (ERROR , "lock file \"%s\" already exists" , lock_file );
194
+ if (kill (encoded_pid , 0 ) == 0 )
195
+ {
196
+ elog (WARNING , "Process %d is using backup %s and still is running" ,
197
+ encoded_pid , base36enc (backup -> start_time ));
198
+ return false;
199
+ }
200
+ else
201
+ {
202
+ if (errno == ESRCH )
203
+ elog (WARNING , "Process %d which used backup %s no longer exists" ,
204
+ encoded_pid , base36enc (backup -> start_time ));
205
+ else
206
+ elog (ERROR , "Failed to send signal 0 to a process %d: %s" ,
207
+ encoded_pid , strerror (errno ));
208
+ }
146
209
}
147
210
148
211
/*
@@ -151,7 +214,7 @@ catalog_lock(void)
151
214
* would-be creators.
152
215
*/
153
216
if (unlink (lock_file ) < 0 )
154
- elog (ERROR , "could not remove old lock file \"%s\": %s" ,
217
+ elog (ERROR , "Could not remove old lock file \"%s\": %s" ,
155
218
lock_file , strerror (errno ));
156
219
}
157
220
@@ -169,7 +232,7 @@ catalog_lock(void)
169
232
unlink (lock_file );
170
233
/* if write didn't set errno, assume problem is no disk space */
171
234
errno = save_errno ? save_errno : ENOSPC ;
172
- elog (ERROR , "could not write lock file \"%s\": %s" ,
235
+ elog (ERROR , "Could not write lock file \"%s\": %s" ,
173
236
lock_file , strerror (errno ));
174
237
}
175
238
if (fsync (fd ) != 0 )
@@ -179,7 +242,7 @@ catalog_lock(void)
179
242
close (fd );
180
243
unlink (lock_file );
181
244
errno = save_errno ;
182
- elog (ERROR , "could not write lock file \"%s\": %s" ,
245
+ elog (ERROR , "Could not write lock file \"%s\": %s" ,
183
246
lock_file , strerror (errno ));
184
247
}
185
248
if (close (fd ) != 0 )
@@ -188,7 +251,7 @@ catalog_lock(void)
188
251
189
252
unlink (lock_file );
190
253
errno = save_errno ;
191
- elog (ERROR , "could not write lock file \"%s\": %s" ,
254
+ elog (ERROR , "Culd not write lock file \"%s\": %s" ,
192
255
lock_file , strerror (errno ));
193
256
}
194
257
@@ -200,41 +263,13 @@ catalog_lock(void)
200
263
atexit (unlink_lock_atexit );
201
264
exit_hook_registered = true;
202
265
}
203
- }
204
266
205
- /*
206
- * Read backup meta information from BACKUP_CONTROL_FILE.
207
- * If no backup matches, return NULL.
208
- */
209
- pgBackup *
210
- read_backup (time_t timestamp )
211
- {
212
- pgBackup tmp ;
213
- char conf_path [MAXPGPATH ];
267
+ /* Use parray so that the lock files are unlinked in a loop */
268
+ if (lock_files == NULL )
269
+ lock_files = parray_new ();
270
+ parray_append (lock_files , pgut_strdup (lock_file ));
214
271
215
- tmp .start_time = timestamp ;
216
- pgBackupGetPath (& tmp , conf_path , lengthof (conf_path ), BACKUP_CONTROL_FILE );
217
-
218
- return readBackupControlFile (conf_path );
219
- }
220
-
221
- /*
222
- * Save the backup status into BACKUP_CONTROL_FILE.
223
- *
224
- * We need to reread the backup using its ID and save it changing only its
225
- * status.
226
- */
227
- void
228
- write_backup_status (pgBackup * backup )
229
- {
230
- pgBackup * tmp ;
231
-
232
- tmp = read_backup (backup -> start_time );
233
-
234
- tmp -> status = backup -> status ;
235
- write_backup (tmp );
236
-
237
- pgBackupFree (tmp );
272
+ return true;
238
273
}
239
274
240
275
/*
@@ -381,6 +416,31 @@ catalog_get_backup_list(time_t requested_backup_id)
381
416
return NULL ;
382
417
}
383
418
419
+ /*
420
+ * Lock list of backups. Function goes in backward direction.
421
+ */
422
+ void
423
+ catalog_lock_backup_list (parray * backup_list , int from_idx , int to_idx )
424
+ {
425
+ int start_idx ,
426
+ end_idx ;
427
+ int i ;
428
+
429
+ if (parray_num (backup_list ) == 0 )
430
+ return ;
431
+
432
+ start_idx = Max (from_idx , to_idx );
433
+ end_idx = Min (from_idx , to_idx );
434
+
435
+ for (i = start_idx ; i >= end_idx ; i -- )
436
+ {
437
+ pgBackup * backup = (pgBackup * ) parray_get (backup_list , i );
438
+ if (!lock_backup (backup ))
439
+ elog (ERROR , "Cannot lock backup %s directory" ,
440
+ base36enc (backup -> start_time ));
441
+ }
442
+ }
443
+
384
444
/*
385
445
* Find the last completed backup on given timeline
386
446
*/
0 commit comments