Parallel calls to Repository.ObjectDatabase.CreateBlob with identical contents fails.

Aperta
#1,122 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
35/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Ferma
Stack tecnologico
csharp, git
Ambito
databases

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.

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!

Lingua principale
C#
Stelle
3.5k
Fork
925
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di libgit2/libgit2sharp

Tutte le issue di libgit2/libgit2sharp

Issue simili

Altre issue su C#

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.