private void InsertPack(PackFile pf) { ObjectDirectory.PackList o; ObjectDirectory.PackList n; do { o = packList.Get(); // If the pack in question is already present in the list // (picked up by a concurrent thread that did a scan?) we // do not want to insert it a second time. // PackFile[] oldList = o.packs; string name = pf.GetPackFile().GetName(); foreach (PackFile p in oldList) { if (PackFile.SORT.Compare(pf, p) < 0) { break; } if (name.Equals(p.GetPackFile().GetName())) { return; } } PackFile[] newList = new PackFile[1 + oldList.Length]; newList[0] = pf; System.Array.Copy(oldList, 0, newList, 1, oldList.Length); n = new ObjectDirectory.PackList(o.snapshot, newList); }while (!packList.CompareAndSet(o, n)); }
private static IDictionary <string, PackFile> ReuseMap(ObjectDirectory.PackList old ) { IDictionary <string, PackFile> forReuse = new Dictionary <string, PackFile>(); foreach (PackFile p in old.packs) { if (p.Invalid()) { // The pack instance is corrupted, and cannot be safely used // again. Do not include it in our reuse map. // p.Close(); continue; } PackFile prior = forReuse.Put(p.GetPackFile().GetName(), p); if (prior != null) { // This should never occur. It should be impossible for us // to have two pack files with the same name, as all of them // came out of the same directory. If it does, we promised to // close any PackFiles we did not reuse, so close the second, // readers are likely to be actively using the first. // forReuse.Put(prior.GetPackFile().GetName(), prior); p.Close(); } } return(forReuse); }
public virtual void TestKeepFiles() { BranchBuilder bb = tr.Branch("refs/heads/master"); bb.Commit().Add("A", "A").Add("B", "B").Create(); stats = gc.GetStatistics(); NUnit.Framework.Assert.AreEqual(4, stats.numberOfLooseObjects); NUnit.Framework.Assert.AreEqual(0, stats.numberOfPackedObjects); NUnit.Framework.Assert.AreEqual(0, stats.numberOfPackFiles); gc.Gc(); stats = gc.GetStatistics(); NUnit.Framework.Assert.AreEqual(0, stats.numberOfLooseObjects); NUnit.Framework.Assert.AreEqual(4, stats.numberOfPackedObjects); NUnit.Framework.Assert.AreEqual(1, stats.numberOfPackFiles); Iterator <PackFile> packIt = ((ObjectDirectory)repo.ObjectDatabase).GetPacks().Iterator (); PackFile singlePack = packIt.Next(); NUnit.Framework.Assert.IsFalse(packIt.HasNext()); FilePath keepFile = new FilePath(singlePack.GetPackFile().GetPath() + ".keep"); NUnit.Framework.Assert.IsFalse(keepFile.Exists()); NUnit.Framework.Assert.IsTrue(keepFile.CreateNewFile()); bb.Commit().Add("A", "A2").Add("B", "B2").Create(); stats = gc.GetStatistics(); NUnit.Framework.Assert.AreEqual(4, stats.numberOfLooseObjects); NUnit.Framework.Assert.AreEqual(4, stats.numberOfPackedObjects); NUnit.Framework.Assert.AreEqual(1, stats.numberOfPackFiles); gc.Gc(); stats = gc.GetStatistics(); NUnit.Framework.Assert.AreEqual(0, stats.numberOfLooseObjects); NUnit.Framework.Assert.AreEqual(8, stats.numberOfPackedObjects); NUnit.Framework.Assert.AreEqual(2, stats.numberOfPackFiles); // check that no object is packed twice Iterator <PackFile> packs = ((ObjectDirectory)repo.ObjectDatabase).GetPacks().Iterator (); PackIndex ind1 = packs.Next().GetIndex(); NUnit.Framework.Assert.AreEqual(4, ind1.GetObjectCount()); PackIndex ind2 = packs.Next().GetIndex(); NUnit.Framework.Assert.AreEqual(4, ind2.GetObjectCount()); foreach (PackIndex.MutableEntry e in ind1) { if (ind2.HasObject(e.ToObjectId())) { NUnit.Framework.Assert.IsFalse(ind2.HasObject(e.ToObjectId()), "the following object is in both packfiles: " + e.ToObjectId()); } } }
/// <exception cref="System.IO.IOException"></exception> internal void CopyPackAsIs(PackFile pack, long length, bool validate, PackOutputStream @out) { MessageDigest md = null; if (validate) { md = Constants.NewMessageDigest(); byte[] buf = @out.GetCopyBuffer(); Pin(pack, 0); if (window.Copy(0, buf, 0, 12) != 12) { pack.SetInvalid(); throw new IOException(JGitText.Get().packfileIsTruncated); } md.Update(buf, 0, 12); } long position = 12; long remaining = length - (12 + 20); while (0 < remaining) { Pin(pack, position); int ptr = (int)(position - window.start); int n = (int)Math.Min(window.Size() - ptr, remaining); window.Write(@out, position, n, md); position += n; remaining -= n; } if (md != null) { byte[] buf = new byte[20]; byte[] actHash = md.Digest(); Pin(pack, position); if (window.Copy(position, buf, 0, 20) != 20) { pack.SetInvalid(); throw new IOException(JGitText.Get().packfileIsTruncated); } if (!Arrays.Equals(actHash, buf)) { pack.SetInvalid(); throw new IOException(MessageFormat.Format(JGitText.Get().packfileCorruptionDetected , pack.GetPackFile().GetPath())); } } }