Skip to content

Commit

Permalink
reftable: honor core.fsync
Browse files Browse the repository at this point in the history
While the reffiles backend honors configured fsync settings, the
reftable backend does not. Address this by fsyncing reftable files using
the write-or-die api's fsync_component() in two places: when we
add additional entries into the table, and when we close the reftable
writer.

This commits adds a flush function pointer as a new member of
reftable_writer because we are not sure that the first argument to the
*write function pointer always contains a file descriptor. In the case of
strbuf_add_void, the first argument is a buffer. This way, we can pass
in a corresponding flush function that knows how to flush depending on
which writer is being used.

This patch does not contain tests as they will need to wait for another
patch to start to exercise the reftable backend. At that point, the
tests will be added to observe that fsyncs are happening when the
reftable is in use.

Signed-off-by: John Cai <[email protected]>
  • Loading branch information
john-cai committed Jan 23, 2024
1 parent e02ecfc commit 528a5d4
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 19 deletions.
6 changes: 3 additions & 3 deletions reftable/merged_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ static void write_test_table(struct strbuf *buf,
}
}

w = reftable_new_writer(&strbuf_add_void, buf, &opts);
w = reftable_new_writer(&strbuf_add_void, &noop_flush, buf, &opts);
reftable_writer_set_limits(w, min, max);

for (i = 0; i < n; i++) {
Expand Down Expand Up @@ -70,7 +70,7 @@ static void write_test_log_table(struct strbuf *buf,
.exact_log_message = 1,
};
struct reftable_writer *w = NULL;
w = reftable_new_writer(&strbuf_add_void, buf, &opts);
w = reftable_new_writer(&strbuf_add_void, &noop_flush, buf, &opts);
reftable_writer_set_limits(w, update_index, update_index);

for (i = 0; i < n; i++) {
Expand Down Expand Up @@ -412,7 +412,7 @@ static void test_default_write_opts(void)
struct reftable_write_options opts = { 0 };
struct strbuf buf = STRBUF_INIT;
struct reftable_writer *w =
reftable_new_writer(&strbuf_add_void, &buf, &opts);
reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);

struct reftable_ref_record rec = {
.refname = "master",
Expand Down
24 changes: 12 additions & 12 deletions reftable/readwrite_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ static void write_table(char ***names, struct strbuf *buf, int N,
.hash_id = hash_id,
};
struct reftable_writer *w =
reftable_new_writer(&strbuf_add_void, buf, &opts);
reftable_new_writer(&strbuf_add_void, &noop_flush, buf, &opts);
struct reftable_ref_record ref = { NULL };
int i = 0, n;
struct reftable_log_record log = { NULL };
Expand Down Expand Up @@ -130,7 +130,7 @@ static void test_log_buffer_size(void)
.message = "commit: 9\n",
} } };
struct reftable_writer *w =
reftable_new_writer(&strbuf_add_void, &buf, &opts);
reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);

