Commit 13c729f71056495e3b532f94badea43f10d98f49

Stefan Sperling 2018-12-24T09:35:07

eliminate got_object_open() round-trip when opening trees

diff --git a/lib/got_lib_object_parse.h b/lib/got_lib_object_parse.h
index ae71532..6e02969 100644
--- a/lib/got_lib_object_parse.h
+++ b/lib/got_lib_object_parse.h
@@ -24,7 +24,7 @@ const struct got_error *got_object_read_blob_privsep(size_t *, int, int,
 const struct got_error *got_object_read_commit_privsep(
     struct got_commit_object **, int, struct got_repository *);
 const struct got_error *got_object_read_tree_privsep(struct got_tree_object **,
-    struct got_object *, int, struct got_repository *);
+    int, struct got_repository *);
 const struct got_error *got_object_read_tag_privsep(struct got_tag_object **,
     struct got_object *, int, struct got_repository *);
 
diff --git a/lib/got_lib_privsep.h b/lib/got_lib_privsep.h
index 6f054bf..2aeba35 100644
--- a/lib/got_lib_privsep.h
+++ b/lib/got_lib_privsep.h
@@ -220,6 +220,8 @@ const struct got_error *got_privsep_send_obj_req(struct imsgbuf *, int,
     struct got_object *);
 const struct got_error *got_privsep_send_commit_req(struct imsgbuf *, int,
     struct got_object_id *, int);
+const struct got_error *got_privsep_send_tree_req(struct imsgbuf *, int,
+    struct got_object_id *, int);
 const struct got_error *got_privsep_send_blob_req(struct imsgbuf *, int);
 const struct got_error *got_privsep_send_blob_outfd(struct imsgbuf *, int);
 const struct got_error *got_privsep_send_tmpfd(struct imsgbuf *, int);
diff --git a/lib/object.c b/lib/object.c
index 3694021..7c1b78c 100644
--- a/lib/object.c
+++ b/lib/object.c
@@ -543,12 +543,13 @@ got_object_qid_alloc(struct got_object_qid **qid, struct got_object_id *id)
 }
 
 static const struct got_error *
