shithub: git9

Download patch

ref: d90da7bc1a7f9815f131d4f2c28a206e234d1a46
parent: 72fbfa9bb7a264e1c7a2175cb36a06effb628cf7
author: Ori Bernstein <ori@eigenstate.org>
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);