Skip to content

Commit 831b366

Browse files
pks-tgitster
authored andcommitted
refs/reftable: allow configuring block size
Add a new option `reftable.blockSize` that allows the user to control the block size used by the reftable library. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent fcf3418 commit 831b366

File tree

4 files changed

+118
-1
lines changed

4 files changed

+118
-1
lines changed

Documentation/config.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,8 @@ include::config/rebase.txt[]
498498

499499
include::config/receive.txt[]
500500

501+
include::config/reftable.txt[]
502+
501503
include::config/remote.txt[]
502504

503505
include::config/remotes.txt[]

Documentation/config/reftable.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
reftable.blockSize::
2+
The size in bytes used by the reftable backend when writing blocks.
3+
The block size is determined by the writer, and does not have to be a
4+
power of 2. The block size must be larger than the longest reference
5+
name or log entry used in the repository, as references cannot span
6+
blocks.
7+
+
8+
Powers of two that are friendly to the virtual memory system or
9+
filesystem (such as 4kB or 8kB) are recommended. Larger sizes (64kB) can
10+
yield better compression, with a possible increased cost incurred by
11+
readers during access.
12+
+
13+
The largest block size is `16777215` bytes (15.99 MiB). The default value is
14+
`4096` bytes (4kB). A value of `0` will use the default value.

refs/reftable-backend.c

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "../git-compat-util.h"
22
#include "../abspath.h"
33
#include "../chdir-notify.h"
4+
#include "../config.h"
45
#include "../environment.h"
56
#include "../gettext.h"
67
#include "../hash.h"
@@ -228,6 +229,22 @@ static int read_ref_without_reload(struct reftable_stack *stack,
228229
return ret;
229230
}
230231

232+
static int reftable_be_config(const char *var, const char *value,
233+
const struct config_context *ctx,
234+
void *_opts)
235+
{
236+
struct reftable_write_options *opts = _opts;
237+
238+
if (!strcmp(var, "reftable.blocksize")) {
239+
unsigned long block_size = git_config_ulong(var, value, ctx->kvi);
240+
if (block_size > 16777215)
241+
die("reftable block size cannot exceed 16MB");
242+
opts->block_size = block_size;
243+
}
244+
245+
return 0;
246+
}
247+
231248
static struct ref_store *reftable_be_init(struct repository *repo,
232249
const char *gitdir,
233250
unsigned int store_flags)
@@ -243,12 +260,24 @@ static struct ref_store *reftable_be_init(struct repository *repo,
243260
base_ref_store_init(&refs->base, repo, gitdir, &refs_be_reftable);
244261
strmap_init(&refs->worktree_stacks);
245262
refs->store_flags = store_flags;
246-
refs->write_options.block_size = 4096;
263+
247264
refs->write_options.hash_id = repo->hash_algo->format_id;
248265
refs->write_options.default_permissions = calc_shared_perm(0666 & ~mask);
249266
refs->write_options.disable_auto_compact =
250267
!git_env_bool("GIT_TEST_REFTABLE_AUTOCOMPACTION", 1);
251268

269+
git_config(reftable_be_config, &refs->write_options);
270+
271+
/*
272+
* It is somewhat unfortunate that we have to mirror the default block
273+
* size of the reftable library here. But given that the write options
274+
* wouldn't be updated by the library here, and given that we require
275+
* the proper block size to trim reflog message so that they fit, we
276+
* must set up a proper value here.
277+
*/
278+
if (!refs->write_options.block_size)
279+
refs->write_options.block_size = 4096;
280+
252281
/*
253282
* Set up the main reftable stack that is hosted in GIT_COMMON_DIR.
254283
* This stack contains both the shared and the main worktree refs.

t/t0613-reftable-write-options.sh

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,76 @@ test_expect_success 'many refs results in multiple blocks' '
9999
)
100100
'
101101

102+
test_expect_success 'tiny block size leads to error' '
103+
test_when_finished "rm -rf repo" &&
104+
git init repo &&
105+
(
106+
cd repo &&
107+
test_commit initial &&
108+
cat >expect <<-EOF &&
109+
error: unable to compact stack: entry too large
110+
EOF
111+
test_must_fail git -c reftable.blockSize=50 pack-refs 2>err &&
112+
test_cmp expect err
113+
)
114+
'
115+
116+
test_expect_success 'small block size leads to multiple ref blocks' '
117+
test_config_global core.logAllRefUpdates false &&
118+
test_when_finished "rm -rf repo" &&
119+
git init repo &&
120+
(
121+
cd repo &&
122+
test_commit A &&
123+
test_commit B &&
124+
git -c reftable.blockSize=100 pack-refs &&
125+
126+
cat >expect <<-EOF &&
127+
header:
128+
block_size: 100
129+
ref:
130+
- length: 53
131+
restarts: 1
132+
- length: 74
133+
restarts: 1
134+
- length: 38
135+
restarts: 1
136+
EOF
137+
test-tool dump-reftable -b .git/reftable/*.ref >actual &&
138+
test_cmp expect actual
139+
)
140+
'
141+
142+
test_expect_success 'small block size fails with large reflog message' '
143+
test_when_finished "rm -rf repo" &&
144+
git init repo &&
145+
(
146+
cd repo &&
147+
test_commit A &&
148+
perl -e "print \"a\" x 500" >logmsg &&
149+
cat >expect <<-EOF &&
150+
fatal: update_ref failed for ref ${SQ}refs/heads/logme${SQ}: reftable: transaction failure: entry too large
151+
EOF
152+
test_must_fail git -c reftable.blockSize=100 \
153+
update-ref -m "$(cat logmsg)" refs/heads/logme HEAD 2>err &&
154+
test_cmp expect err
155+
)
156+
'
157+
158+
test_expect_success 'block size exceeding maximum supported size' '
159+
test_config_global core.logAllRefUpdates false &&
160+
test_when_finished "rm -rf repo" &&
161+
git init repo &&
162+
(
163+
cd repo &&
164+
test_commit A &&
165+
test_commit B &&
166+
cat >expect <<-EOF &&
167+
fatal: reftable block size cannot exceed 16MB
168+
EOF
169+
test_must_fail git -c reftable.blockSize=16777216 pack-refs 2>err &&
170+
test_cmp expect err
171+
)
172+
'
173+
102174
test_done

0 commit comments

Comments
 (0)