libgit2 / libgit2/libgit2sharp
Parallel calls to Repository.ObjectDatabase.CreateBlob with identical contents fails.
Ninguém assumiu esta issue ainda.
- Linguagem predominante
- C#
- Estrelas
- 3.5k
- Forks
- 925
- Métricas de merge de PRs
- Nenhum PR com merge em 30d
Descrição
I would like to insert blobs from memory into an object database in parallel (based on the technique described at http://stackoverflow.com/a/16244234). This works fine most of the time, but is subject to race conditions if the contents are the same. There are two classes of errors I observe:
1. Exception due to FILE_EXISTS conflict when trying to create the directory with the first two characters of the OID under objects.
2. NULL blob returned from CreateBlob.
Here's some example code to reproduce the problem:
using System;
using System.Text;
using System.IO;
using System.Threading.Tasks;
using LibGit2Sharp;
namespace GitODBStress
{
class Program
{
static void Main()
{
string repoPath = Path.Combine(Path.GetTempPath(), "Git_Parallel_Odb");
int iterationCount = 100;
if (!Directory.Exists(repoPath))
{
Directory.CreateDirectory(repoPath);
}
var path = Repository.Init(repoPath, isBare:true);
Console.WriteLine("Made repo at {0}", path);
var repo = new Repository(path);
var tasks = new Task[2];
for (int i = 0; i < iterationCount; ++i)
{
var iter = i;
byte[] buf = Encoding.ASCII.GetBytes("foo" + iter.ToString());
for (int taskNo = 0; taskNo < 2; ++taskNo)
{
tasks[taskNo] = Task.Factory.StartNew(() =>
{
MemoryStream ms = new MemoryStream(buf);
for (; ; )
{
try
{
var blob = repo.ObjectDatabase.CreateBlob(ms);
if (blob == null)
{
Console.WriteLine("ERROR: NULL blob on iteration {0}", iter);
continue;
}
break;
}
catch (LibGit2SharpException e)
{
Console.WriteLine("ERROR: Caught LibGit2SharpException on iteration {0}: {1}", iter, e.Message);
if (e.Message.Contains("Cannot create a file when that file already exists."))
{
continue;
}
}
}
});
}
Task.WaitAll(tasks);
}
repo.Dispose();
// clean up temp repo files
var files = Directory.GetFiles(repoPath, "*.*", SearchOption.AllDirectories);
foreach (var f in files)
{
var attrib = File.GetAttributes(f);
if (attrib.HasFlag(FileAttributes.ReadOnly))
{
File.SetAttributes(f, attrib & ~FileAttributes.ReadOnly);
}
}
Directory.Delete(repoPath, true);
}
}
}
Thanks!
Guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Direção de pesquisa
Comece em Repository.ObjectDatabase.CreateBlob e execute a reprodução em C# em um repositório bare. Rastreie o caminho paralelo para conteúdos idênticos e os resultados FILE_EXISTS e null-blob relatados. Está concluído quando as chamadas concorrentes forem concluídas sem nenhuma das duas falhas ao criar o blob esperado.
Escrita pelo modelo de indexação a partir do texto da issue.
Avaliação
- Stack de tecnologia
- csharp, git
- Domínio
- databases
- Tipo de issue
- Bug
- Dificuldade
- 4/5
- Tempo estimado
- 3-5 dias
- Status de atividade
- Estagnada
- Clareza
- Razoavelmente clara
- Facilidade para iniciantes
- 35/100