libgit2 / libgit2/libgit2sharp
Parallel calls to Repository.ObjectDatabase.CreateBlob with identical contents fails.
Nessuno ha ancora preso questa issue.
- Lingua principale
- C#
- Stelle
- 3.5k
- Fork
- 925
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Descrizione
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!
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia da Repository.ObjectDatabase.CreateBlob ed esegui la riproduzione in C# su un repository bare. Traccia il percorso parallelo per contenuti identici e gli esiti FILE_EXISTS e null-blob segnalati. Il lavoro è completato quando le chiamate concorrenti terminano senza nessuno dei due errori creando il blob previsto.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- csharp, git
- Ambito
- databases
- Tipo di issue
- Bug
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Ferma
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 35/100