git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v4 09/19] reftable: a generic binary tree implementation

From
Han-Wen Nienhuys via GitGitGadget <gitgitgadget@gmail.com>
Date
Oct 7, 2021, 20:25 UTC
Message-ID
<96e490ac32ccde5c9a4eae5f344ecd7f7c941923.1633638316.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.1081.v4.git.git.1633638315.gitgitgadget@gmail.com>
From: Han-Wen Nienhuys <hanwen@google.com>

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>
---
 Makefile                 |  4 ++-
 reftable/tree.c          | 63 ++++++++++++++++++++++++++++++++++++++++
 reftable/tree.h          | 34 ++++++++++++++++++++++
 reftable/tree_test.c     | 61 ++++++++++++++++++++++++++++++++++++++
 t/helper/test-reftable.c |  1 +
 5 files changed, 162 insertions(+), 1 deletion(-)
 create mode 100644 reftable/tree.c
 create mode 100644 reftable/tree.h
 create mode 100644 reftable/tree_test.c
diff --git a/Makefile b/Makefile
index 153db9dff11..d8d4bb0143b 100644
--- a/Makefile
+++ b/Makefile
@@ -2442,11 +2442,13 @@ REFTABLE_OBJS += reftable/block.o
 REFTABLE_OBJS += reftable/blocksource.o
 REFTABLE_OBJS += reftable/publicbasics.o
 REFTABLE_OBJS += reftable/record.o
+REFTABLE_OBJS += reftable/tree.o
 
+REFTABLE_TEST_OBJS += reftable/basics_test.o
 REFTABLE_TEST_OBJS += reftable/block_test.o
 REFTABLE_TEST_OBJS += reftable/record_test.o
 REFTABLE_TEST_OBJS += reftable/test_framework.o
-REFTABLE_TEST_OBJS += reftable/basics_test.o
+REFTABLE_TEST_OBJS += reftable/tree_test.o
 
 TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS)) $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS))
 