/* This tests buffer extension for log compression. Must use a random
hash, to ensure that the compressed part is larger than the original.
Expand Down Expand Up @@ -171,7 +171,7 @@ static void test_log_overflow(void)
.message = msg,
} } };
struct reftable_writer *w =
reftable_new_writer(&strbuf_add_void, &buf, &opts);
reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);

uint8_t hash1[GIT_SHA1_RAWSZ] = {1}, hash2[GIT_SHA1_RAWSZ] = { 2 };

Expand Down Expand Up @@ -202,7 +202,7 @@ static void test_log_write_read(void)
struct reftable_block_source source = { NULL };
struct strbuf buf = STRBUF_INIT;
struct reftable_writer *w =
reftable_new_writer(&strbuf_add_void, &buf, &opts);
reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
const struct reftable_stats *stats = NULL;
reftable_writer_set_limits(w, 0, N);
for (i = 0; i < N; i++) {
Expand Down Expand Up @@ -294,7 +294,7 @@ static void test_log_zlib_corruption(void)
struct reftable_block_source source = { 0 };
struct strbuf buf = STRBUF_INIT;
struct reftable_writer *w =
reftable_new_writer(&strbuf_add_void, &buf, &opts);
reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
const struct reftable_stats *stats = NULL;
uint8_t hash1[GIT_SHA1_RAWSZ] = { 1 };
uint8_t hash2[GIT_SHA1_RAWSZ] = { 2 };
Expand Down Expand Up @@ -535,7 +535,7 @@ static void test_table_refs_for(int indexed)

struct strbuf buf = STRBUF_INIT;
struct reftable_writer *w =
reftable_new_writer(&strbuf_add_void, &buf, &opts);
reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);

struct reftable_iterator it = { NULL };
int j;
Expand Down Expand Up @@ -628,7 +628,7 @@ static void test_write_empty_table(void)
struct reftable_write_options opts = { 0 };
struct strbuf buf = STRBUF_INIT;
struct reftable_writer *w =
reftable_new_writer(&strbuf_add_void, &buf, &opts);
reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
struct reftable_block_source source = { NULL };
struct reftable_reader *rd = NULL;
struct reftable_ref_record rec = { NULL };
Expand Down Expand Up @@ -666,7 +666,7 @@ static void test_write_object_id_min_length(void)
};
struct strbuf buf = STRBUF_INIT;
struct reftable_writer *w =
reftable_new_writer(&strbuf_add_void, &buf, &opts);
reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
struct reftable_ref_record ref = {
.update_index = 1,
.value_type = REFTABLE_REF_VAL1,
Expand Down Expand Up @@ -701,7 +701,7 @@ static void test_write_object_id_length(void)
};
struct strbuf buf = STRBUF_INIT;
struct reftable_writer *w =
reftable_new_writer(&strbuf_add_void, &buf, &opts);
reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
struct reftable_ref_record ref = {
.update_index = 1,
.value_type = REFTABLE_REF_VAL1,
Expand Down Expand Up @@ -735,7 +735,7 @@ static void test_write_empty_key(void)
struct reftable_write_options opts = { 0 };
struct strbuf buf = STRBUF_INIT;
struct reftable_writer *w =
reftable_new_writer(&strbuf_add_void, &buf, &opts);
reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
struct reftable_ref_record ref = {
.refname = "",
.update_index = 1,
Expand All @@ -758,7 +758,7 @@ static void test_write_key_order(void)
struct reftable_write_options opts = { 0 };
struct strbuf buf = STRBUF_INIT;
struct reftable_writer *w =
reftable_new_writer(&strbuf_add_void, &buf, &opts);
reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
struct reftable_ref_record refs[2] = {
{
.refname = "b",
Expand Down Expand Up @@ -801,7 +801,7 @@ static void test_write_multiple_indices(void)
struct reftable_reader *reader;
int err, i;

writer = reftable_new_writer(&strbuf_add_void, &writer_buf, &opts);
writer = reftable_new_writer(&strbuf_add_void, &noop_flush, &writer_buf, &opts);
reftable_writer_set_limits(writer, 1, 1);
for (i = 0; i < 100; i++) {
struct reftable_ref_record ref = {
Expand Down
2 changes: 1 addition & 1 deletion reftable/refname_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ static void test_conflict(void)
struct reftable_write_options opts = { 0 };
struct strbuf buf = STRBUF_INIT;
struct reftable_writer *w =
reftable_new_writer(&strbuf_add_void, &buf, &opts);
reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
struct reftable_ref_record rec = {
.refname = "a/b",
.value_type = REFTABLE_REF_SYMREF,
Expand Down
1 change: 1 addition & 0 deletions reftable/reftable-writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ struct reftable_stats {
/* reftable_new_writer creates a new writer */
struct reftable_writer *
reftable_new_writer(ssize_t (*writer_func)(void *, const void *, size_t),
int (*flush_func)(void *),
void *writer_arg, struct reftable_write_options *opts);

