aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--reftable/reftable-stack.h11
-rw-r--r--reftable/stack.c42
-rw-r--r--t/unit-tests/u-reftable-stack.c12
3 files changed, 58 insertions, 7 deletions
diff --git a/reftable/reftable-stack.h b/reftable/reftable-stack.h
index d70fcb705d..c2415cbc6e 100644
--- a/reftable/reftable-stack.h
+++ b/reftable/reftable-stack.h
@@ -123,6 +123,17 @@ struct reftable_log_expiry_config {
int reftable_stack_compact_all(struct reftable_stack *st,
struct reftable_log_expiry_config *config);
+/*
+ * Check if compaction is required.
+ *
+ * When `use_heuristics` is false, check if all tables can be compacted to a
+ * single table. If true, use heuristics to determine if the tables need to be
+ * compacted to maintain geometric progression.
+ */
+int reftable_stack_compaction_required(struct reftable_stack *st,
+ bool use_heuristics,
+ bool *required);
+
/* heuristically compact unbalanced table stack. */
int reftable_stack_auto_compact(struct reftable_stack *st);
diff --git a/reftable/stack.c b/reftable/stack.c
index 49387f9344..826500abed 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -1647,19 +1647,51 @@ static int stack_segments_for_compaction(struct reftable_stack *st,
return 0;
}
-int reftable_stack_auto_compact(struct reftable_stack *st)
+static int update_segment_if_compaction_required(struct reftable_stack *st,
+ struct segment *seg,
+ bool use_heuristics,
+ bool *required)
{
- struct segment seg;
int err;
- if (st->merged->tables_len < 2)
+ if (st->merged->tables_len < 2) {
+ *required = false;
+ return 0;
+ }
+
+ if (!use_heuristics) {
+ *required = true;
return 0;
+ }
+
+ err = stack_segments_for_compaction(st, seg);
+ if (err)
+ return err;
+
+ *required = segment_size(seg) > 0;
+ return 0;
+}
+
+int reftable_stack_compaction_required(struct reftable_stack *st,
+ bool use_heuristics,
+ bool *required)
+{
+ struct segment seg;
+ return update_segment_if_compaction_required(st, &seg, use_heuristics,
+ required);
+}
+
+int reftable_stack_auto_compact(struct reftable_stack *st)
+{
+ struct segment seg;
+ bool required;
+ int err;
- err = stack_segments_for_compaction(st, &seg);
+ err = update_segment_if_compaction_required(st, &seg, true, &required);
if (err)
return err;
- if (segment_size(&seg) > 0)
+ if (required)
return stack_compact_range(st, seg.start, seg.end - 1,
NULL, STACK_COMPACT_RANGE_BEST_EFFORT);
diff --git a/t/unit-tests/u-reftable-stack.c b/t/unit-tests/u-reftable-stack.c
index a8b91812e8..b8110cdeee 100644
--- a/t/unit-tests/u-reftable-stack.c
+++ b/t/unit-tests/u-reftable-stack.c
@@ -1067,6 +1067,7 @@ void test_reftable_stack__add_performs_auto_compaction(void)
.value_type = REFTABLE_REF_SYMREF,
.value.symref = (char *) "master",
};
+ bool required = false;
char buf[128];
/*
@@ -1087,10 +1088,17 @@ void test_reftable_stack__add_performs_auto_compaction(void)
* auto compaction is disabled. When enabled, we should merge
* all tables in the stack.
*/
- if (i != n)
+ cl_assert_equal_i(reftable_stack_compaction_required(st, true, &required), 0);
+ if (i != n) {
cl_assert_equal_i(st->merged->tables_len, i + 1);
- else
+ if (i < 1)
+ cl_assert_equal_b(required, false);
+ else
+ cl_assert_equal_b(required, true);
+ } else {
cl_assert_equal_i(st->merged->tables_len, 1);
+ cl_assert_equal_b(required, false);
+ }
}
reftable_stack_destroy(st);