summaryrefslogtreecommitdiff
path: root/reftable/tree.c
diff options
context:
space:
mode:
authorLibravatar Han-Wen Nienhuys <hanwen@google.com>2021-10-07 20:25:05 +0000
committerLibravatar Junio C Hamano <gitster@pobox.com>2021-10-08 10:45:48 -0700
commit35425d1034f2a98d438da21c68334056af7033ca (patch)
tree28aaf52578a4c41af1351a30f95a96ffe45ab02e /reftable/tree.c
parentreftable: reading/writing blocks (diff)
downloadtgif-35425d1034f2a98d438da21c68334056af7033ca.tar.xz
reftable: a generic binary tree implementation
The reftable format includes support for an (OID => ref) map. This map can speed up visibility and reachability checks. In particular, various operations along the fetch/push path within Gerrit have ben sped up by using this structure. The map is constructed with help of a binary tree. Object IDs are hashes, so they are uniformly distributed. Hence, the tree does not attempt forced rebalancing. Signed-off-by: Han-Wen Nienhuys <hanwen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'reftable/tree.c')
-rw-r--r--reftable/tree.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/reftable/tree.c b/reftable/tree.c
new file mode 100644
index 0000000000..82db7995dd
--- /dev/null
+++ b/reftable/tree.c
@@ -0,0 +1,63 @@
+/*
+Copyright 2020 Google LLC
+
+Use of this source code is governed by a BSD-style
+license that can be found in the LICENSE file or at
+https://developers.google.com/open-source/licenses/bsd
+*/
+
+#include "tree.h"
+
+#include "basics.h"
+#include "system.h"
+
+struct tree_node *tree_search(void *key, struct tree_node **rootp,
+ int (*compare)(const void *, const void *),
+ int insert)
+{
+ int res;
+ if (*rootp == NULL) {
+ if (!insert) {
+ return NULL;
+ } else {
+ struct tree_node *n =
+ reftable_calloc(sizeof(struct tree_node));
+ n->key = key;
+ *rootp = n;
+ return *rootp;
+ }
+ }
+
+ res = compare(key, (*rootp)->key);
+ if (res < 0)
+ return tree_search(key, &(*rootp)->left, compare, insert);
+ else if (res > 0)
+ return tree_search(key, &(*rootp)->right, compare, insert);
+ return *rootp;
+}
+
+void infix_walk(struct tree_node *t, void (*action)(void *arg, void *key),
+ void *arg)
+{
+ if (t->left) {
+ infix_walk(t->left, action, arg);
+ }
+ action(arg, t->key);
+ if (t->right) {
+ infix_walk(t->right, action, arg);
+ }
+}
+
+void tree_free(struct tree_node *t)
+{
+ if (t == NULL) {
+ return;
+ }
+ if (t->left) {
+ tree_free(t->left);
+ }
+ if (t->right) {
+ tree_free(t->right);
+ }
+ reftable_free(t);
+}