/* Set the range of update indices for the records we will add. When writing a
Expand Down
16 changes: 13 additions & 3 deletions reftable/stack.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ license that can be found in the LICENSE file or at

#include "stack.h"

#include "../write-or-die.h"
#include "system.h"
#include "merged.h"
#include "reader.h"
Expand All @@ -16,7 +17,6 @@ license that can be found in the LICENSE file or at
#include "reftable-record.h"
#include "reftable-merged.h"
#include "writer.h"

#include "tempfile.h"

static int stack_try_add(struct reftable_stack *st,
Expand Down Expand Up @@ -47,6 +47,13 @@ static ssize_t reftable_fd_write(void *arg, const void *data, size_t sz)
return write_in_full(*fdp, data, sz);
}

static int reftable_fd_flush(void *arg)
{
int *fdp = (int *)arg;

return fsync_component(FSYNC_COMPONENT_REFERENCE, *fdp);
}

int reftable_new_stack(struct reftable_stack **dest, const char *dir,
struct reftable_write_options config)
{
Expand Down Expand Up @@ -545,6 +552,9 @@ int reftable_addition_commit(struct reftable_addition *add)
goto done;
}

fsync_component_or_die(FSYNC_COMPONENT_REFERENCE, lock_file_fd,
get_tempfile_path(add->lock_file));

err = rename_tempfile(&add->lock_file, add->stack->list_file);
if (err < 0) {
err = REFTABLE_IO_ERROR;
Expand Down Expand Up @@ -639,7 +649,7 @@ int reftable_addition_add(struct reftable_addition *add,
goto done;
}
}
wr = reftable_new_writer(reftable_fd_write, &tab_fd,
wr = reftable_new_writer(reftable_fd_write, reftable_fd_flush, &tab_fd,
&add->stack->config);
err = write_table(wr, arg);
if (err < 0)
Expand Down Expand Up @@ -731,7 +741,7 @@ static int stack_compact_locked(struct reftable_stack *st, int first, int last,
strbuf_addstr(temp_tab, ".temp.XXXXXX");

tab_fd = mkstemp(temp_tab->buf);
wr = reftable_new_writer(reftable_fd_write, &tab_fd, &st->config);
wr = reftable_new_writer(reftable_fd_write, reftable_fd_flush, &tab_fd, &st->config);

err = stack_write_compact(st, wr, first, last, config);
if (err < 0)
Expand Down
5 changes: 5 additions & 0 deletions reftable/test_framework.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,8 @@ ssize_t strbuf_add_void(void *b, const void *data, size_t sz)
strbuf_add(b, data, sz);
return sz;
}

int noop_flush(void *arg)
{
return 0;
}
2 changes: 2 additions & 0 deletions reftable/test_framework.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,6 @@ void set_test_hash(uint8_t *p, int i);
*/
ssize_t strbuf_add_void(void *b, const void *data, size_t sz);

int noop_flush(void *);

#endif
8 changes: 8 additions & 0 deletions reftable/writer.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ static struct strbuf reftable_empty_strbuf = STRBUF_INIT;

struct reftable_writer *
reftable_new_writer(ssize_t (*writer_func)(void *, const void *, size_t),
int (*flush_func)(void *),
void *writer_arg, struct reftable_write_options *opts)
{
struct reftable_writer *wp =
Expand All @@ -136,6 +137,7 @@ reftable_new_writer(ssize_t (*writer_func)(void *, const void *, size_t),
wp->write = writer_func;
wp->write_arg = writer_arg;
wp->opts = *opts;
wp->flush = flush_func;
writer_reinit_block_writer(wp, BLOCK_TYPE_REF);

return wp;
Expand Down Expand Up @@ -603,6 +605,12 @@ int reftable_writer_close(struct reftable_writer *w)
put_be32(p, crc32(0, footer, p - footer));
p += 4;

err = w->flush(w->write_arg);
if (err < 0) {
err = REFTABLE_IO_ERROR;
goto done;
}

err = padded_write(w, footer, footer_size(writer_version(w)), 0);
if (err < 0)
goto done;
Expand Down
1 change: 1 addition & 0 deletions reftable/writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ license that can be found in the LICENSE file or at

struct reftable_writer {
ssize_t (*write)(void *, const void *, size_t);
int (*flush)(void *);
void *write_arg;
int pending_padding;
struct strbuf last_key;
Expand Down

0 comments on commit 528a5d4

Please sign in to comment.