-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chunk-format: create chunk format write API
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 <[email protected]> Helped-by: Junio C Hamano <[email protected]> Signed-off-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
- Loading branch information
1 parent
eb90719
commit 570df42
Showing
3 changed files
with
112 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |