reftable/merged: handle allocation failures in `merged_table_init_iter()`

Handle allocation failures in `merged_table_init_iter()`. While at it,
merge `merged_iter_init()` into the function. It only has a single
caller and merging them makes it easier to handle allocation failures
consistently.

This change also requires us to adapt `reftable_stack_init_*_iterator()`
to bubble up the new error codes of `merged_table_iter_init()`. Adapt
callsites accordingly.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Patrick Steinhardt 2024-10-02 12:55:54 +02:00 committed by Junio C Hamano
parent 74d1c18757
commit 802c0646ac
9 changed files with 131 additions and 64 deletions

View File

@ -1307,7 +1307,9 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
struct reftable_log_record log = {0}; struct reftable_log_record log = {0};
struct reftable_iterator it = {0}; struct reftable_iterator it = {0};


reftable_stack_init_log_iterator(arg->stack, &it); ret = reftable_stack_init_log_iterator(arg->stack, &it);
if (ret < 0)
goto done;


/* /*
* When deleting refs we also delete all reflog entries * When deleting refs we also delete all reflog entries
@ -1677,7 +1679,10 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
* copy over all log entries from the old reflog. Last but not least, * copy over all log entries from the old reflog. Last but not least,
* when renaming we also have to delete all the old reflog entries. * when renaming we also have to delete all the old reflog entries.
*/ */
reftable_stack_init_log_iterator(arg->stack, &it); ret = reftable_stack_init_log_iterator(arg->stack, &it);
if (ret < 0)
goto done;

