ref: d90da7bc1a7f9815f131d4f2c28a206e234d1a46
parent: 72fbfa9bb7a264e1c7a2175cb36a06effb628cf7
author: Ori Bernstein <[email protected]>
date: Wed Dec 30 00:35:49 EST 2020
git/send: fix delta caching The delta table refers to the buffer within the object, so it should hold a reference to the object. While in here, clean up the code a bit.
--- a/delta.c
+++ b/delta.c
@@ -124,7 +124,7 @@
}
void
-dtinit(Dtab *dt, void *base, int nbase)
+dtinit(Dtab *dt, Object *obj)
{
uchar *s, *e;
u64int h;
@@ -131,13 +131,14 @@
vlong n, o;
o = 0;
- s = base;
- e = s + nbase;
+ s = (uchar*)obj->data;
+ e = s + obj->size;
+ dt->o = ref(obj);
dt->nb = 0;
dt->sz = 128;
dt->b = eamalloc(dt->sz, sizeof(Dblock));
- dt->base = base;
- dt->nbase = nbase;
+ dt->base = (uchar*)obj->data;
+ dt->nbase = obj->size;
while(s != e){
n = nextblk(s, e);
h = hash(s, n);
@@ -150,6 +151,7 @@
void
dtclear(Dtab *dt)
{
+ unref(dt->o);
free(dt->b);
}
@@ -190,7 +192,7 @@
}
Delta*
-deltify(void *targ, int ntarg, Dtab *dt, int *pnd)
+deltify(Object *obj, Dtab *dt, int *pnd)
{
Delta *d;
Dblock *b;
@@ -199,8 +201,8 @@
o = 0;
d = nil;
- s = targ;
- e = s + ntarg;
+ s = (uchar*)obj->data;
+ e = s + obj->size;
*pnd = 0;
while(s != e){
n = nextblk(s, e);
--- a/git.h
+++ b/git.h
@@ -152,6 +152,7 @@
};
struct Dtab {
+ Object *o;
uchar *base;
int nbase;
Dblock *b;
@@ -287,9 +288,9 @@
int showprogress(int, int);
/* packing */
-void dtinit(Dtab *, void *, int);
+void dtinit(Dtab *, Object*);
void dtclear(Dtab*);
-Delta* deltify(void*, int, Dtab*, int*);
+Delta* deltify(Object*, Dtab*, int*);
/* proto handling */
int readpkt(Conn*, char*, int);
--- a/pack.c
+++ b/pack.c
@@ -25,8 +25,7 @@
/* The best delta we picked */
Meta *head;
- Meta *prev;
- Object *base;
+ Meta *prev;
Delta *delta;
int ndelta;
int nchain;
@@ -516,7 +515,6 @@
werrstr("object too big");
return -1;
}
-
switch(t){
default:
werrstr("invalid object at %lld", Boffset(f));
@@ -1361,7 +1359,6 @@
for(i = 0; i < nmeta; i++){
m = meta[i];
pct = showprogress((i*100) / nmeta, pct);
- m->base = nil;
m->delta = nil;
m->ndelta = 0;
if(m->obj->type == GCommit || m->obj->type == GTag)
@@ -1368,16 +1365,16 @@
continue;
if((o = readobject(m->obj->hash)) == nil)
sysfatal("readobject %H: %r", m->obj->hash);
- best = o->size;
- dtinit(&m->dtab, o->data, o->size);
+ dtinit(&m->dtab, o);
if(i >= 11)
dtclear(&meta[i-11]->dtab);
+ best = o->size;
for(j = max(0, i - 10); j < i; j++){
p = meta[j];
/* long chains make unpacking slow */
if(p->nchain >= 128 || p->obj->type != o->type)
continue;
- d = deltify(o->data, o->size, &p->dtab, &nd);
+ d = deltify(o, &p->dtab, &nd);
sz = deltasz(d, nd);
if(sz + 32 < best){
/*
@@ -1393,9 +1390,6 @@
m->head = p->head;
if(m->head == nil)
m->head = p;
- if((m->base = readobject(p->obj->hash)) == nil)
- sysfatal("readobject %H: %r", p->obj->hash);
- unref(m->base);
}else
free(d);
}
@@ -1564,7 +1558,7 @@
DigestState *st;
Biobuf *bfd;
Meta *m;
- Object *o;
+ Object *o, *b;
char *p, buf[32];
st = nil;
@@ -1587,8 +1581,9 @@
if(interactive)
fprint(2, "writing %d objects: 0%%", nmeta);
for(i = 0; i < nmeta; i++){
- m = meta[i];
pct = showprogress((i*100)/nmeta, pct);
+ m = meta[i];
+ m->off = Boffset(bfd);
if((o = readobject(m->obj->hash)) == nil)
return -1;
if(m->delta == nil){
@@ -1597,8 +1592,9 @@
if(hcompress(bfd, o->data, o->size, &st) == -1)
goto error;
}else{
- m->off = Boffset(bfd);
- nd = encodedelta(m, o, m->base, &p);
+ b = readobject(m->prev->obj->hash);
+ nd = encodedelta(m, o, b, &p);
+ unref(b);
if(odelta && m->prev->off != 0){
nh = 0;
nh += packhdr(buf, GOdelta, nd);
@@ -1607,7 +1603,7 @@
}else{
nh = packhdr(buf, GRdelta, nd);
hwrite(bfd, buf, nh, &st);
- hwrite(bfd, m->base->hash.h, sizeof(m->base->hash.h), &st);
+ hwrite(bfd, m->prev->obj->hash.h, sizeof(m->prev->obj->hash.h), &st);
}
res = hcompress(bfd, p, nd, &st);
free(p);