reftable/block: handle allocation failures
Handle allocation failures in `block_writer_init()` and `block_reader_init()`. This requires us to bubble up error codes into `writer_reinit_block_writer()`. Adapt call sites accordingly. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
parent
cd6a47167e
commit
2d5dbb37b2
|
@ -52,6 +52,8 @@ static int block_writer_register_restart(struct block_writer *w, int n,
|
||||||
return -1;
|
return -1;
|
||||||
if (is_restart) {
|
if (is_restart) {
|
||||||
REFTABLE_ALLOC_GROW(w->restarts, w->restart_len + 1, w->restart_cap);
|
REFTABLE_ALLOC_GROW(w->restarts, w->restart_len + 1, w->restart_cap);
|
||||||
|
if (!w->restarts)
|
||||||
|
return REFTABLE_OUT_OF_MEMORY_ERROR;
|
||||||
w->restarts[w->restart_len++] = w->next;
|
w->restarts[w->restart_len++] = w->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,8 +65,8 @@ static int block_writer_register_restart(struct block_writer *w, int n,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf,
|
int block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf,
|
||||||
uint32_t block_size, uint32_t header_off, int hash_size)
|
uint32_t block_size, uint32_t header_off, int hash_size)
|
||||||
{
|
{
|
||||||
bw->buf = buf;
|
bw->buf = buf;
|
||||||
bw->hash_size = hash_size;
|
bw->hash_size = hash_size;
|
||||||
|
@ -78,8 +80,12 @@ void block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf,
|
||||||
bw->last_key.len = 0;
|
bw->last_key.len = 0;
|
||||||
if (!bw->zstream) {
|
if (!bw->zstream) {
|
||||||
REFTABLE_CALLOC_ARRAY(bw->zstream, 1);
|
REFTABLE_CALLOC_ARRAY(bw->zstream, 1);
|
||||||
|
if (!bw->zstream)
|
||||||
|
return REFTABLE_OUT_OF_MEMORY_ERROR;
|
||||||
deflateInit(bw->zstream, 9);
|
deflateInit(bw->zstream, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t block_writer_type(struct block_writer *bw)
|
uint8_t block_writer_type(struct block_writer *bw)
|
||||||
|
@ -163,6 +169,10 @@ int block_writer_finish(struct block_writer *w)
|
||||||
*/
|
*/
|
||||||
compressed_len = deflateBound(w->zstream, src_len);
|
compressed_len = deflateBound(w->zstream, src_len);
|
||||||
REFTABLE_ALLOC_GROW(w->compressed, compressed_len, w->compressed_cap);
|
REFTABLE_ALLOC_GROW(w->compressed, compressed_len, w->compressed_cap);
|
||||||
|
if (!w->compressed) {
|
||||||
|
ret = REFTABLE_OUT_OF_MEMORY_ERROR;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
w->zstream->next_out = w->compressed;
|
w->zstream->next_out = w->compressed;
|
||||||
w->zstream->avail_out = compressed_len;
|
w->zstream->avail_out = compressed_len;
|
||||||
|
@ -219,12 +229,21 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
|
||||||
/* Log blocks specify the *uncompressed* size in their header. */
|
/* Log blocks specify the *uncompressed* size in their header. */
|
||||||
REFTABLE_ALLOC_GROW(br->uncompressed_data, sz,
|
REFTABLE_ALLOC_GROW(br->uncompressed_data, sz,
|
||||||
br->uncompressed_cap);
|
br->uncompressed_cap);
|
||||||
|
if (!br->uncompressed_data) {
|
||||||
|
err = REFTABLE_OUT_OF_MEMORY_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy over the block header verbatim. It's not compressed. */
|
/* Copy over the block header verbatim. It's not compressed. */
|
||||||
memcpy(br->uncompressed_data, block->data, block_header_skip);
|
memcpy(br->uncompressed_data, block->data, block_header_skip);
|
||||||
|
|
||||||
if (!br->zstream) {
|
if (!br->zstream) {
|
||||||
REFTABLE_CALLOC_ARRAY(br->zstream, 1);
|
REFTABLE_CALLOC_ARRAY(br->zstream, 1);
|
||||||
|
if (!br->zstream) {
|
||||||
|
err = REFTABLE_OUT_OF_MEMORY_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
err = inflateInit(br->zstream);
|
err = inflateInit(br->zstream);
|
||||||
} else {
|
} else {
|
||||||
err = inflateReset(br->zstream);
|
err = inflateReset(br->zstream);
|
||||||
|
|
|
@ -45,8 +45,8 @@ struct block_writer {
|
||||||
/*
|
/*
|
||||||
* initializes the blockwriter to write `typ` entries, using `buf` as temporary
|
* initializes the blockwriter to write `typ` entries, using `buf` as temporary
|
||||||
* storage. `buf` is not owned by the block_writer. */
|
* storage. `buf` is not owned by the block_writer. */
|
||||||
void block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf,
|
int block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf,
|
||||||
uint32_t block_size, uint32_t header_off, int hash_size);
|
uint32_t block_size, uint32_t header_off, int hash_size);
|
||||||
|
|
||||||
/* returns the block type (eg. 'r' for ref records. */
|
/* returns the block type (eg. 'r' for ref records. */
|
||||||
uint8_t block_writer_type(struct block_writer *bw);
|
uint8_t block_writer_type(struct block_writer *bw);
|
||||||
|
|
|
@ -102,19 +102,24 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest)
|
||||||
return header_size(writer_version(w));
|
return header_size(writer_version(w));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writer_reinit_block_writer(struct reftable_writer *w, uint8_t typ)
|
static int writer_reinit_block_writer(struct reftable_writer *w, uint8_t typ)
|
||||||
{
|
{
|
||||||
int block_start = 0;
|
int block_start = 0, ret;
|
||||||
if (w->next == 0) {
|
|
||||||
|
if (w->next == 0)
|
||||||
block_start = header_size(writer_version(w));
|
block_start = header_size(writer_version(w));
|
||||||
}
|
|
||||||
|
|
||||||
strbuf_reset(&w->last_key);
|
strbuf_reset(&w->last_key);
|
||||||
block_writer_init(&w->block_writer_data, typ, w->block,
|
ret = block_writer_init(&w->block_writer_data, typ, w->block,
|
||||||
w->opts.block_size, block_start,
|
w->opts.block_size, block_start,
|
||||||
hash_size(w->opts.hash_id));
|
hash_size(w->opts.hash_id));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
w->block_writer = &w->block_writer_data;
|
w->block_writer = &w->block_writer_data;
|
||||||
w->block_writer->restart_interval = w->opts.restart_interval;
|
w->block_writer->restart_interval = w->opts.restart_interval;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int reftable_writer_new(struct reftable_writer **out,
|
int reftable_writer_new(struct reftable_writer **out,
|
||||||
|
@ -247,8 +252,11 @@ static int writer_add_record(struct reftable_writer *w,
|
||||||
|
|
||||||
strbuf_reset(&w->last_key);
|
strbuf_reset(&w->last_key);
|
||||||
strbuf_addbuf(&w->last_key, &key);
|
strbuf_addbuf(&w->last_key, &key);
|
||||||
if (!w->block_writer)
|
if (!w->block_writer) {
|
||||||
writer_reinit_block_writer(w, reftable_record_type(rec));
|
err = writer_reinit_block_writer(w, reftable_record_type(rec));
|
||||||
|
if (err < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (block_writer_type(w->block_writer) != reftable_record_type(rec))
|
if (block_writer_type(w->block_writer) != reftable_record_type(rec))
|
||||||
BUG("record of type %d added to writer of type %d",
|
BUG("record of type %d added to writer of type %d",
|
||||||
|
@ -271,7 +279,9 @@ static int writer_add_record(struct reftable_writer *w,
|
||||||
err = writer_flush_block(w);
|
err = writer_flush_block(w);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto done;
|
goto done;
|
||||||
writer_reinit_block_writer(w, reftable_record_type(rec));
|
err = writer_reinit_block_writer(w, reftable_record_type(rec));
|
||||||
|
if (err < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to add the record to the writer again. If this still fails then
|
* Try to add the record to the writer again. If this still fails then
|
||||||
|
@ -461,7 +471,9 @@ static int writer_finish_section(struct reftable_writer *w)
|
||||||
|
|
||||||
max_level++;
|
max_level++;
|
||||||
index_start = w->next;
|
index_start = w->next;
|
||||||
writer_reinit_block_writer(w, BLOCK_TYPE_INDEX);
|
err = writer_reinit_block_writer(w, BLOCK_TYPE_INDEX);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
idx = w->index;
|
idx = w->index;
|
||||||
idx_len = w->index_len;
|
idx_len = w->index_len;
|
||||||
|
@ -555,7 +567,10 @@ static void write_object_record(void *void_arg, void *key)
|
||||||
if (arg->err < 0)
|
if (arg->err < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
writer_reinit_block_writer(arg->w, BLOCK_TYPE_OBJ);
|
arg->err = writer_reinit_block_writer(arg->w, BLOCK_TYPE_OBJ);
|
||||||
|
if (arg->err < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
arg->err = block_writer_add(arg->w->block_writer, &rec);
|
arg->err = block_writer_add(arg->w->block_writer, &rec);
|
||||||
if (arg->err == 0)
|
if (arg->err == 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -584,16 +599,18 @@ static int writer_dump_object_index(struct reftable_writer *w)
|
||||||
struct common_prefix_arg common = {
|
struct common_prefix_arg common = {
|
||||||
.max = 1, /* obj_id_len should be >= 2. */
|
.max = 1, /* obj_id_len should be >= 2. */
|
||||||
};
|
};
|
||||||
if (w->obj_index_tree) {
|
int err;
|
||||||
|
|
||||||
|
if (w->obj_index_tree)
|
||||||
infix_walk(w->obj_index_tree, &update_common, &common);
|
infix_walk(w->obj_index_tree, &update_common, &common);
|
||||||
}
|
|
||||||
w->stats.object_id_len = common.max + 1;
|
w->stats.object_id_len = common.max + 1;
|
||||||
|
|
||||||
writer_reinit_block_writer(w, BLOCK_TYPE_OBJ);
|
err = writer_reinit_block_writer(w, BLOCK_TYPE_OBJ);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
if (w->obj_index_tree) {
|
if (w->obj_index_tree)
|
||||||
infix_walk(w->obj_index_tree, &write_object_record, &closure);
|
infix_walk(w->obj_index_tree, &write_object_record, &closure);
|
||||||
}
|
|
||||||
|
|
||||||
if (closure.err < 0)
|
if (closure.err < 0)
|
||||||
return closure.err;
|
return closure.err;
|
||||||
|
|
|
@ -34,8 +34,9 @@ static void t_ref_block_read_write(void)
|
||||||
REFTABLE_CALLOC_ARRAY(block.data, block_size);
|
REFTABLE_CALLOC_ARRAY(block.data, block_size);
|
||||||
block.len = block_size;
|
block.len = block_size;
|
||||||
block_source_from_strbuf(&block.source ,&buf);
|
block_source_from_strbuf(&block.source ,&buf);
|
||||||
block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size,
|
ret = block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size,
|
||||||
header_off, hash_size(GIT_SHA1_FORMAT_ID));
|
header_off, hash_size(GIT_SHA1_FORMAT_ID));
|
||||||
|
check(!ret);
|
||||||
|
|
||||||
rec.u.ref.refname = (char *) "";
|
rec.u.ref.refname = (char *) "";
|
||||||
rec.u.ref.value_type = REFTABLE_REF_DELETION;
|
rec.u.ref.value_type = REFTABLE_REF_DELETION;
|
||||||
|
@ -126,8 +127,9 @@ static void t_log_block_read_write(void)
|
||||||
REFTABLE_CALLOC_ARRAY(block.data, block_size);
|
REFTABLE_CALLOC_ARRAY(block.data, block_size);
|
||||||
block.len = block_size;
|
block.len = block_size;
|
||||||
block_source_from_strbuf(&block.source ,&buf);
|
block_source_from_strbuf(&block.source ,&buf);
|
||||||
block_writer_init(&bw, BLOCK_TYPE_LOG, block.data, block_size,
|
ret = block_writer_init(&bw, BLOCK_TYPE_LOG, block.data, block_size,
|
||||||
header_off, hash_size(GIT_SHA1_FORMAT_ID));
|
header_off, hash_size(GIT_SHA1_FORMAT_ID));
|
||||||
|
check(!ret);
|
||||||
|
|
||||||
for (i = 0; i < N; i++) {
|
for (i = 0; i < N; i++) {
|
||||||
rec.u.log.refname = xstrfmt("branch%02"PRIuMAX , (uintmax_t)i);
|
rec.u.log.refname = xstrfmt("branch%02"PRIuMAX , (uintmax_t)i);
|
||||||
|
@ -214,8 +216,9 @@ static void t_obj_block_read_write(void)
|
||||||
REFTABLE_CALLOC_ARRAY(block.data, block_size);
|
REFTABLE_CALLOC_ARRAY(block.data, block_size);
|
||||||
block.len = block_size;
|
block.len = block_size;
|
||||||
block_source_from_strbuf(&block.source, &buf);
|
block_source_from_strbuf(&block.source, &buf);
|
||||||
block_writer_init(&bw, BLOCK_TYPE_OBJ, block.data, block_size,
|
ret = block_writer_init(&bw, BLOCK_TYPE_OBJ, block.data, block_size,
|
||||||
header_off, hash_size(GIT_SHA1_FORMAT_ID));
|
header_off, hash_size(GIT_SHA1_FORMAT_ID));
|
||||||
|
check(!ret);
|
||||||
|
|
||||||
for (i = 0; i < N; i++) {
|
for (i = 0; i < N; i++) {
|
||||||
uint8_t bytes[] = { i, i + 1, i + 2, i + 3, i + 5 }, *allocated;
|
uint8_t bytes[] = { i, i + 1, i + 2, i + 3, i + 5 }, *allocated;
|
||||||
|
@ -296,8 +299,9 @@ static void t_index_block_read_write(void)
|
||||||
REFTABLE_CALLOC_ARRAY(block.data, block_size);
|
REFTABLE_CALLOC_ARRAY(block.data, block_size);
|
||||||
block.len = block_size;
|
block.len = block_size;
|
||||||
block_source_from_strbuf(&block.source, &buf);
|
block_source_from_strbuf(&block.source, &buf);
|
||||||
block_writer_init(&bw, BLOCK_TYPE_INDEX, block.data, block_size,
|
ret = block_writer_init(&bw, BLOCK_TYPE_INDEX, block.data, block_size,
|
||||||
header_off, hash_size(GIT_SHA1_FORMAT_ID));
|
header_off, hash_size(GIT_SHA1_FORMAT_ID));
|
||||||
|
check(!ret);
|
||||||
|
|
||||||
for (i = 0; i < N; i++) {
|
for (i = 0; i < N; i++) {
|
||||||
strbuf_init(&recs[i].u.idx.last_key, 9);
|
strbuf_init(&recs[i].u.idx.last_key, 9);
|
||||||
|
|
Loading…
Reference in New Issue