Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c1af5a3

Browse files
carlosmnvmg
authored andcommitted
Implement cooperative caching
When indexing a file with ref deltas, a temporary cache for the offsets has to be built, as we don't have an index file yet. If the user takes the responsiblity for filling the cache, the packing code will look there first when it finds a ref delta. Signed-off-by: Carlos Martín Nieto <[email protected]>
1 parent 061047c commit c1af5a3

File tree

3 files changed

+49
-4
lines changed

3 files changed

+49
-4
lines changed

src/indexer.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,23 @@ static int parse_header(git_indexer *idx)
7979
return GIT_SUCCESS;
8080
}
8181

82-
int objects_cmp(const void *a, const void *b)
82+
static int objects_cmp(const void *a, const void *b)
8383
{
8484
const struct entry *entrya = a;
8585
const struct entry *entryb = b;
8686

8787
return git_oid_cmp(&entrya->oid, &entryb->oid);
8888
}
8989

90+
static int cache_cmp(const void *a, const void *b)
91+
{
92+
const struct git_pack_entry *ea = a;
93+
const struct git_pack_entry *eb = b;
94+
95+
return git_oid_cmp(&ea->sha1, &eb->sha1);
96+
}
97+
98+
9099
int git_indexer_new(git_indexer **out, const char *packname)
91100
{
92101
git_indexer *idx;
@@ -139,10 +148,14 @@ int git_indexer_new(git_indexer **out, const char *packname)
139148

140149
idx->nr_objects = ntohl(idx->hdr.hdr_entries);
141150

151+
error = git_vector_init(&idx->pack->cache, idx->nr_objects, cache_cmp);
152+
if (error < GIT_SUCCESS)
153+
goto cleanup;
154+
155+
idx->pack->has_cache = 1;
142156
error = git_vector_init(&idx->objects, idx->nr_objects, objects_cmp);
143-
if (error < GIT_SUCCESS) {
157+
if (error < GIT_SUCCESS)
144158
goto cleanup;
145-
}
146159

147160
*out = idx;
148161

@@ -250,6 +263,7 @@ int git_indexer_write(git_indexer *idx)
250263
/* Write out the packfile trailer */
251264

252265
packfile_hash = git_mwindow_open(&idx->pack->mwf, &w, idx->st.st_size - GIT_OID_RAWSZ, GIT_OID_RAWSZ, &left);
266+
git_mwindow_close(&w);
253267
if (packfile_hash == NULL) {
254268
error = git__rethrow(GIT_ENOMEM, "Failed to open window to packfile hash");
255269
goto cleanup;
@@ -276,6 +290,7 @@ int git_indexer_write(git_indexer *idx)
276290
error = git_filebuf_commit_at(&idx->file, filename);
277291

278292
cleanup:
293+
git_mwindow_free_all(&idx->pack->mwf);
279294
if (error < GIT_SUCCESS)
280295
git_filebuf_cleanup(&idx->file);
281296

@@ -303,6 +318,7 @@ int git_indexer_run(git_indexer *idx, git_indexer_stats *stats)
303318
while (processed < idx->nr_objects) {
304319
git_rawobj obj;
305320
git_oid oid;
321+
struct git_pack_entry *pentry;
306322
git_mwindow *w = NULL;
307323
char hdr[512] = {0}; /* FIXME: How long should this be? */
308324
int i, hdr_len;
@@ -326,12 +342,24 @@ int git_indexer_run(git_indexer *idx, git_indexer_stats *stats)
326342
goto cleanup;
327343
}
328344

345+
/* FIXME: Parse the object instead of hashing it */
329346
error = git_odb__hash_obj(&oid, hdr, sizeof(hdr), &hdr_len, &obj);
330347
if (error < GIT_SUCCESS) {
331348
error = git__rethrow(error, "Failed to hash object");
332349
goto cleanup;
333350
}
334351

352+
pentry = git__malloc(sizeof(struct git_pack_entry));
353+
if (pentry == NULL) {
354+
error = GIT_ENOMEM;
355+
goto cleanup;
356+
}
357+
git_oid_cpy(&pentry->sha1, &oid);
358+
pentry->offset = entry_start;
359+
error = git_vector_insert(&idx->pack->cache, pentry);
360+
if (error < GIT_SUCCESS)
361+
goto cleanup;
362+
335363
git_oid_cpy(&entry->oid, &oid);
336364
entry->crc = crc32(0L, Z_NULL, 0);
337365

@@ -371,11 +399,15 @@ void git_indexer_free(git_indexer *idx)
371399
{
372400
unsigned int i;
373401
struct entry *e;
402+
struct git_pack_entry *pe;
374403

375404
p_close(idx->pack->mwf.fd);
376405
git_vector_foreach(&idx->objects, i, e)
377406
free(e);
378407
git_vector_free(&idx->objects);
408+
git_vector_foreach(&idx->pack->cache, i, pe)
409+
free(pe);
410+
git_vector_free(&idx->pack->cache);
379411
free(idx->pack);
380412
free(idx);
381413
}

src/pack.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,18 @@ off_t get_delta_base(
473473
return 0; /* out of bound */
474474
*curpos += used;
475475
} else if (type == GIT_OBJ_REF_DELTA) {
476+
/* If we have the cooperative cache, search in it first */
477+
if (p->has_cache) {
478+
int pos;
479+
struct git_pack_entry key;
480+
481+
git_oid_fromraw(&key.sha1, base_info);
482+
pos = git_vector_bsearch(&p->cache, &key);
483+
if (pos >= 0) {
484+
*curpos += 20;
485+
return ((struct git_pack_entry *)git_vector_get(&p->cache, pos))->offset;
486+
}
487+
}
476488
/* The base entry _must_ be in the same pack */
477489
if (pack_entry_find_offset(&base_offset, &unused, p, (git_oid *)base_info, GIT_OID_HEXSZ) < GIT_SUCCESS)
478490
return git__rethrow(GIT_EPACKCORRUPTED, "Base entry delta is not in the same pack");

src/pack.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,9 @@ struct git_pack_file {
7777

7878
int index_version;
7979
git_time_t mtime;
80-
unsigned pack_local:1, pack_keep:1;
80+
unsigned pack_local:1, pack_keep:1, has_cache:1;
8181
git_oid sha1;
82+
git_vector cache;
8283

8384
/* something like ".git/objects/pack/xxxxx.pack" */
8485
char pack_name[GIT_FLEX_ARRAY]; /* more */

0 commit comments

Comments
 (0)