Skip to content

Commit 268ea85

Browse files
pks-tgitster
authored andcommitted
refs/files: batch refname availability checks for initial transactions
The "files" backend explicitly carves out special logic for its initial transaction so that it can avoid writing out every single reference as a loose reference. While the assumption is that there shouldn't be any preexisting references, we still have to verify that none of the newly written references will conflict with any other new reference in the same transaction. Refactor the initial transaction to use batched refname availability checks. This does not yet have an effect on performance as we still call `refs_verify_refname_available()` in a loop. But this will change in subsequent commits and then impact performance when cloning a repository with many references or when migrating references to the "files" format. This will improve performance when cloning a repository with many references or when migrating references from any format to the "files" format once the availability checks have learned to optimize checks for many references in a subsequent commit. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6c90726 commit 268ea85

File tree

1 file changed

+16
-7
lines changed

1 file changed

+16
-7
lines changed

refs/files-backend.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3056,6 +3056,7 @@ static int files_transaction_finish_initial(struct files_ref_store *refs,
30563056
size_t i;
30573057
int ret = 0;
30583058
struct string_list affected_refnames = STRING_LIST_INIT_NODUP;
3059+
struct string_list refnames_to_check = STRING_LIST_INIT_NODUP;
30593060
struct ref_transaction *packed_transaction = NULL;
30603061
struct ref_transaction *loose_transaction = NULL;
30613062

@@ -3105,11 +3106,7 @@ static int files_transaction_finish_initial(struct files_ref_store *refs,
31053106
!is_null_oid(&update->old_oid))
31063107
BUG("initial ref transaction with old_sha1 set");
31073108

3108-
if (refs_verify_refname_available(&refs->base, update->refname,
3109-
&affected_refnames, NULL, 1, err)) {
3110-
ret = TRANSACTION_NAME_CONFLICT;
3111-
goto cleanup;
3112-
}
3109+
string_list_append(&refnames_to_check, update->refname);
31133110

31143111
/*
31153112
* packed-refs don't support symbolic refs, root refs and reflogs,
@@ -3145,8 +3142,19 @@ static int files_transaction_finish_initial(struct files_ref_store *refs,
31453142
}
31463143
}
31473144

3148-
if (packed_refs_lock(refs->packed_ref_store, 0, err) ||
3149-
ref_transaction_commit(packed_transaction, err)) {
3145+
if (packed_refs_lock(refs->packed_ref_store, 0, err)) {
3146+
ret = TRANSACTION_GENERIC_ERROR;
3147+
goto cleanup;
3148+
}
3149+
3150+
if (refs_verify_refnames_available(&refs->base, &refnames_to_check,
3151+
&affected_refnames, NULL, 1, err)) {
3152+
packed_refs_unlock(refs->packed_ref_store);
3153+
ret = TRANSACTION_NAME_CONFLICT;
3154+
goto cleanup;
3155+
}
3156+
3157+
if (ref_transaction_commit(packed_transaction, err)) {
31503158
ret = TRANSACTION_GENERIC_ERROR;
31513159
goto cleanup;
31523160
}
@@ -3167,6 +3175,7 @@ static int files_transaction_finish_initial(struct files_ref_store *refs,
31673175
ref_transaction_free(packed_transaction);
31683176
transaction->state = REF_TRANSACTION_CLOSED;
31693177
string_list_clear(&affected_refnames, 0);
3178+
string_list_clear(&refnames_to_check, 0);
31703179
return ret;
31713180
}
31723181

0 commit comments

Comments
 (0)