Skip to content

Commit f6e7be6

Browse files
committed
simplify grabbing and releasing shared lock
1 parent 818ef36 commit f6e7be6

File tree

1 file changed

+66
-97
lines changed

1 file changed

+66
-97
lines changed

src/catalog.c

Lines changed: 66 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ static bool backup_lock_exit_hook_registered = false;
2828
static parray *locks = NULL;
2929

3030
static int grab_excl_lock_file(const char *backup_dir, const char *backup_id, bool strict);
31-
static int grab_shared_lock_file(pgBackup *backup);
31+
static int grab_shared_lock_file(const char *backup_dir);
3232
static int wait_shared_owners(pgBackup *backup);
3333

3434

@@ -231,7 +231,7 @@ lock_backup(pgBackup *backup, bool strict, bool exclusive)
231231
if (exclusive)
232232
rc = wait_shared_owners(backup);
233233
else
234-
rc = grab_shared_lock_file(backup);
234+
rc = grab_shared_lock_file(backup->root_dir);
235235

236236
if (rc != 0)
237237
{
@@ -600,26 +600,21 @@ wait_shared_owners(pgBackup *backup)
600600
return 0;
601601
}
602602

603+
#define FT_SLICE pid
604+
#define FT_SLICE_TYPE pid_t
605+
#include <ft_array.inc.h>
606+
603607
/*
604-
* Lock backup in shared mode
605-
* 0 - successs
606-
* 1 - fail
608+
* returns array of pids stored in shared lock file and still alive.
609+
* It excludes our own pid, so no need to exclude it explicitely.
607610
*/
608-
int
609-
grab_shared_lock_file(pgBackup *backup)
611+
static ft_arr_pid_t
612+
read_shared_lock_file(const char *lock_file)
610613
{
611614
FILE *fp_in = NULL;
612-
FILE *fp_out = NULL;
613615
char buf_in[256];
614616
pid_t encoded_pid;
615-
char lock_file[MAXPGPATH];
616-
617-
char buffer[8192]; /*TODO: should be enough, but maybe malloc+realloc is better ? */
618-
char lock_file_tmp[MAXPGPATH];
619-
int buffer_len = 0;
620-
621-
join_path_components(lock_file, backup->root_dir, BACKUP_RO_LOCK_FILE);
622-
snprintf(lock_file_tmp, MAXPGPATH, "%s%s", lock_file, "tmp");
617+
ft_arr_pid_t pids = ft_arr_init();
623618

624619
/* open already existing lock files */
625620
fp_in = fopen(lock_file, "r");
@@ -629,7 +624,7 @@ grab_shared_lock_file(pgBackup *backup)
629624
/* read PIDs of owners */
630625
while (fp_in && fgets(buf_in, sizeof(buf_in), fp_in))
631626
{
632-
encoded_pid = atoi(buf_in);
627+
encoded_pid = (pid_t)atoll(buf_in);
633628
if (encoded_pid <= 0)
634629
{
635630
elog(WARNING, "Bogus data in lock file \"%s\": \"%s\"", lock_file, buf_in);
@@ -645,11 +640,11 @@ grab_shared_lock_file(pgBackup *backup)
645640
* Somebody is still using this backup in shared mode,
646641
* copy this pid into a new file.
647642
*/
648-
buffer_len += snprintf(buffer+buffer_len, 4096, "%llu\n", (long long)encoded_pid);
643+
ft_arr_pid_push(&pids, encoded_pid);
649644
}
650645
else if (errno != ESRCH)
651646
elog(ERROR, "Failed to send signal 0 to a process %lld: %s",
652-
(long long)encoded_pid, strerror(errno));
647+
(long long)encoded_pid, strerror(errno));
653648
}
654649

655650
if (fp_in)
@@ -659,31 +654,69 @@ grab_shared_lock_file(pgBackup *backup)
659654
fclose(fp_in);
660655
}
661656

657+
return pids;
658+
}
659+
660+
static void
661+
write_shared_lock_file(const char *lock_file, ft_arr_pid_t pids)
662+
{
663+
FILE *fp_out = NULL;
664+
char lock_file_tmp[MAXPGPATH];
665+
ssize_t i;
666+
667+
snprintf(lock_file_tmp, MAXPGPATH, "%s%s", lock_file, "tmp");
668+
662669
fp_out = fopen(lock_file_tmp, "w");
663670
if (fp_out == NULL)
664671
{
665672
if (errno == EROFS)
666-
return 0;
673+
return;
667674

668675
elog(ERROR, "Cannot open temp lock file \"%s\": %s", lock_file_tmp, strerror(errno));
669676
}
670677

671-
/* add my own pid */
672-
buffer_len += snprintf(buffer+buffer_len, sizeof(buffer), "%llu\n", (long long)my_pid);
673-
674678
/* write out the collected PIDs to temp lock file */
675-
fwrite(buffer, 1, buffer_len, fp_out);
679+
for (i = 0; i < pids.len; i++)
680+
fprintf(fp_out, "%lld\n", (long long)ft_arr_pid_at(&pids, i));
681+
fflush(fp_out);
676682

677683
if (ferror(fp_out))
684+
{
685+
fclose(fp_out);
686+
remove(lock_file_tmp);
678687
elog(ERROR, "Cannot write to lock file: \"%s\"", lock_file_tmp);
688+
}
679689

680690
if (fclose(fp_out) != 0)
691+
{
692+
remove(lock_file_tmp);
681693
elog(ERROR, "Cannot close temp lock file \"%s\": %s", lock_file_tmp, strerror(errno));
694+
}
682695

683696
if (rename(lock_file_tmp, lock_file) < 0)
684697
elog(ERROR, "Cannot rename file \"%s\" to \"%s\": %s",
685-
lock_file_tmp, lock_file, strerror(errno));
698+
lock_file_tmp, lock_file, strerror(errno));
699+
}
686700

