shithub: gefs

Download patch

ref: 32de1f7a58b7b3a8476d1ceb3532e3317004a95c
parent: 62391489c0ccd5bb01a860b50523eb99905241d1
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Jan 4 13:16:04 EST 2024

tree: clean up code

--- a/tree.c
+++ b/tree.c
@@ -463,7 +463,7 @@
 updateleaf(Tree *t, Path *up, Path *p)
 {
 	char buf[Msgmax];
-	int i, j, ok, full, spc;
+	int i, j, c, ok, full, spc;
 	Blk *b, *n;
 	Bptr bp;
 	Msg m;
@@ -484,50 +484,62 @@
 	spc = Leafspc - blkfill(b);
 	n = newblk(t, b->type, 0);
 	assert(i >= 0 && j >= 0);
-	while(i < b->nval){
-		ok = 1;
-		getval(p->b, i, &v);
-		switch(pullmsg(up, j, &v, &m, &full, spc)){
+	while(i < b->nval || j < up->hi){
+		if(i >= b->nval)
+			c = 1;
+		else{
+			c = -1;
+			getval(p->b, i, &v);
+			if(j < up->hi){
+				if(up->ins != nil)
+					m = up->ins[j];
+				else
+					getmsg(up->b, j, &m);
+				if(msgsz(&m) <= spc)
+					c = keycmp(&v, &m);
+				else
+					full = 1;
+			}
+		}
+		switch(c){
+		/* Value before message: just copy value */
 		case -1:
-			setval(n, &v);
 			i++;
+			setval(n, &v);
 			break;
-		case 1:
-			/*
-			 * new values must always start as
-			 * an insertion, mutations come after.
-			 */
-			if(m.op == Oclearb || m.op == Oclobber)
-				ok = 0;
-			else if(m.op != Oinsert)
-				fatal("%d(/%d), %d: %M not insert\n", i, b->nval, j, &m);
-			cpkvp(&v, &m, buf, sizeof(buf));
-			spc -= valsz(&m);
-			goto Copy;
+		/* Value merges with message sequence */
 		case 0:
 			i++;
-			if(m.op != Oinsert)
-				cpkvp(&v, &v, buf, sizeof(buf));
+			j++;
+			cpkvp(&v, &v, buf, sizeof(buf));
+			ok = apply(&v, &m, buf, sizeof(buf));
+			if(ok && m.op == Oclearb){
+				bp = unpackbp(v.v, v.nv);
+				freeblk(t, nil, bp);
+			}
+			goto Copyloop;
+		/* Message before value: Insert message sequence */
+		case 1:
+			j++;
+			cpkvp(&v, &m, buf, sizeof(buf));
+			ok = 0;
+			if(m.op != Oclearb && m.op != Oclobber){
+				spc -= valsz(&m);
+				p->pullsz += msgsz(&m);
+				ok = 1;
+			}
+			goto Copyloop;
+		Copyloop:
 			while(j < up->hi){
-				/*
-				 * If a file is truncated multiple times,
-				 * we can end up with duplicate Oclearb
-				 * messages in the buffer.
-				 *
-				 * These Oclearb doublings will leave
-				 * v.nv with a length of 0, so we can
-				 * and should skip those
-				 */
-				if(m.op == Oclearb && v.nv != 0){
+				if(pullmsg(up, j, &v, &m, &full, spc) != 0)
+					break;
+				if(ok && m.op == Oclearb){
 					bp = unpackbp(v.v, v.nv);
 					freeblk(t, nil, bp);
 				}
+				p->pullsz += msgsz(&m);
 				ok = apply(&v, &m, buf, sizeof(buf));
-		Copy:
 				j++;
-				p->pullsz += msgsz(&m);
-				if(j >= up->hi || pullmsg(up, j, &v, &m, &full, spc) != 0)
-					break;
 			}
 			if(ok)
 				setval(n, &v);
@@ -534,24 +546,6 @@
 			break;
 		}
 	}
-	while(j < up->hi) {
-		/* can't fail */
-		pullmsg(up, j++, nil, &m, &full, spc);
-		ok = 1;
-		cpkvp(&v, &m, buf, sizeof(buf));
-		p->pullsz += msgsz(&m);
-		if(m.op == Oclearb || m.op == Oclobber)
-			continue;
-		if(m.op != Oinsert)
-			fatal("%d(/%d), %d: %M not insert\n", i, b->nval, j, &m);
-		while(pullmsg(up, j, &v, &m, &full, spc) == 0){
-			ok = apply(&v, &m, buf, sizeof(buf));
-			p->pullsz += msgsz(&m);
-			j++;
-		}
-		if(ok)
-			setval(n, &v);
-	}
 	p->npull = (j - up->lo);
 	p->nl = n;
 }
@@ -637,9 +631,10 @@
 splitleaf(Tree *t, Path *up, Path *p, Kvp *mid)
 {
 	char buf[Msgmax];
+	Blk *b, *d, *l, *r;
 	int full, copied, spc, ok, halfsz;
 	int i, j, c;
-	Blk *b, *d, *l, *r;
+	Bptr bp;
 	Msg m;
 	Kvp v;
 
@@ -682,38 +677,47 @@
 			spc = Leafspc - (halfsz + Msgmax);
 			getval(b, i, mid);
 		}
-		ok = 1;
 		getval(b, i, &v);
  		c = pullmsg(up, j, &v, &m, &full, spc);
 		switch(c){
 		case -1:
+			i++;
 			setval(d, &v);
 			copied += valsz(&v);
-			i++;
 			break;
-		case 1:
-			/*
-			 * new values must always start as
-			 * an insertion, mutations come after.
-			 */
-			if(m.op == Oclearb || m.op == Oclobber)
-				ok = 0;
-			else if(m.op != Oinsert)
-				fatal("%d(/%d), %d: expected insert, got %M\n", i, b->nval, j, &m);
-			cpkvp(&v, &m, buf, sizeof(buf));
-			spc -= valsz(&m);
-			goto Copy;
 		case 0:
 			i++;
-			if(m.op != Oinsert)
-				cpkvp(&v, &v, buf, sizeof(buf));
+			j++;
+			cpkvp(&v, &v, buf, sizeof(buf));
+			copied += valsz(&v);
+			ok = apply(&v, &m, buf, sizeof(buf));
+			if(ok && m.op == Oclearb){
+				bp = unpackbp(v.v, v.nv);
+				freeblk(t, nil, bp);
+			}
+			goto Copyloop;
+		case 1:
+			j++;
+			cpkvp(&v, &m, buf, sizeof(buf));
+			copied += valsz(&v);
+			ok = 0;
+			if(m.op != Oclearb && m.op != Oclobber){
+				spc -= valsz(&m);
+				p->pullsz += msgsz(&m);
+				ok = 1;
+			}
+			goto Copyloop;
+		Copyloop:
 			while(j < up->hi){
-				ok = apply(&v, &m, buf, sizeof(buf));
-		Copy:
+				if(pullmsg(up, j, &v, &m, &full, spc) != 0)
+					break;
+				if(ok && m.op == Oclearb){
+					bp = unpackbp(v.v, v.nv);
+					freeblk(t, nil, bp);
+				}
 				p->pullsz += msgsz(&m);
+				ok = apply(&v, &m, buf, sizeof(buf));
 				j++;
-				if(j == up->hi || pullmsg(up, j, &v, &m, &full, spc) != 0)
-					break;
 			}
 			if(ok)
 				setval(d, &v);