Как Git или libgit2 справляются с условиями гонки? - PullRequest
0 голосов
/ 10 июля 2020

Я использую libgit2 и спрашиваю себя, что произойдет, если 2 процесса одновременно выполнят операцию записи в одном и том же репо?

Приведенный ниже пример является простым примером фиксации в репо. Он состоит из множества команд.

Что делать, если процесс A выполняет первые 3 команды и зависает на несколько секунд, а другой процесс выполняет тот же порядок команд, но выполняется все, затем A продолжается. Я знаю, что это редко, поскольку Git действия в основном являются взаимодействиями с пользователем, и пользователь редко использует 2 такие команды одновременно, но Я хотел бы понять теоретические последствия таких состояний гонки в Git чтобы убедиться, что я ничего не сломаю.

Большое спасибо!

check_lg2(git_repository_index(&index, repo), "Could not open repository index", NULL);
check_lg2(git_index_write_tree(&tree_oid, index), "Could not write tree", NULL);;
check_lg2(git_index_write(index), "Could not write index", NULL);

check_lg2(git_tree_lookup(&tree, repo, &tree_oid), "Error looking up tree", NULL);

check_lg2(git_signature_default(&signature, repo), "Error creating signature", NULL);

check_lg2(git_commit_create_v(
    &commit_oid,
    repo,
    "HEAD",
    signature,
    signature,
    NULL,
    comment,
    tree,
    parent ? 1 : 0, parent), "Error creating commit", NULL);

1 Ответ

1 голос
/ 10 июля 2020

Git использует несколько подходов для обработки этого случая, а libgit2 использует те же подходы для совместимости.

Когда Git необходимо обновить файл с фиксированным именем, таким как индекс или ссылка, он создает файл с тем же именем, но оканчивается на .lock, O_CREAT и O_EXCL, а затем записывает новое содержимое в этот файл. Затем он использует переименование atomi c поверх существующего файла. В системах Unix это означает, что процессы со старым открытым файлом не увидят изменений, а новые процессы откроют новый файл.

Если вы записываете объект в хранилище объектов, например, дерево или фиксацию, это не связано с гонками, потому что у него однозначное название. Файл либо существует, либо нет, а если нет, он создается как временный файл и переименовывается на место. Переименование означает, что если идентичный объект уже существует, он будет заменен идентичной копией.

Теперь возможно, что вы хотите записать файл, например индекс, и кто-то другой уже делает это , и в этом случае вам придется подождать, пока файл блокировки не исчезнет. Обычно время ожидания довольно короткое, поэтому ожидание не проблема. Для таких вещей, как индекс, libgit2 предлагает индексы в памяти, которые не требуют блокировки и от которых легче отказаться, если вы решите, что они вам не нужны.

Обратите внимание, что Git не гарантирует atomi c операций в рабочем дереве, потому что действительно невозможно полностью откатиться, если что-то go не так. Если вы просто имеете дело с содержимым репозитория и не обновляете рабочее дерево, тогда Git должен быть свободен от состояний гонки и достаточно производительным для нескольких пользователей.

...