Skip to content

Commit fd88831

Browse files
pks-tgitster
authored andcommitted
reftable/table: move reading block into block reader
The logic to read blocks from a reftable is scattered across both the table and the block subsystems. Besides causing somewhat fuzzy responsibilities, it also means that we have to awkwardly pass around the ownership of blocks between the subsystems. Refactor the code so that we stop passing the block when initializing a reader, but instead by passing in the block source plus the offset at which we're supposed to read a block. Like this, the ownership of the block itself doesn't need to get handed over as the block reader is the one owning the block right from the start. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ba620d2 commit fd88831

File tree

4 files changed

+107
-129
lines changed

4 files changed

+107
-129
lines changed

reftable/block.c

Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -209,39 +209,65 @@ int block_writer_finish(struct block_writer *w)
209209
return w->next;
210210
}
211211

212-
int block_reader_init(struct block_reader *br, struct reftable_block *block,
213-
uint32_t header_off, uint32_t table_block_size,
214-
uint32_t hash_size)
212+
static int read_block(struct reftable_block_source *source,
213+
struct reftable_block *dest, uint64_t off,
214+
uint32_t sz)
215215
{
216+
size_t size = block_source_size(source);
217+
block_source_return_block(dest);
218+
if (off >= size)
219+
return 0;
220+
if (off + sz > size)
221+
sz = size - off;
222+
return block_source_read_block(source, dest, off, sz);
223+
}
224+
225+
int block_reader_init(struct block_reader *br,
226+
struct reftable_block_source *source,
227+
uint32_t offset, uint32_t header_size,
228+
uint32_t table_block_size, uint32_t hash_size)
229+
{
230+
uint32_t guess_block_size = table_block_size ?
231+
table_block_size : DEFAULT_BLOCK_SIZE;
216232
uint32_t full_block_size = table_block_size;
217-
uint8_t typ = block->data[header_off];
218-
uint32_t sz = reftable_get_be24(block->data + header_off + 1);
219233
uint16_t restart_count;
220234
uint32_t restart_off;
235+
uint32_t block_size;
236+
uint8_t block_type;
221237
int err;
222238

223-
block_source_return_block(&br->block);
239+
err = read_block(source, &br->block, offset, guess_block_size);
240+
if (err < 0)
241+
goto done;
224242

225-
if (!reftable_is_block_type(typ)) {
226-
err = REFTABLE_FORMAT_ERROR;
243+
block_type = br->block.data[header_size];
244+
if (!reftable_is_block_type(block_type)) {
245+
err = REFTABLE_FORMAT_ERROR;
227246
goto done;
228247
}
229248

230-
if (typ == BLOCK_TYPE_LOG) {
231-
uint32_t block_header_skip = 4 + header_off;
232-
uLong dst_len = sz - block_header_skip;
233-
uLong src_len = block->len - block_header_skip;
249+
block_size = reftable_get_be24(br->block.data + header_size + 1);
250+
if (block_size > guess_block_size) {
251+
err = read_block(source, &br->block, offset, block_size);
252+
if (err < 0)
253+
goto done;
254+
}
255+
256+
if (block_type == BLOCK_TYPE_LOG) {
257+
uint32_t block_header_skip = 4 + header_size;
258+
uLong dst_len = block_size - block_header_skip;
259+
uLong src_len = br->block.len - block_header_skip;
234260

235261
/* Log blocks specify the *uncompressed* size in their header. */
236-
REFTABLE_ALLOC_GROW_OR_NULL(br->uncompressed_data, sz,
262+
REFTABLE_ALLOC_GROW_OR_NULL(br->uncompressed_data, block_size,
237263
br->uncompressed_cap);
238264
if (!br->uncompressed_data) {
239265
err = REFTABLE_OUT_OF_MEMORY_ERROR;
240266
goto done;
241267
}
242268

243269
/* Copy over the block header verbatim. It's not compressed. */
244-
memcpy(br->uncompressed_data, block->data, block_header_skip);
270+
memcpy(br->uncompressed_data, br->block.data, block_header_skip);
245271

246272
if (!br->zstream) {
247273
REFTABLE_CALLOC_ARRAY(br->zstream, 1);
@@ -259,7 +285,7 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
259285
goto done;
260286
}
261287

262-
br->zstream->next_in = block->data + block_header_skip;
288+
br->zstream->next_in = br->block.data + block_header_skip;
263289
br->zstream->avail_in = src_len;
264290
br->zstream->next_out = br->uncompressed_data + block_header_skip;
265291
br->zstream->avail_out = dst_len;
@@ -278,43 +304,41 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
278304
}
279305
err = 0;
280306

281-
if (br->zstream->total_out + block_header_skip != sz) {
307+
if (br->zstream->total_out + block_header_skip != block_size) {
282308
err = REFTABLE_FORMAT_ERROR;
283309
goto done;
284310
}
285311

286312
/* We're done with the input data. */
287-
block_source_return_block(block);
288-
block->data = br->uncompressed_data;
289-
block->len = sz;
313+
block_source_return_block(&br->block);
314+
br->block.data = br->uncompressed_data;
315+
br->block.len = block_size;
290316
full_block_size = src_len + block_header_skip - br->zstream->avail_in;
291317
} else if (full_block_size == 0) {
292-
full_block_size = sz;
293-
} else if (sz < full_block_size && sz < block->len &&
294-
block->data[sz] != 0) {
318+
full_block_size = block_size;
319+
} else if (block_size < full_block_size && block_size < br->block.len &&
320+
br->block.data[block_size] != 0) {
295321
/* If the block is smaller than the full block size, it is
296322
padded (data followed by '\0') or the next block is
297323
unaligned. */
298-
full_block_size = sz;
324+
full_block_size = block_size;
299325
}
300326

301-
restart_count = reftable_get_be16(block->data + sz - 2);
302-
restart_off = sz - 2 - 3 * restart_count;
303-
304-
/* transfer ownership. */
305-
br->block = *block;
306-
block->data = NULL;
307-
block->len = 0;
327+
restart_count = reftable_get_be16(br->block.data + block_size - 2);
328+
restart_off = block_size - 2 - 3 * restart_count;
308329

330+
br->block_type = block_type;
309331
br->hash_size = hash_size;
310332
br->restart_off = restart_off;
311333
br->full_block_size = full_block_size;
312-
br->header_off = header_off;
334+
br->header_off = header_size;
313335
br->restart_count = restart_count;
314336

315337
err = 0;
316338

317339
done:
340+
if (err < 0)
341+
block_reader_release(br);
318342
return err;
319343
}
320344

@@ -324,6 +348,7 @@ void block_reader_release(struct block_reader *br)
324348
reftable_free(br->zstream);
325349
reftable_free(br->uncompressed_data);
326350
block_source_return_block(&br->block);
351+
memset(br, 0, sizeof(*br));
327352
}
328353

329354
uint8_t block_reader_type(const struct block_reader *r)

reftable/block.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,14 @@ struct block_reader {
8989
/* size of the data in the file. For log blocks, this is the compressed
9090
* size. */
9191
uint32_t full_block_size;
92+
uint8_t block_type;
9293
};
9394

9495
/* initializes a block reader. */
95-
int block_reader_init(struct block_reader *br, struct reftable_block *bl,
96-
uint32_t header_off, uint32_t table_block_size,
97-
uint32_t hash_size);
96+
int block_reader_init(struct block_reader *br,
97+
struct reftable_block_source *source,
98+
uint32_t offset, uint32_t header_size,
99+
uint32_t table_block_size, uint32_t hash_size);
98100

99101
void block_reader_release(struct block_reader *br);
100102

reftable/table.c

Lines changed: 6 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,6 @@ table_offsets_for(struct reftable_table *t, uint8_t typ)
3030
abort();
3131
}
3232

33-
static int table_get_block(struct reftable_table *t,
34-
struct reftable_block *dest, uint64_t off,
35-
uint32_t sz)
36-
{
37-
ssize_t bytes_read;
38-
if (off >= t->size)
39-
return 0;
40-
if (off + sz > t->size)
41-
sz = t->size - off;
42-
43-
bytes_read = block_source_read_block(&t->source, dest, off, sz);
44-
if (bytes_read < 0)
45-
return (int)bytes_read;
46-
47-
return 0;
48-
}
49-
5033
enum reftable_hash reftable_table_hash_id(struct reftable_table *t)
5134
{
5235
return t->hash_id;
@@ -180,64 +163,28 @@ static void table_iter_block_done(struct table_iter *ti)
180163
block_iter_reset(&ti->bi);
181164
}
182165

183-
static int32_t extract_block_size(uint8_t *data, uint8_t *typ, uint64_t off,
184-
int version)
185-
{
186-
int32_t result = 0;
187-
188-
if (off == 0) {
189-
data += header_size(version);
190-
}
191-
192-
*typ = data[0];
193-
if (reftable_is_block_type(*typ)) {
194-
result = reftable_get_be24(data + 1);
195-
}
196-
return result;
197-
}
198-
199166
int table_init_block_reader(struct reftable_table *t, struct block_reader *br,
200167
uint64_t next_off, uint8_t want_typ)
201168
{
202-
int32_t guess_block_size = t->block_size ? t->block_size :
203-
DEFAULT_BLOCK_SIZE;
204-
struct reftable_block block = { NULL };
205-
uint8_t block_typ = 0;
206-
int err = 0;
207169
uint32_t header_off = next_off ? 0 : header_size(t->version);
208-
int32_t block_size = 0;
170+
int err;
209171

210172
if (next_off >= t->size)
211173
return 1;
212174

213-
err = table_get_block(t, &block, next_off, guess_block_size);
175+
err = block_reader_init(br, &t->source, next_off, header_off,
176+
t->block_size, hash_size(t->hash_id));
214177
if (err < 0)
215178
goto done;
216179

217-
block_size = extract_block_size(block.data, &block_typ, next_off,
218-
t->version);
219-
if (block_size < 0) {
220-
err = block_size;
221-
goto done;
222-
}
223-
if (want_typ != BLOCK_TYPE_ANY && block_typ != want_typ) {
180+
if (want_typ != BLOCK_TYPE_ANY && br->block_type != want_typ) {
224181
err = 1;
225182
goto done;
226183
}
227184

228-
if (block_size > guess_block_size) {
229-
block_source_return_block(&block);
230-
err = table_get_block(t, &block, next_off, block_size);
231-
if (err < 0) {
232-
goto done;
233-
}
234-
}
235-
236-
err = block_reader_init(br, &block, header_off, t->block_size,
237-
hash_size(t->hash_id));
238185
done:
239-
block_source_return_block(&block);
240-
186+
if (err)
187+
block_reader_release(br);
241188
return err;
242189
}
243190

0 commit comments

Comments
 (0)