diff --git a/reftable/tree.c b/reftable/tree.c
new file mode 100644
index 00000000000..82db7995dd6
--- /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);
+}
diff --git a/reftable/tree.h b/reftable/tree.h
new file mode 100644
index 00000000000..fbdd002e23a
--- /dev/null
+++ b/reftable/tree.h
@@ -0,0 +1,34 @@
+/*
+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
+*/
+
+#ifndef TREE_H
+#define TREE_H
+
+/* tree_node is a generic binary search tree. */
+struct tree_node {
+	void *key;
+	struct tree_node *left, *right;
+};
+
+/* looks for `key` in `rootp` using `compare` as comparison function. If insert
+ * is set, insert the key if it's not found. Else, return NULL.
+ */
+struct tree_node *tree_search(void *key, struct tree_node **rootp,
+			      int (*compare)(const void *, const void *),
+			      int insert);
+
+/* performs an infix walk of the tree. */
+void infix_walk(struct tree_node *t, void (*action)(void *arg, void *key),
+		void *arg);
+
+/*
+ * deallocates the tree nodes recursively. Keys should be deallocated separately
+ * by walking over the tree. */
+void tree_free(struct tree_node *t);
+
+#endif
diff --git a/reftable/tree_test.c b/reftable/tree_test.c
new file mode 100644
index 00000000000..cbff1255886
--- /dev/null
+++ b/reftable/tree_test.c
@@ -0,0 +1,61 @@
+/*
+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 "record.h"
+#include "test_framework.h"
+#include "reftable-tests.h"
+
+static int test_compare(const void *a, const void *b)
+{
+	return (char *)a - (char *)b;
+}
+
+struct curry {
+	void *last;
+};
+
+static void check_increasing(void *arg, void *key)
+{
+	struct curry *c = arg;
+	if (c->last) {
+		EXPECT(test_compare(c->last, key) < 0);
+	}
+	c->last = key;
+}
+
+static void test_tree(void)
+{
+	struct tree_node *root = NULL;
+
+	void *values[11] = { NULL };
+	struct tree_node *nodes[11] = { NULL };
+	int i = 1;
+	struct curry c = { NULL };
+	do {
+		nodes[i] = tree_search(values + i, &root, &test_compare, 1);
+		i = (i * 7) % 11;
+	} while (i != 1);
+
+	for (i = 1; i < ARRAY_SIZE(nodes); i++) {
+		EXPECT(values + i == nodes[i]->key);
+		EXPECT(nodes[i] ==
+		       tree_search(values + i, &root, &test_compare, 0));
+	}
+
+	infix_walk(root, check_increasing, &c);
+	tree_free(root);
+}
+
+int tree_test_main(int argc, const char *argv[])
+{
+	RUN_TEST(test_tree);
+	return 0;
+}
diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c
index c9deeaf08c7..050551fa698 100644
--- a/t/helper/test-reftable.c
+++ b/t/helper/test-reftable.c
@@ -6,5 +6,6 @@ int cmd__reftable(int argc, const char **argv)
 	basics_test_main(argc, argv);
 	block_test_main(argc, argv);
 	record_test_main(argc, argv);
+	tree_test_main(argc, argv);
 	return 0;
 }
-- 
gitgitgadget
Previous: Han-Wen Nienhuys via GitGitGadgetNext: Han-Wen Nienhuys via GitGitGadget
Message 94 of 111 in “Adds reftable library code from https://github.com/hanwen/reftable.”
  1. 00/19 Adds reftable library code from https://github.com/hanwen/reftable.Han-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  2. 01/19 hash.h: provide constants for the hash IDsHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  3. 03/19 reftable: add error related functionalityHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  4. 02/19 reftable: RFC: add LICENSEHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  5. 04/19 reftable: utility functionsHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  6. 05/19 reftable: add blocksource, an abstraction for random access readsHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  7. 07/19 Provide zlib's uncompress2 from compat/zlib-compat.cHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  8. fixup! Provide zlib's uncompress2 from compat/zlib-compat.cCarlo Marcelo Arenas Belón, Sep 2, 2021
  9. 06/19 reftable: (de)serialization for the polymorphic record type.Han-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  10. 09/19 reftable: a generic binary tree implementationHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  11. 08/19 reftable: reading/writing blocksHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  12. 11/19 reftable: generic interface to tablesHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  13. 14/19 reftable: add a heap-based priority queue for reftable recordsHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  14. 10/19 reftable: write reftable filesHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  15. 13/19 reftable: reftable file level testsHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  16. 12/19 reftable: read reftable filesHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  17. 15/19 reftable: add merged table viewHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  18. 16/19 reftable: implement refname validationHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  19. 18/19 reftable: add dump utilityHan-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  20. 19/19 Add "test-tool dump-reftable" command.Han-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  21. 17/19 reftable: implement stack, a mutable database of reftable files.Han-Wen Nienhuys via GitGitGadget, Aug 30, 2021
  22. Han-Wen NienhuysAug 30, 2021
  23. 0/4 fixup for hn/reftableCarlo Marcelo Arenas Belón, Sep 8, 2021
  24. 1/4 fixup! reftable: reading/writing blocksCarlo Marcelo Arenas Belón, Sep 8, 2021
  25. 2/4 fixup! reftable: utility functionsCarlo Marcelo Arenas Belón, Sep 8, 2021
  26. 3/4 fixup! Provide zlib's uncompress2 from compat/zlib-compat.cCarlo Marcelo Arenas Belón, Sep 8, 2021
  27. 4/4 fixup! reftable: utility functionsCarlo Marcelo Arenas Belón, Sep 8, 2021
  28. Junio C HamanoSep 8, 2021
  29. 00/19 Adds reftable library code from https://github.com/hanwen/reftable.Han-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  30. 01/19 hash.h: provide constants for the hash IDsHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  31. 02/19 reftable: RFC: add LICENSEHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  32. 03/19 reftable: add error related functionalityHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  33. 04/19 reftable: utility functionsHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  34. 06/19 reftable: (de)serialization for the polymorphic record type.Han-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  35. 07/19 Provide zlib's uncompress2 from compat/zlib-compat.cHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  36. Carlo ArenasSep 15, 2021
  37. 05/19 reftable: add blocksource, an abstraction for random access readsHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  38. 08/19 reftable: reading/writing blocksHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  39. Ævar Arnfjörð BjarmasonSep 24, 2021
  40. 09/19 reftable: a generic binary tree implementationHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  41. 10/19 reftable: write reftable filesHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  42. 11/19 reftable: generic interface to tablesHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  43. 12/19 reftable: read reftable filesHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  44. 14/19 reftable: add a heap-based priority queue for reftable recordsHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  45. 13/19 reftable: reftable file level testsHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  46. 16/19 reftable: implement refname validationHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  47. 15/19 reftable: add merged table viewHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  48. 17/19 reftable: implement stack, a mutable database of reftable files.Han-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  49. 18/19 reftable: add dump utilityHan-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  50. 19/19 Add "test-tool dump-reftable" command.Han-Wen Nienhuys via GitGitGadget, Sep 9, 2021
  51. Junio C HamanoSep 9, 2021
  52. Junio C HamanoSep 9, 2021
  53. Han-Wen NienhuysSep 13, 2021
  54. Junio C HamanoSep 13, 2021
  55. Carlo ArenasSep 13, 2021
  56. Junio C HamanoSep 13, 2021
  57. 00/19 Adds reftable library code from https://github.com/hanwen/reftable.Han-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  58. 02/19 reftable: RFC: add LICENSEHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  59. 03/19 reftable: add error related functionalityHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  60. 01/19 hash.h: provide constants for the hash IDsHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  61. 04/19 reftable: utility functionsHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  62. 05/19 reftable: add blocksource, an abstraction for random access readsHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  63. 06/19 reftable: (de)serialization for the polymorphic record type.Han-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  64. 07/19 Provide zlib's uncompress2 from compat/zlib-compat.cHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  65. 09/19 reftable: a generic binary tree implementationHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  66. 08/19 reftable: reading/writing blocksHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  67. squash! reftable: reading/writing blocksCarlo Marcelo Arenas Belón, Sep 30, 2021
  68. Han-Wen NienhuysOct 7, 2021
  69. 10/19 reftable: write reftable filesHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  70. 11/19 reftable: generic interface to tablesHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  71. 12/19 reftable: read reftable filesHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  72. 15/19 reftable: add merged table viewHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  73. 13/19 reftable: reftable file level testsHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  74. 14/19 reftable: add a heap-based priority queue for reftable recordsHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  75. 16/19 reftable: implement refname validationHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  76. 17/19 reftable: implement stack, a mutable database of reftable files.Han-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  77. 18/19 reftable: add dump utilityHan-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  78. 19/19 Add "test-tool dump-reftable" command.Han-Wen Nienhuys via GitGitGadget, Sep 28, 2021
  79. Junio C HamanoSep 28, 2021
  80. Ævar Arnfjörð BjarmasonOct 2, 2021
  81. hn/reftable "fixes"Carlo Marcelo Arenas Belón, Sep 30, 2021
  82. 1/4 fixup! reftable: add a heap-based priority queue for reftable recordsCarlo Marcelo Arenas Belón, Sep 30, 2021
  83. 2/4 fixup! reftable: implement stack, a mutable database of reftable files.Carlo Marcelo Arenas Belón, Sep 30, 2021
  84. C++(C99)-style comments in git.gitÆvar Arnfjörð Bjarmason, Oct 1, 2021
  85. 3/4 config.mak.uname: last release and snapshots of Minix still use zlib 1.2.3Carlo Marcelo Arenas Belón, Sep 30, 2021
  86. 4/4 reftable: avoid non portable compile time pointer to functionCarlo Marcelo Arenas Belón, Sep 30, 2021
  87. Junio C HamanoSep 30, 2021
  88. 00/19 Adds reftable library code from https://github.com/hanwen/reftable.Han-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  89. 01/19 hash.h: provide constants for the hash IDsHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  90. 02/19 reftable: add LICENSEHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  91. 03/19 reftable: add error related functionalityHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  92. 04/19 reftable: utility functionsHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  93. 05/19 reftable: add blocksource, an abstraction for random access readsHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  94. 09/19 reftable: a generic binary tree implementationHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  95. 10/19 reftable: write reftable filesHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  96. 11/19 reftable: generic interface to tablesHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  97. 08/19 reftable: reading/writing blocksHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  98. 12/19 reftable: read reftable filesHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  99. 06/19 reftable: (de)serialization for the polymorphic record type.Han-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  100. 07/19 Provide zlib's uncompress2 from compat/zlib-compat.cHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  101. 13/19 reftable: reftable file level testsHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  102. 14/19 reftable: add a heap-based priority queue for reftable recordsHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  103. 15/19 reftable: add merged table viewHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  104. reftable tests: use C syntax compatible with old xlcÆvar Arnfjörð Bjarmason, Jan 13, 2022
  105. Han-Wen NienhuysJan 13, 2022
  106. Ævar Arnfjörð BjarmasonJan 13, 2022
  107. Junio C HamanoJan 13, 2022
  108. 16/19 reftable: implement refname validationHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  109. 18/19 reftable: add dump utilityHan-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  110. 17/19 reftable: implement stack, a mutable database of reftable files.Han-Wen Nienhuys via GitGitGadget, Oct 7, 2021
  111. 19/19 Add "test-tool dump-reftable" command.Han-Wen Nienhuys via GitGitGadget, Oct 7, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.