-read_packed_tree_privsep(struct got_tree_object **tree,
-    struct got_object *obj, struct got_pack *pack)
+request_packed_tree(struct got_tree_object **tree, struct got_pack *pack,
+    int pack_idx, struct got_object_id *id)
 {
 	const struct got_error *err = NULL;
 
-	err = got_privsep_send_obj_req(pack->privsep_child->ibuf, -1, obj);
+	err = got_privsep_send_tree_req(pack->privsep_child->ibuf, -1, id,
+	    pack_idx);
 	if (err)
 		return err;
 
@@ -556,13 +557,33 @@ read_packed_tree_privsep(struct got_tree_object **tree,
 }
 
 static const struct got_error *
-open_tree(struct got_tree_object **tree,
-    struct got_repository *repo, struct got_object *obj, int check_cache)
+read_packed_tree_privsep(struct got_tree_object **tree,
+    struct got_pack *pack, struct got_packidx *packidx, int idx,
+    struct got_object_id *id)
+{
+	const struct got_error *err = NULL;
+
+	if (pack->privsep_child)
+		return request_packed_tree(tree, pack, idx, id);
+
+	err = start_pack_privsep_child(pack, packidx);
+	if (err)
+		return err;
+
+	return request_packed_tree(tree, pack, idx, id);
+}
+
+static const struct got_error *
+open_tree(struct got_tree_object **tree, struct got_repository *repo,
+    struct got_object_id *id, int check_cache)
 {
 	const struct got_error *err = NULL;
+	struct got_packidx *packidx = NULL;
+	int idx;
+	char *path_packfile;
 
 	if (check_cache) {
-		*tree = got_repo_get_cached_tree(repo, &obj->id);
+		*tree = got_repo_get_cached_tree(repo, id);
 		if (*tree != NULL) {
 			(*tree)->refcnt++;
 			return NULL;
@@ -570,31 +591,36 @@ open_tree(struct got_tree_object **tree,
 	} else
 		*tree = NULL;
 
-	if (obj->type != GOT_OBJ_TYPE_TREE)
-		return got_error(GOT_ERR_OBJ_TYPE);
+	err = got_repo_search_packidx(&packidx, &idx, repo, id);
+	if (err == NULL) {
+		struct got_pack *pack = NULL;
 
-	if (obj->flags & GOT_OBJ_FLAG_PACKED) {
-		struct got_pack *pack;
-		pack = got_repo_get_cached_pack(repo, obj->path_packfile);
+		err = get_packfile_path(&path_packfile, packidx);
+		if (err)
+			return err;
+
+		pack = got_repo_get_cached_pack(repo, path_packfile);
 		if (pack == NULL) {
-			err = got_repo_cache_pack(&pack, repo,
-			    obj->path_packfile, NULL);
+			err = got_repo_cache_pack(&pack, repo, path_packfile,
+			    packidx);
 			if (err)
 				return err;
 		}
-		err = read_packed_tree_privsep(tree, obj, pack);
-	} else {
+		err = read_packed_tree_privsep(tree, pack,
+		    packidx, idx, id);
+	} else if (err->code == GOT_ERR_NO_OBJ) {
 		int fd;
-		err = open_loose_object(&fd, got_object_get_id(obj), repo);
+
+		err = open_loose_object(&fd, id, repo);
 		if (err)
 			return err;
-		err = got_object_read_tree_privsep(tree, obj, fd, repo);
+		err = got_object_read_tree_privsep(tree, fd, repo);
 		close(fd);
 	}
 
 	if (err == NULL) {
 		(*tree)->refcnt++;
-		err = got_repo_cache_tree(repo, &obj->id, *tree);
+		err = got_repo_cache_tree(repo, id, *tree);
 	}
 
 	return err;
@@ -604,34 +630,20 @@ const struct got_error *
 got_object_open_as_tree(struct got_tree_object **tree,
     struct got_repository *repo, struct got_object_id *id)
 {
-	const struct got_error *err;
-	struct got_object *obj;
-
 	*tree = got_repo_get_cached_tree(repo, id);
 	if (*tree != NULL) {
 		(*tree)->refcnt++;
 		return NULL;
 	}
 
-	err = got_object_open(&obj, repo, id);
-	if (err)
-		return err;
-	if (obj->type != GOT_OBJ_TYPE_TREE) {
-		err = got_error(GOT_ERR_OBJ_TYPE);
-		goto done;
-	}
-
-	err = open_tree(tree, repo, obj, 0);
-done:
-	got_object_close(obj);
-	return err;
+	return open_tree(tree, repo, id, 0);
 }
 
 const struct got_error *
 got_object_tree_open(struct got_tree_object **tree,
     struct got_repository *repo, struct got_object *obj)
 {
-	return open_tree(tree, repo, obj, 1);
+	return open_tree(tree, repo, got_object_get_id(obj), 1);
 }
 
 const struct got_tree_entries *
@@ -1290,14 +1302,14 @@ got_object_read_commit_privsep(struct got_commit_object **commit,
 
 static const struct got_error *
 request_tree(struct got_tree_object **tree, struct got_repository *repo,
-    struct got_object *obj, int fd)
+    int fd)
 {
 	const struct got_error *err = NULL;
 	struct imsgbuf *ibuf;
 
 	ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TREE].ibuf;
 
-	err = got_privsep_send_obj_req(ibuf, fd, obj);
+	err = got_privsep_send_tree_req(ibuf, fd, NULL, -1);
 	if (err)
 		return err;
 
@@ -1306,14 +1318,14 @@ request_tree(struct got_tree_object **tree, struct got_repository *repo,
 
 const struct got_error *
 got_object_read_tree_privsep(struct got_tree_object **tree,
-    struct got_object *obj, int obj_fd, struct got_repository *repo)
+    int obj_fd, struct got_repository *repo)
 {
 	int imsg_fds[2];
 	pid_t pid;
 	struct imsgbuf *ibuf;
 
 	if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TREE].imsg_fd != -1)
-		return request_tree(tree, repo, obj, obj_fd);
+		return request_tree(tree, repo, obj_fd);
 
 	ibuf = calloc(1, sizeof(*ibuf));
 	if (ibuf == NULL)
@@ -1340,7 +1352,7 @@ got_object_read_tree_privsep(struct got_tree_object **tree,
 	repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TREE].ibuf = ibuf;
 
 
-	return request_tree(tree, repo, obj, obj_fd);
+	return request_tree(tree, repo, obj_fd);
 }
 
 static const struct got_error *
diff --git a/lib/privsep.c b/lib/privsep.c
index 2a15c7e..17fe8da 100644
--- a/lib/privsep.c
+++ b/lib/privsep.c
@@ -290,6 +290,30 @@ got_privsep_send_commit_req(struct imsgbuf *ibuf, int fd,
 }
 
 const struct got_error *
+got_privsep_send_tree_req(struct imsgbuf *ibuf, int fd,
+    struct got_object_id *id, int pack_idx)
+{
+	struct got_imsg_packed_object iobj, *iobjp;
+	size_t len;
+
+	if (id) { /* tree is packed */
+		iobj.idx = pack_idx;
+		memcpy(iobj.id, id->sha1, sizeof(iobj.id));
+		iobjp = &iobj;
+		len = sizeof(iobj);
+	} else {
+		iobjp = NULL;
+		len = 0;
+	}
+
+	if (imsg_compose(ibuf, GOT_IMSG_TREE_REQUEST, 0, 0, fd, iobjp, len)
+	    == -1)
+		return got_error_from_errno();
+
+	return flush_imsg(ibuf);
+}
+
+const struct got_error *
 got_privsep_send_blob_req(struct imsgbuf *ibuf, int infd)
 {
 	if (imsg_compose(ibuf, GOT_IMSG_BLOB_REQUEST, 0, 0, infd, NULL, 0)
diff --git a/libexec/got-read-pack/got-read-pack.c b/libexec/got-read-pack/got-read-pack.c
index 8d243d0..c6dc175 100644
--- a/libexec/got-read-pack/got-read-pack.c
+++ b/libexec/got-read-pack/got-read-pack.c
@@ -168,13 +168,21 @@ tree_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
     struct got_packidx *packidx, struct got_object_cache *objcache)
 {
 	const struct got_error *err = NULL;
+	struct got_imsg_packed_object iobj;
 	struct got_object *obj = NULL;
 	struct got_tree_object *tree = NULL;
 	uint8_t *buf;
 	size_t len;
+	struct got_object_id id;
+	size_t datalen;
 
-	err = get_object(&obj, imsg, ibuf, pack, packidx, objcache,
-	    GOT_OBJ_TYPE_TREE);
+	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
+	if (datalen != sizeof(iobj))
+		return got_error(GOT_ERR_PRIVSEP_LEN);
+	memcpy(&iobj, imsg->data, sizeof(iobj));
+	memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH);
+
+	err = got_packfile_open_object(&obj, pack, packidx, iobj.idx, &id);
 	if (err)
 		return err;
 
diff --git a/libexec/got-read-tree/got-read-tree.c b/libexec/got-read-tree/got-read-tree.c
index 9030954..cfdb2fb 100644
--- a/libexec/got-read-tree/got-read-tree.c
+++ b/libexec/got-read-tree/got-read-tree.c
@@ -47,16 +47,18 @@ catch_sigint(int signo)
 	sigint_received = 1;
 }
 static const struct got_error *
-read_tree_object(struct got_tree_object **tree, struct got_object *obj, FILE *f)
+read_tree_object(struct got_tree_object **tree, FILE *f)
 {
 	const struct got_error *err = NULL;
+	struct got_object *obj;
 	size_t len;
 	uint8_t *p;
 
-	if (obj->flags & GOT_OBJ_FLAG_PACKED)
-		err = got_read_file_to_mem(&p, &len, f);
-	else
-		err = got_inflate_to_mem(&p, &len, f);
+	err = got_inflate_to_mem(&p, &len, f);
+	if (err)
+		return err;
+
+	err = got_object_parse_header(&obj, p, len);
 	if (err)
 		return err;
 
@@ -68,8 +70,9 @@ read_tree_object(struct got_tree_object **tree, struct got_object *obj, FILE *f)
 	/* Skip object header. */
 	len -= obj->hdrlen;
 	err = got_object_parse_tree(tree, p + obj->hdrlen, len);
-	free(p);
 done:
+	free(p);
+	got_object_close(obj);
 	return err;
 }
 
@@ -77,9 +80,7 @@ int
 main(int argc, char *argv[])
 {
 	const struct got_error *err = NULL;
-	struct got_tree_object *tree = NULL;
 	struct imsgbuf ibuf;
-	size_t datalen;
 
 	signal(SIGINT, catch_sigint);
 
@@ -96,9 +97,8 @@ main(int argc, char *argv[])
 
 	while (1) {
 		struct imsg imsg;
-		struct got_imsg_object iobj;
 		FILE *f = NULL;
-		struct got_object *obj = NULL;
+		struct got_tree_object *tree = NULL;
 
 		if (sigint_received) {
 			err = got_error(GOT_ERR_CANCELLED);
@@ -120,32 +120,11 @@ main(int argc, char *argv[])
 			goto done;
 		}
 
-		datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
-		if (datalen != sizeof(iobj)) {
-			err = got_error(GOT_ERR_PRIVSEP_LEN);
-			goto done;
-		}
-
-		memcpy(&iobj, imsg.data, sizeof(iobj));
-		if (iobj.type != GOT_OBJ_TYPE_TREE) {
-			err = got_error(GOT_ERR_OBJ_TYPE);
-			goto done;
-		}
-
 		if (imsg.fd == -1) {
 			err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 			goto done;
 		}
 
-		obj = calloc(1, sizeof(*obj));
-		if (obj == NULL) {
-			err = got_error_from_errno();
-			goto done;
-		}
-		obj->type = iobj.type;
-		obj->hdrlen = iobj.hdrlen;
-		obj->size = iobj.size;
-
 		/* Always assume file offset zero. */
 		f = fdopen(imsg.fd, "rb");
 		if (f == NULL) {
@@ -153,7 +132,7 @@ main(int argc, char *argv[])
 			goto done;
 		}
 
-		err = read_tree_object(&tree, obj, f);
+		err = read_tree_object(&tree, f);
 		if (err)
 			goto done;
 
@@ -164,8 +143,6 @@ done:
 		else if (imsg.fd != -1)
 			close(imsg.fd);
 		imsg_free(&imsg);
-		if (obj)
-			got_object_close(obj);
 		if (err)
 			break;
 	}