commit c3703302b15feb5ec68b86fa86ffbc78a7aa670b from: Stefan Sperling date: Tue Jan 23 14:19:45 2018 UTC model delta chains in a better way commit - 5a2e13f79259a3935a3d6aa3cb242d1e33877ef9 commit + c3703302b15feb5ec68b86fa86ffbc78a7aa670b blob - 9c70b677f3a1b9e8dafc55e075a180cdf42e887d blob + e3a0f891cc456e23b9a1b1a45535bce0d61a5387 --- lib/delta.c +++ lib/delta.c @@ -28,51 +28,51 @@ #include "delta.h" -struct got_delta_base * -got_delta_base_open(const char *path_packfile, int type, off_t offset, +struct got_delta * +got_delta_open(const char *path_packfile, int type, off_t offset, size_t size) { - struct got_delta_base *base; + struct got_delta *delta; - base = calloc(1, sizeof(*base)); - if (base == NULL) + delta = calloc(1, sizeof(*delta)); + if (delta == NULL) return NULL; - base->path_packfile = strdup(path_packfile); - if (base->path_packfile == NULL) { - free(base); + delta->path_packfile = strdup(path_packfile); + if (delta->path_packfile == NULL) { + free(delta); return NULL; } - base->type = type; - base->offset = offset; - base->size = size; - return base; + delta->type = type; + delta->offset = offset; + delta->size = size; + return delta; } void -got_delta_base_close(struct got_delta_base *base) +got_delta_close(struct got_delta *delta) { - free(base->path_packfile); - free(base); + free(delta->path_packfile); + free(delta); } const struct got_error * got_delta_chain_get_base_type(int *type, struct got_delta_chain *deltas) { - struct got_delta_base *base; + struct got_delta *delta; int n = 0; - /* Find the last base in the chain. It should be a plain object. */ - SIMPLEQ_FOREACH(base, &deltas->entries, entry) { + /* Find the last delta in the chain. It should be a plain object. */ + SIMPLEQ_FOREACH(delta, &deltas->entries, entry) { n++; - if (base->type == GOT_OBJ_TYPE_COMMIT || - base->type == GOT_OBJ_TYPE_TREE || - base->type == GOT_OBJ_TYPE_BLOB || - base->type == GOT_OBJ_TYPE_TAG) { + if (delta->type == GOT_OBJ_TYPE_COMMIT || + delta->type == GOT_OBJ_TYPE_TREE || + delta->type == GOT_OBJ_TYPE_BLOB || + delta->type == GOT_OBJ_TYPE_TAG) { if (n != deltas->nentries) return got_error(GOT_ERR_BAD_DELTA_CHAIN); - *type = base->type; + *type = delta->type; return NULL; } } blob - 62886c7c82e09b5d1c86b0ca6f0a878d32fdd799 blob + 1410200d3d473b20e4826c4517191df7013a47ae --- lib/delta.h +++ lib/delta.h @@ -14,8 +14,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -struct got_delta_base { - SIMPLEQ_ENTRY(got_delta_base) entry; +struct got_delta { + SIMPLEQ_ENTRY(got_delta) entry; char *path_packfile; off_t offset; int type; @@ -24,11 +24,11 @@ struct got_delta_base { struct got_delta_chain { int nentries; - SIMPLEQ_HEAD(, got_delta_base) entries; + SIMPLEQ_HEAD(, got_delta) entries; }; -struct got_delta_base *got_delta_base_open(const char *, int, off_t, size_t); -void got_delta_base_close(struct got_delta_base *); +struct got_delta *got_delta_open(const char *, int, off_t, size_t); +void got_delta_close(struct got_delta *); const struct got_error *got_delta_chain_get_base_type(int *, struct got_delta_chain *) ; const struct got_error * blob - e3f1c9f9a937caec05aa78177ba1e2dd15b7efa5 blob + a721709119aba653daa7e240526d7b3fa4ba89a5 --- lib/object.c +++ lib/object.c @@ -336,11 +336,11 @@ void got_object_close(struct got_object *obj) { if (obj->flags & GOT_OBJ_FLAG_DELTIFIED) { - struct got_delta_base *base; + struct got_delta *delta; while (!SIMPLEQ_EMPTY(&obj->deltas.entries)) { - base = SIMPLEQ_FIRST(&obj->deltas.entries); + delta = SIMPLEQ_FIRST(&obj->deltas.entries); SIMPLEQ_REMOVE_HEAD(&obj->deltas.entries, entry); - got_delta_base_close(base); + got_delta_close(delta); } } if (obj->flags & GOT_OBJ_FLAG_PACKED) blob - 6c4139fbdfc2df2d94af6b3e3a6f0ffb9497ccce blob + 36403790a36579c86f0729411a12b212116126df --- lib/pack.c +++ lib/pack.c @@ -329,7 +329,8 @@ read_packfile_hdr(FILE *f, struct got_packidx_v2_hdr * } static const struct got_error * -decode_type_and_size(uint8_t *type, uint64_t *size, size_t *len, FILE *packfile) +decode_object_type_and_size(uint8_t *type, uint64_t *size, size_t *len, + FILE *packfile) { uint8_t t = 0; uint64_t s = 0; @@ -440,59 +441,61 @@ parse_offset_delta(off_t *base_offset, FILE *packfile, } static const struct got_error *resolve_delta_chain(struct got_delta_chain *, - FILE *, const char *, off_t, size_t); + FILE *, const char *, int, off_t, size_t); static const struct got_error * resolve_offset_delta(struct got_delta_chain *deltas, FILE *packfile, - const char *path_packfile, off_t offset, size_t delta_size) + const char *path_packfile, off_t delta_offset) { const struct got_error *err; - off_t next_offset; + off_t base_offset; + uint8_t base_type; + uint64_t base_size; + size_t base_tslen; - err = parse_offset_delta(&next_offset, packfile, offset); + err = parse_offset_delta(&base_offset, packfile, delta_offset); if (err) return err; - /* Next offset must be in the same packfile. */ - return resolve_delta_chain(deltas, packfile, path_packfile, - next_offset, delta_size); -} - -static const struct got_error * -resolve_delta_chain(struct got_delta_chain *deltas, FILE *packfile, - const char *path_packfile, off_t offset, size_t delta_size) -{ - const struct got_error *err = NULL; - uint8_t base_type; - uint64_t base_size; - size_t base_tslen; - struct got_delta_base *base; - - if (fseeko(packfile, offset, SEEK_SET) != 0) + /* An offset delta must be in the same packfile. */ + if (fseeko(packfile, base_offset, SEEK_SET) != 0) return got_error_from_errno(); - err = decode_type_and_size(&base_type, &base_size, &base_tslen, + err = decode_object_type_and_size(&base_type, &base_size, &base_tslen, packfile); if (err) return err; - base = got_delta_base_open(path_packfile, base_type, offset, + return resolve_delta_chain(deltas, packfile, path_packfile, + base_type, base_offset + base_tslen, base_size); +} + +static const struct got_error * +resolve_delta_chain(struct got_delta_chain *deltas, FILE *packfile, + const char *path_packfile, int delta_type, off_t delta_offset, + size_t delta_size) +{ + const struct got_error *err = NULL; + struct got_delta *delta; + + delta = got_delta_open(path_packfile, delta_type, delta_offset, delta_size); - if (base == NULL) + if (delta == NULL) return got_error(GOT_ERR_NO_MEM); deltas->nentries++; - SIMPLEQ_INSERT_TAIL(&deltas->entries, base, entry); - /* In case of error below, base will be freed in got_object_close(). */ + SIMPLEQ_INSERT_TAIL(&deltas->entries, delta, entry); + /* In case of error below, delta is freed in got_object_close(). */ - switch (base_type) { + switch (delta_type) { case GOT_OBJ_TYPE_COMMIT: case GOT_OBJ_TYPE_TREE: case GOT_OBJ_TYPE_BLOB: case GOT_OBJ_TYPE_TAG: + /* Plain types are the final delta base. Recursion ends. */ break; case GOT_OBJ_TYPE_OFFSET_DELTA: err = resolve_offset_delta(deltas, packfile, path_packfile, - offset, base_size); + delta_offset); break; case GOT_OBJ_TYPE_REF_DELTA: default: @@ -506,20 +509,15 @@ static const struct got_error * open_offset_delta_object(struct got_object **obj, struct got_repository *repo, struct got_packidx_v2_hdr *packidx, const char *path_packfile, FILE *packfile, struct got_object_id *id, - off_t offset, size_t tslen, size_t size) + off_t offset, size_t tslen, size_t delta_size) { const struct got_error *err = NULL; - off_t base_offset; struct got_object_id base_id; uint8_t base_type; int resolved_type; uint64_t base_size; size_t base_tslen; - err = parse_offset_delta(&base_offset, packfile, offset); - if (err) - return err; - *obj = calloc(1, sizeof(**obj)); if (*obj == NULL) return got_error(GOT_ERR_NO_MEM); @@ -539,8 +537,9 @@ open_offset_delta_object(struct got_object **obj, SIMPLEQ_INIT(&(*obj)->deltas.entries); (*obj)->flags |= GOT_OBJ_FLAG_DELTIFIED; + err = resolve_delta_chain(&(*obj)->deltas, packfile, path_packfile, - base_offset, size); + GOT_OBJ_TYPE_OFFSET_DELTA, offset, delta_size); if (err) goto done; @@ -605,7 +604,7 @@ open_packed_object(struct got_object **obj, struct got goto done; } - err = decode_type_and_size(&type, &size, &tslen, packfile); + err = decode_object_type_and_size(&type, &size, &tslen, packfile); if (err) goto done;