Browse Source
In anticipation of combining the logic from the commit-graph and multi-pack-index file formats, create a new chunk-format API. Use a 'struct chunkfile' pointer to keep track of data that has been registered for writes. This struct is anonymous outside of chunk-format.c to ensure no user attempts to interfere with the data. The next change will use this API in commit-graph.c, but the general approach is: 1. initialize the chunkfile with init_chunkfile(f). 2. add chunks in the intended writing order with add_chunk(). 3. write any header information to the hashfile f. 4. write the chunkfile data using write_chunkfile(). 5. free the chunkfile struct using free_chunkfile(). Helped-by: Taylor Blau <me@ttaylorr.com> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint


3 changed files with 112 additions and 0 deletions
@ -0,0 +1,90 @@
@@ -0,0 +1,90 @@
|
||||
#include "cache.h" |
||||
#include "chunk-format.h" |
||||
#include "csum-file.h" |
||||
|
||||
/* |
||||
* When writing a chunk-based file format, collect the chunks in |
||||
* an array of chunk_info structs. The size stores the _expected_ |
||||
* amount of data that will be written by write_fn. |
||||
*/ |
||||
struct chunk_info { |
||||
uint32_t id; |
||||
uint64_t size; |
||||
chunk_write_fn write_fn; |
||||
}; |
||||
|
||||
struct chunkfile { |
||||
struct hashfile *f; |
||||
|
||||
struct chunk_info *chunks; |
||||
size_t chunks_nr; |
||||
size_t chunks_alloc; |
||||
}; |
||||
|
||||
struct chunkfile *init_chunkfile(struct hashfile *f) |
||||
{ |
||||
struct chunkfile *cf = xcalloc(1, sizeof(*cf)); |
||||
cf->f = f; |
||||
return cf; |
||||
} |
||||
|
||||
void free_chunkfile(struct chunkfile *cf) |
||||
{ |
||||
if (!cf) |
||||
return; |
||||
free(cf->chunks); |
||||
free(cf); |
||||
} |
||||
|
||||
int get_num_chunks(struct chunkfile *cf) |
||||
{ |
||||
return cf->chunks_nr; |
||||
} |
||||
|
||||
void add_chunk(struct chunkfile *cf, |
||||
uint32_t id, |
||||
size_t size, |
||||
chunk_write_fn fn) |
||||
{ |
||||
ALLOC_GROW(cf->chunks, cf->chunks_nr + 1, cf->chunks_alloc); |
||||
|
||||
cf->chunks[cf->chunks_nr].id = id; |
||||
cf->chunks[cf->chunks_nr].write_fn = fn; |
||||
cf->chunks[cf->chunks_nr].size = size; |
||||
cf->chunks_nr++; |
||||
} |
||||
|
||||
int write_chunkfile(struct chunkfile *cf, void *data) |
||||
{ |
||||
int i; |
||||
uint64_t cur_offset = hashfile_total(cf->f); |
||||
|
||||
/* Add the table of contents to the current offset */ |
||||
cur_offset += (cf->chunks_nr + 1) * CHUNK_TOC_ENTRY_SIZE; |
||||
|
||||
for (i = 0; i < cf->chunks_nr; i++) { |
||||
hashwrite_be32(cf->f, cf->chunks[i].id); |
||||
hashwrite_be64(cf->f, cur_offset); |
||||
|
||||
cur_offset += cf->chunks[i].size; |
||||
} |
||||
|
||||
/* Trailing entry marks the end of the chunks */ |
||||
hashwrite_be32(cf->f, 0); |
||||
hashwrite_be64(cf->f, cur_offset); |
||||
|
||||
for (i = 0; i < cf->chunks_nr; i++) { |
||||
off_t start_offset = hashfile_total(cf->f); |
||||
int result = cf->chunks[i].write_fn(cf->f, data); |
||||
|
||||
if (result) |
||||
return result; |
||||
|
||||
if (hashfile_total(cf->f) - start_offset != cf->chunks[i].size) |
||||
BUG("expected to write %"PRId64" bytes to chunk %"PRIx32", but wrote %"PRId64" instead", |
||||
cf->chunks[i].size, cf->chunks[i].id, |
||||
hashfile_total(cf->f) - start_offset); |
||||
} |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
#ifndef CHUNK_FORMAT_H |
||||
#define CHUNK_FORMAT_H |
||||
|
||||
#include "git-compat-util.h" |
||||
|
||||
struct hashfile; |
||||
struct chunkfile; |
||||
|
||||
#define CHUNK_TOC_ENTRY_SIZE (sizeof(uint32_t) + sizeof(uint64_t)) |
||||
|
||||
struct chunkfile *init_chunkfile(struct hashfile *f); |
||||
void free_chunkfile(struct chunkfile *cf); |
||||
int get_num_chunks(struct chunkfile *cf); |
||||
typedef int (*chunk_write_fn)(struct hashfile *f, void *data); |
||||
void add_chunk(struct chunkfile *cf, |
||||
uint32_t id, |
||||
size_t size, |
||||
chunk_write_fn fn); |
||||
int write_chunkfile(struct chunkfile *cf, void *data); |
||||
|
||||
#endif |
Loading…
Reference in new issue