ret = reftable_iterator_seek_log(&it, arg->oldname); ret = reftable_iterator_seek_log(&it, arg->oldname);
if (ret < 0) if (ret < 0)
goto done; goto done;
@ -1898,7 +1903,10 @@ static struct reftable_reflog_iterator *reflog_iterator_for_stack(struct reftabl
if (ret < 0) if (ret < 0)
goto done; goto done;


reftable_stack_init_log_iterator(stack, &iter->iter); ret = reftable_stack_init_log_iterator(stack, &iter->iter);
if (ret < 0)
goto done;

ret = reftable_iterator_seek_log(&iter->iter, ""); ret = reftable_iterator_seek_log(&iter->iter, "");
if (ret < 0) if (ret < 0)
goto done; goto done;
@ -1965,7 +1973,10 @@ static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store,
if (refs->err < 0) if (refs->err < 0)
return refs->err; return refs->err;


reftable_stack_init_log_iterator(stack, &it); ret = reftable_stack_init_log_iterator(stack, &it);
if (ret < 0)
goto done;

ret = reftable_iterator_seek_log(&it, refname); ret = reftable_iterator_seek_log(&it, refname);
while (!ret) { while (!ret) {
ret = reftable_iterator_next_log(&it, &log); ret = reftable_iterator_next_log(&it, &log);
@ -1981,6 +1992,7 @@ static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store,
break; break;
} }


done:
reftable_log_record_release(&log); reftable_log_record_release(&log);
reftable_iterator_destroy(&it); reftable_iterator_destroy(&it);
return ret; return ret;
@ -2002,7 +2014,10 @@ static int reftable_be_for_each_reflog_ent(struct ref_store *ref_store,
if (refs->err < 0) if (refs->err < 0)
return refs->err; return refs->err;


reftable_stack_init_log_iterator(stack, &it); ret = reftable_stack_init_log_iterator(stack, &it);
if (ret < 0)
goto done;

ret = reftable_iterator_seek_log(&it, refname); ret = reftable_iterator_seek_log(&it, refname);
while (!ret) { while (!ret) {
struct reftable_log_record log = {0}; struct reftable_log_record log = {0};
@ -2052,7 +2067,10 @@ static int reftable_be_reflog_exists(struct ref_store *ref_store,
if (ret < 0) if (ret < 0)
goto done; goto done;


reftable_stack_init_log_iterator(stack, &it); ret = reftable_stack_init_log_iterator(stack, &it);
if (ret < 0)
goto done;

ret = reftable_iterator_seek_log(&it, refname); ret = reftable_iterator_seek_log(&it, refname);
if (ret < 0) if (ret < 0)
goto done; goto done;
@ -2158,7 +2176,9 @@ static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_da


reftable_writer_set_limits(writer, ts, ts); reftable_writer_set_limits(writer, ts, ts);


reftable_stack_init_log_iterator(arg->stack, &it); ret = reftable_stack_init_log_iterator(arg->stack, &it);
if (ret < 0)
goto out;


/* /*
* In order to delete a table we need to delete all reflog entries one * In order to delete a table we need to delete all reflog entries one
@ -2182,6 +2202,7 @@ static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_da
ret = reftable_writer_add_log(writer, &tombstone); ret = reftable_writer_add_log(writer, &tombstone);
} }


out:
reftable_log_record_release(&log); reftable_log_record_release(&log);
reftable_iterator_destroy(&it); reftable_iterator_destroy(&it);
return ret; return ret;
@ -2320,7 +2341,9 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
if (ret < 0) if (ret < 0)
goto done; goto done;


reftable_stack_init_log_iterator(stack, &it); ret = reftable_stack_init_log_iterator(stack, &it);
if (ret < 0)
goto done;


ret = reftable_iterator_seek_log(&it, refname); ret = reftable_iterator_seek_log(&it, refname);
if (ret < 0) if (ret < 0)

View File

@ -30,22 +30,6 @@ struct merged_iter {
ssize_t advance_index; ssize_t advance_index;
}; };


static void merged_iter_init(struct merged_iter *mi,
struct reftable_merged_table *mt,
uint8_t typ)
{
memset(mi, 0, sizeof(*mi));
mi->advance_index = -1;
mi->suppress_deletions = mt->suppress_deletions;

REFTABLE_CALLOC_ARRAY(mi->subiters, mt->readers_len);
for (size_t i = 0; i < mt->readers_len; i++) {
reftable_record_init(&mi->subiters[i].rec, typ);
reader_init_iter(mt->readers[i], &mi->subiters[i].iter, typ);
}
mi->subiters_len = mt->readers_len;
}

static void merged_iter_close(void *p) static void merged_iter_close(void *p)
{ {
struct merged_iter *mi = p; struct merged_iter *mi = p;
@ -244,25 +228,61 @@ reftable_merged_table_min_update_index(struct reftable_merged_table *mt)
return mt->min; return mt->min;
} }


void merged_table_init_iter(struct reftable_merged_table *mt, int merged_table_init_iter(struct reftable_merged_table *mt,
struct reftable_iterator *it, struct reftable_iterator *it,
uint8_t typ) uint8_t typ)
{ {
struct merged_iter *mi = reftable_malloc(sizeof(*mi)); struct merged_subiter *subiters;
merged_iter_init(mi, mt, typ); struct merged_iter *mi = NULL;
int ret;

REFTABLE_CALLOC_ARRAY(subiters, mt->readers_len);
if (!subiters) {
ret = REFTABLE_OUT_OF_MEMORY_ERROR;
goto out;
}

for (size_t i = 0; i < mt->readers_len; i++) {
reftable_record_init(&subiters[i].rec, typ);
reader_init_iter(mt->readers[i], &subiters[i].iter, typ);
}

REFTABLE_CALLOC_ARRAY(mi, 1);
if (!mi) {
ret = REFTABLE_OUT_OF_MEMORY_ERROR;
goto out;
}
mi->advance_index = -1;
mi->suppress_deletions = mt->suppress_deletions;
mi->subiters = subiters;
mi->subiters_len = mt->readers_len;

iterator_from_merged_iter(it, mi); iterator_from_merged_iter(it, mi);
ret = 0;

out:
if (ret < 0) {
for (size_t i = 0; subiters && i < mt->readers_len; i++) {
reftable_iterator_destroy(&subiters[i].iter);
reftable_record_release(&subiters[i].rec);
}
reftable_free(subiters);
reftable_free(mi);
}

return ret;
} }


void reftable_merged_table_init_ref_iterator(struct reftable_merged_table *mt, int reftable_merged_table_init_ref_iterator(struct reftable_merged_table *mt,
struct reftable_iterator *it) struct reftable_iterator *it)
{ {
merged_table_init_iter(mt, it, BLOCK_TYPE_REF); return merged_table_init_iter(mt, it, BLOCK_TYPE_REF);
} }


void reftable_merged_table_init_log_iterator(struct reftable_merged_table *mt, int reftable_merged_table_init_log_iterator(struct reftable_merged_table *mt,
struct reftable_iterator *it) struct reftable_iterator *it)
{ {
merged_table_init_iter(mt, it, BLOCK_TYPE_LOG); return merged_table_init_iter(mt, it, BLOCK_TYPE_LOG);
} }


uint32_t reftable_merged_table_hash_id(struct reftable_merged_table *mt) uint32_t reftable_merged_table_hash_id(struct reftable_merged_table *mt)

View File

@ -26,7 +26,7 @@ struct reftable_merged_table {


struct reftable_iterator; struct reftable_iterator;


void merged_table_init_iter(struct reftable_merged_table *mt, int merged_table_init_iter(struct reftable_merged_table *mt,
struct reftable_iterator *it, struct reftable_iterator *it,
uint8_t typ); uint8_t typ);



View File

@ -37,11 +37,11 @@ int reftable_merged_table_new(struct reftable_merged_table **dest,
uint32_t hash_id); uint32_t hash_id);


/* Initialize a merged table iterator for reading refs. */ /* Initialize a merged table iterator for reading refs. */
void reftable_merged_table_init_ref_iterator(struct reftable_merged_table *mt, int reftable_merged_table_init_ref_iterator(struct reftable_merged_table *mt,
struct reftable_iterator *it); struct reftable_iterator *it);


/* Initialize a merged table iterator for reading logs. */ /* Initialize a merged table iterator for reading logs. */
void reftable_merged_table_init_log_iterator(struct reftable_merged_table *mt, int reftable_merged_table_init_log_iterator(struct reftable_merged_table *mt,
struct reftable_iterator *it); struct reftable_iterator *it);


/* returns the max update_index covered by this merged table. */ /* returns the max update_index covered by this merged table. */

View File

@ -73,7 +73,7 @@ struct reftable_iterator;
* be used to iterate through refs. The iterator is valid until the next reload * be used to iterate through refs. The iterator is valid until the next reload
* or write. * or write.
*/ */
void reftable_stack_init_ref_iterator(struct reftable_stack *st, int reftable_stack_init_ref_iterator(struct reftable_stack *st,
struct reftable_iterator *it); struct reftable_iterator *it);


/* /*
@ -81,7 +81,7 @@ void reftable_stack_init_ref_iterator(struct reftable_stack *st,
* be used to iterate through logs. The iterator is valid until the next reload * be used to iterate through logs. The iterator is valid until the next reload
* or write. * or write.
*/ */
void reftable_stack_init_log_iterator(struct reftable_stack *st, int reftable_stack_init_log_iterator(struct reftable_stack *st,
struct reftable_iterator *it); struct reftable_iterator *it);


/* returns the merged_table for seeking. This table is valid until the /* returns the merged_table for seeking. This table is valid until the

View File

@ -136,17 +136,17 @@ int read_lines(const char *filename, char ***namesp)
return err; return err;
} }


void reftable_stack_init_ref_iterator(struct reftable_stack *st, int reftable_stack_init_ref_iterator(struct reftable_stack *st,
struct reftable_iterator *it) struct reftable_iterator *it)
{ {
merged_table_init_iter(reftable_stack_merged_table(st), return merged_table_init_iter(reftable_stack_merged_table(st),
it, BLOCK_TYPE_REF); it, BLOCK_TYPE_REF);
} }


void reftable_stack_init_log_iterator(struct reftable_stack *st, int reftable_stack_init_log_iterator(struct reftable_stack *st,
struct reftable_iterator *it) struct reftable_iterator *it)
{ {
merged_table_init_iter(reftable_stack_merged_table(st), return merged_table_init_iter(reftable_stack_merged_table(st),
it, BLOCK_TYPE_LOG); it, BLOCK_TYPE_LOG);
} }


@ -952,7 +952,10 @@ static int stack_write_compact(struct reftable_stack *st,
if (err < 0) if (err < 0)
goto done; goto done;


merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); err = merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
if (err < 0)
goto done;

err = reftable_iterator_seek_ref(&it, ""); err = reftable_iterator_seek_ref(&it, "");
if (err < 0) if (err < 0)
goto done; goto done;
@ -977,7 +980,10 @@ static int stack_write_compact(struct reftable_stack *st,
} }
reftable_iterator_destroy(&it); reftable_iterator_destroy(&it);


merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG);
if (err < 0)
goto done;

err = reftable_iterator_seek_log(&it, ""); err = reftable_iterator_seek_log(&it, "");
if (err < 0) if (err < 0)
goto done; goto done;
@ -1496,7 +1502,10 @@ int reftable_stack_read_ref(struct reftable_stack *st, const char *refname,
struct reftable_iterator it = { 0 }; struct reftable_iterator it = { 0 };
int ret; int ret;


reftable_merged_table_init_ref_iterator(st->merged, &it); ret = reftable_merged_table_init_ref_iterator(st->merged, &it);
if (ret)
goto out;

ret = reftable_iterator_seek_ref(&it, refname); ret = reftable_iterator_seek_ref(&it, refname);
if (ret) if (ret)
goto out; goto out;
@ -1523,7 +1532,10 @@ int reftable_stack_read_log(struct reftable_stack *st, const char *refname,
struct reftable_iterator it = {0}; struct reftable_iterator it = {0};
int err; int err;


reftable_stack_init_log_iterator(st, &it); err = reftable_stack_init_log_iterator(st, &it);
if (err)
goto done;

err = reftable_iterator_seek_log(&it, refname); err = reftable_iterator_seek_log(&it, refname);
if (err) if (err)
goto done; goto done;

View File

@ -28,7 +28,10 @@ static int dump_table(struct reftable_merged_table *mt)
const struct git_hash_algo *algop; const struct git_hash_algo *algop;
int err; int err;


reftable_merged_table_init_ref_iterator(mt, &it); err = reftable_merged_table_init_ref_iterator(mt, &it);
if (err < 0)
return err;

err = reftable_iterator_seek_ref(&it, ""); err = reftable_iterator_seek_ref(&it, "");
if (err < 0) if (err < 0)
return err; return err;
@ -63,7 +66,10 @@ static int dump_table(struct reftable_merged_table *mt)
reftable_iterator_destroy(&it); reftable_iterator_destroy(&it);
reftable_ref_record_release(&ref); reftable_ref_record_release(&ref);


reftable_merged_table_init_log_iterator(mt, &it); err = reftable_merged_table_init_log_iterator(mt, &it);
if (err < 0)
return err;

err = reftable_iterator_seek_log(&it, ""); err = reftable_iterator_seek_log(&it, "");
if (err < 0) if (err < 0)
return err; return err;

View File

@ -82,7 +82,8 @@ static void t_merged_single_record(void)
struct reftable_iterator it = { 0 }; struct reftable_iterator it = { 0 };
int err; int err;


merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); err = merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
check(!err);
err = reftable_iterator_seek_ref(&it, "a"); err = reftable_iterator_seek_ref(&it, "a");
check(!err); check(!err);


@ -161,7 +162,8 @@ static void t_merged_refs(void)
size_t cap = 0; size_t cap = 0;
size_t i; size_t i;


merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); err = merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
check(!err);
err = reftable_iterator_seek_ref(&it, "a"); err = reftable_iterator_seek_ref(&it, "a");
check(!err); check(!err);
check_int(reftable_merged_table_hash_id(mt), ==, GIT_SHA1_FORMAT_ID); check_int(reftable_merged_table_hash_id(mt), ==, GIT_SHA1_FORMAT_ID);
@ -367,7 +369,8 @@ static void t_merged_logs(void)
size_t cap = 0; size_t cap = 0;
size_t i; size_t i;


merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG);
check(!err);
err = reftable_iterator_seek_log(&it, "a"); err = reftable_iterator_seek_log(&it, "a");
check(!err); check(!err);
check_int(reftable_merged_table_hash_id(mt), ==, GIT_SHA1_FORMAT_ID); check_int(reftable_merged_table_hash_id(mt), ==, GIT_SHA1_FORMAT_ID);
@ -390,7 +393,8 @@ static void t_merged_logs(void)
check(reftable_log_record_equal(want[i], &out[i], check(reftable_log_record_equal(want[i], &out[i],
GIT_SHA1_RAWSZ)); GIT_SHA1_RAWSZ));


merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG);
check(!err);
err = reftable_iterator_seek_log_at(&it, "a", 2); err = reftable_iterator_seek_log_at(&it, "a", 2);
check(!err); check(!err);
reftable_log_record_release(&out[0]); reftable_log_record_release(&out[0]);

View File

@ -599,7 +599,9 @@ static void t_reftable_stack_iterator(void)


reftable_iterator_destroy(&it); reftable_iterator_destroy(&it);


reftable_stack_init_log_iterator(st, &it); err = reftable_stack_init_log_iterator(st, &it);
check(!err);

reftable_iterator_seek_log(&it, logs[0].refname); reftable_iterator_seek_log(&it, logs[0].refname);
for (i = 0; ; i++) { for (i = 0; ; i++) {
struct reftable_log_record log = { 0 }; struct reftable_log_record log = { 0 };