reftable/stack: register compacted tables as tempfiles

We do not register tables resulting from stack compaction with the tempfile API. Those tables will thus not be deleted in case Git gets killed. Refactor the code to register compacted tables as tempfiles. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Mar 7, 2024 at 14:10 UTC 60c4c425155c61a081cc035240ee649aa2cb2e37
1 file changed +30 -24
reftable/stack.c
+30 -24
@@ -827,51 +827,56 @@ uint64_t reftable_stack_next_update_index(struct reftable_stack *st)
827
828 static int stack_compact_locked(struct reftable_stack *st,
829 size_t first, size_t last,
830 - struct strbuf *temp_tab,
831 - struct reftable_log_expiry_config *config)
830 + struct reftable_log_expiry_config *config,
831 + struct tempfile **tab_file_out)
832 {
833 struct strbuf next_name = STRBUF_INIT;
834 - int tab_fd = -1;
834 + struct strbuf tab_file_path = STRBUF_INIT;
835 struct reftable_writer *wr = NULL;
836 - int err = 0;
836 + struct tempfile *tab_file;
837 + int tab_fd, err = 0;
838
839 format_name(&next_name,
840 reftable_reader_min_update_index(st->readers[first]),
841 reftable_reader_max_update_index(st->readers[last]));
842 + stack_filename(&tab_file_path, st, next_name.buf);
843 + strbuf_addstr(&tab_file_path, ".temp.XXXXXX");
844
842 - stack_filename(temp_tab, st, next_name.buf);
843 - strbuf_addstr(temp_tab, ".temp.XXXXXX");
845 + tab_file = mks_tempfile(tab_file_path.buf);
846 + if (!tab_file) {
847 + err = REFTABLE_IO_ERROR;
848 + goto done;
849 + }
850 + tab_fd = get_tempfile_fd(tab_file);
851
845 - tab_fd = mkstemp(temp_tab->buf);
852 if (st->config.default_permissions &&
847 - chmod(temp_tab->buf, st->config.default_permissions) < 0) {
853 + chmod(get_tempfile_path(tab_file), st->config.default_permissions) < 0) {
854 err = REFTABLE_IO_ERROR;
855 goto done;
856 }
857
852 - wr = reftable_new_writer(reftable_fd_write, reftable_fd_flush, &tab_fd, &st->config);
853 -
858 + wr = reftable_new_writer(reftable_fd_write, reftable_fd_flush,
859 + &tab_fd, &st->config);
860 err = stack_write_compact(st, wr, first, last, config);
861 if (err < 0)
862 goto done;
863 +
864 err = reftable_writer_close(wr);
865 if (err < 0)
866 goto done;
867
861 - err = close(tab_fd);
862 - tab_fd = 0;
868 + err = close_tempfile_gently(tab_file);
869 + if (err < 0)
870 + goto done;
871 +
872 + *tab_file_out = tab_file;
873 + tab_file = NULL;
874
875 done:
876 + delete_tempfile(&tab_file);
877 reftable_writer_free(wr);
866 - if (tab_fd > 0) {
867 - close(tab_fd);
868 - tab_fd = 0;
869 - }
870 - if (err != 0 && temp_tab->len > 0) {
871 - unlink(temp_tab->buf);
872 - strbuf_release(temp_tab);
873 - }
878 strbuf_release(&next_name);
879 + strbuf_release(&tab_file_path);
880 return err;
881 }
882
@@ -979,12 +984,12 @@ static int stack_compact_range(struct reftable_stack *st,
984 struct reftable_log_expiry_config *expiry)
985 {
986 struct strbuf tables_list_buf = STRBUF_INIT;
982 - struct strbuf new_table_temp_path = STRBUF_INIT;
987 struct strbuf new_table_name = STRBUF_INIT;
988 struct strbuf new_table_path = STRBUF_INIT;
989 struct strbuf table_name = STRBUF_INIT;
990 struct lock_file tables_list_lock = LOCK_INIT;
991 struct lock_file *table_locks = NULL;
992 + struct tempfile *new_table = NULL;
993 int is_empty_table = 0, err = 0;
994 size_t i;
995
@@ -1059,7 +1064,7 @@ static int stack_compact_range(struct reftable_stack *st,
1064 * these tables may end up with an empty new table in case tombstones
1065 * end up cancelling out all refs in that range.
1066 */
1062 - err = stack_compact_locked(st, first, last, &new_table_temp_path, expiry);
1067 + err = stack_compact_locked(st, first, last, expiry, &new_table);
1068 if (err < 0) {
1069 if (err != REFTABLE_EMPTY_TABLE_ERROR)
1070 goto done;
@@ -1099,7 +1104,7 @@ static int stack_compact_range(struct reftable_stack *st,
1104 strbuf_addstr(&new_table_name, ".ref");
1105 stack_filename(&new_table_path, st, new_table_name.buf);
1106
1102 - err = rename(new_table_temp_path.buf, new_table_path.buf);
1107 + err = rename_tempfile(&new_table, new_table_path.buf);
1108 if (err < 0) {
1109 err = REFTABLE_IO_ERROR;
1110 goto done;
@@ -1166,9 +1171,10 @@ done:
1171 rollback_lock_file(&table_locks[i - first]);
1172 reftable_free(table_locks);
1173
1174 + delete_tempfile(&new_table);
1175 strbuf_release(&new_table_name);
1176 strbuf_release(&new_table_path);
1171 - strbuf_release(&new_table_temp_path);
1177 +
1178 strbuf_release(&tables_list_buf);
1179 strbuf_release(&table_name);
1180 return err;