701+
/*
702+
* Lock backup in shared mode
703+
* 0 - successs
704+
* 1 - fail
705+
*/
706+
int
707+
grab_shared_lock_file(const char *backup_dir)
708+
{
709+
char lock_file[MAXPGPATH];
710+
ft_arr_pid_t pids;
711+
712+
join_path_components(lock_file, backup_dir, BACKUP_RO_LOCK_FILE);
713+
714+
pids = read_shared_lock_file(lock_file);
715+
/* add my own pid */
716+
ft_arr_pid_push(&pids, my_pid);
717+
718+
write_shared_lock_file(lock_file, pids);
719+
ft_arr_pid_free(&pids);
687720
return 0;
688721
}
689722

@@ -723,87 +756,23 @@ release_excl_lock_file(const char *backup_dir)
723756
void
724757
release_shared_lock_file(const char *backup_dir)
725758
{
726-
FILE *fp_in = NULL;
727-
FILE *fp_out = NULL;
728-
char buf_in[256];
729-
pid_t encoded_pid;
730759
char lock_file[MAXPGPATH];
731-
732-
char buffer[8192]; /*TODO: should be enough, but maybe malloc+realloc is better ? */
733-
char lock_file_tmp[MAXPGPATH];
734-
int buffer_len = 0;
760+
ft_arr_pid_t pids;
735761

736762
join_path_components(lock_file, backup_dir, BACKUP_RO_LOCK_FILE);
737-
snprintf(lock_file_tmp, MAXPGPATH, "%s%s", lock_file, "tmp");
738763

739-
/* open lock file */
740-
fp_in = fopen(lock_file, "r");
741-
if (fp_in == NULL)
764+
pids = read_shared_lock_file(lock_file);
765+
/* read_shared_lock_file already had deleted my own pid */
766+
if (pids.len == 0)
742767
{
743-
if (errno == ENOENT)
744-
return;
745-
else
746-
elog(ERROR, "Cannot open lock file \"%s\": %s", lock_file, strerror(errno));
747-
}
748-
749-
/* read PIDs of owners */
750-
while (fgets(buf_in, sizeof(buf_in), fp_in))
751-
{
752-
encoded_pid = atoi(buf_in);
753-
754-
if (encoded_pid <= 0)
755-
{
756-
elog(WARNING, "Bogus data in lock file \"%s\": \"%s\"", lock_file, buf_in);
757-
continue;
758-
}
759-
760-
/* remove my pid */
761-
if (encoded_pid == my_pid)
762-
continue;
763-
764-
if (kill(encoded_pid, 0) == 0)
765-
{
766-
/*
767-
* Somebody is still using this backup in shared mode,
768-
* copy this pid into a new file.
769-
*/
770-
buffer_len += snprintf(buffer+buffer_len, 4096, "%llu\n", (long long)encoded_pid);
771-
}
772-
else if (errno != ESRCH)
773-
elog(ERROR, "Failed to send signal 0 to a process %lld: %s",
774-
(long long)encoded_pid, strerror(errno));
775-
}
776-
777-
if (ferror(fp_in))
778-
elog(ERROR, "Cannot read from lock file: \"%s\"", lock_file);
779-
fclose(fp_in);
780-
781-
/* if there is no active pid left, then there is nothing to do */
782-
if (buffer_len == 0)
783-
{
784-
if (fio_remove(FIO_BACKUP_HOST, lock_file, false) != 0)
768+
ft_arr_pid_free(&pids);
769+
if (remove(lock_file) != 0)
785770
elog(ERROR, "Cannot remove shared lock file \"%s\": %s", lock_file, strerror(errno));
786771
return;
787772
}
788773

789-
fp_out = fopen(lock_file_tmp, "w");
790-
if (fp_out == NULL)
791-
elog(ERROR, "Cannot open temp lock file \"%s\": %s", lock_file_tmp, strerror(errno));
792-
793-
/* write out the collected PIDs to temp lock file */
794-
fwrite(buffer, 1, buffer_len, fp_out);
795-
796-
if (ferror(fp_out))
797-
elog(ERROR, "Cannot write to lock file: \"%s\"", lock_file_tmp);
798-
799-
if (fclose(fp_out) != 0)
800-
elog(ERROR, "Cannot close temp lock file \"%s\": %s", lock_file_tmp, strerror(errno));
801-
802-
if (rename(lock_file_tmp, lock_file) < 0)
803-
elog(ERROR, "Cannot rename file \"%s\" to \"%s\": %s",
804-
lock_file_tmp, lock_file, strerror(errno));
805-
806-
return;
774+
write_shared_lock_file(lock_file, pids);
775+
ft_arr_pid_free(&pids);
807776
}
808777

809778
/*

0 commit comments

Comments
 (0)