libgit2 / libgit2/libgit2sharp
Parallel calls to Repository.ObjectDatabase.CreateBlob with identical contents fails.
Personne n'a encore pris cette issue.
- Langage dominant
- C#
- Étoiles
- 3.5k
- Forks
- 925
- Métriques de merge des PR
- Aucune PR mergée en 30 j
Description
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!
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Commencez par Repository.ObjectDatabase.CreateBlob et exécutez la reproduction en C# sur un dépôt bare. Suivez le chemin parallèle pour des contenus identiques ainsi que les résultats FILE_EXISTS et null-blob signalés. C’est terminé lorsque les appels concurrents s’achèvent sans l’un ou l’autre des deux échecs tout en créant le blob attendu.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- csharp, git
- Domaine
- databases
- Type d'issue
- Bug
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Activité
- À l'abandon
- Clarté
- Plutôt claire
- Accessibilité débutants
- 35/100