public BlobReferenceIterator(BlobStore blobs, byte[] blobhash, BlobLocation.BlobType blobtype, bool includefiles, bool bottomup) { Blobs = blobs; ParentHash = blobhash; BottomUp = bottomup; IncludeFiles = includefiles; BlobType = blobtype; }
/// <summary> /// Calculates the size of the blobs and child blobs referenced by the given hash. /// </summary> /// <param name="blobhash"></param> /// <returns>(Size of all referenced blobs, size of blobs referenced only by the given hash and its children)</returns> public (int allreferences, int uniquereferences) GetSizes(byte[] blobhash, BlobLocation.BlobType blobtype) { Dictionary <string, (int frequency, BlobLocation blocation)> hashfreqsize = new Dictionary <string, (int, BlobLocation)>(); GetBlobReferenceFrequencies(blobhash, blobtype, hashfreqsize); int allreferences = 0; int uniquereferences = 0; foreach (var(frequency, blocation) in hashfreqsize.Values) { allreferences += blocation.ByteLength * frequency; if (blocation.TotalReferenceCount == frequency) { uniquereferences += blocation.ByteLength; // TODO: unique referenes } } return(allreferences, uniquereferences); }
public void FinalizeBlobAddition(BackupSetReference bsname, byte[] blobhash, BlobLocation.BlobType blobType) { // Handle root blob BlobLocation rootblocation = GetBlobLocation(blobhash); if (rootblocation.TotalReferenceCount == 0) { IBlobReferenceIterator blobReferences = GetAllBlobReferences(blobhash, blobType, true, false); // Loop through children foreach (byte[] reference in blobReferences) { BlobLocation blocation = GetBlobLocation(reference); if (blocation.TotalReferenceCount > 0) // This was already stored { blobReferences.SkipChildrenOfCurrent(); } IncrementReferenceCountNoRecurse(bsname, blocation, blobhash, 1); } } // Increment root blob IncrementReferenceCountNoRecurse(bsname, rootblocation, blobhash, 1); }
public void DecrementReferenceCount(string backupsetname, byte[] blobhash, BlobLocation.BlobType blobtype, bool includefiles) { BlobLocation rootBlobLocation = GetBlobLocation(blobhash); if (rootBlobLocation.BSetReferenceCounts[backupsetname] == 1) // To be deleted? { IBlobReferenceIterator blobReferences = GetAllBlobReferences(blobhash, blobtype, includefiles, false); foreach (var reference in blobReferences) { BlobLocation blocation = GetBlobLocation(reference); // When we finish iterating over the children, decrement this blob blobReferences.PostOrderAction(() => IncrementReferenceCountNoRecurse(backupsetname, blocation, reference, -1)); if (rootBlobLocation.BSetReferenceCounts[backupsetname] != 1) // Not to be deleted? { // Dont need to decrement child references if this wont be deleted blobReferences.SkipChildren(); } } } IncrementReferenceCountNoRecurse(backupsetname, rootBlobLocation, blobhash, -1); // must delete parent last so parent can be loaded/used in GetAllBlobReferences() }
public void TransferBlobAndReferences(BlobStore dst, string dstbackupset, byte[] blobhash, BlobLocation.BlobType blobtype, bool includefiles) { BlobLocation rootDstBlobLocation; try { rootDstBlobLocation = dst.GetBlobLocation(blobhash); } catch (KeyNotFoundException) { byte[] blob; (rootDstBlobLocation, blob) = TransferBlobNoReferences(dst, dstbackupset, blobhash, GetBlobLocation(blobhash)); IBlobReferenceIterator blobReferences = GetAllBlobReferences(blobhash, blobtype, includefiles, false); blobReferences.SupplyData(blob); foreach (var reference in blobReferences) { BlobLocation dstBlobLocation; try { dstBlobLocation = dst.GetBlobLocation(reference); // Dont need to increment child references if this already exists blobReferences.SkipChildren(); } catch (KeyNotFoundException) { (dstBlobLocation, blob) = TransferBlobNoReferences(dst, dstbackupset, reference, GetBlobLocation(reference)); blobReferences.SupplyData(blob); } // When we finish iterating over the children, increment this blob blobReferences.PostOrderAction(() => dst.IncrementReferenceCountNoRecurse(dstbackupset, dstBlobLocation, reference, 1)); } } dst.IncrementReferenceCountNoRecurse(dstbackupset, rootDstBlobLocation, blobhash, 1); }
public IBlobReferenceIterator GetAllBlobReferences(byte[] blobhash, BlobLocation.BlobType blobtype, bool includefiles, bool bottomup = true) { return(new BlobReferenceIterator(this, blobhash, blobtype, includefiles, bottomup)); }
// TODO: If include files is false, should we require dstbackupset.EndsWith(Core.ShallowSuffix)? public void TransferBlobAndReferences(BlobStore dst, BackupSetReference dstbackupset, byte[] blobhash, BlobLocation.BlobType blobtype, bool includefiles) { bool refInDst; bool shallowInDst; BlobLocation?rootDstBlobLocation = null; try { rootDstBlobLocation = dst.GetBlobLocation(blobhash); refInDst = true; shallowInDst = rootDstBlobLocation.TotalNonShallowReferenceCount == 0; } catch (KeyNotFoundException) { refInDst = false; shallowInDst = false; // Meaningless when ref not in dst } if (!refInDst || (shallowInDst && includefiles)) { byte[]? blob; if (refInDst) { blob = RetrieveData(blobhash); } else { (rootDstBlobLocation, blob) = TransferBlobNoReferences(dst, dstbackupset, blobhash, GetBlobLocation(blobhash)); } IBlobReferenceIterator blobReferences = GetAllBlobReferences(blobhash, blobtype, includefiles, false); blobReferences.SupplyData(blob); foreach (var reference in blobReferences) { bool iterRefInDst; bool iterShallowInDst; BlobLocation?dstBlobLocation = null; try { dstBlobLocation = dst.GetBlobLocation(reference); iterRefInDst = true; iterShallowInDst = dstBlobLocation.TotalNonShallowReferenceCount == 0; } catch (KeyNotFoundException) { iterRefInDst = false; iterShallowInDst = false; // Meaningless when ref not in dst } if (!iterRefInDst || (iterShallowInDst && includefiles)) { if (iterRefInDst) { blob = RetrieveData(reference); } else { (dstBlobLocation, blob) = TransferBlobNoReferences(dst, dstbackupset, reference, GetBlobLocation(reference)); } blobReferences.SupplyData(blob); } else { // Dont need to increment child references if this already exists blobReferences.SkipChildrenOfCurrent(); } //if (!iterRefInDst) // Don't increment child reference if already present? //{ // When we finish iterating over the children, increment this blob #pragma warning disable CS8604 // Possible null reference argument. blobReferences.PostOrderAction(() => dst.IncrementReferenceCountNoRecurse(dstbackupset, dstBlobLocation, reference, 1)); #pragma warning restore CS8604 // Possible null reference argument. //} } } #pragma warning disable CS8604 // Possible null reference argument. dst.IncrementReferenceCountNoRecurse(dstbackupset, rootDstBlobLocation, blobhash, 1); #pragma warning restore CS8604 // Possible null reference argument. }
private void GetBlobReferenceFrequencies(byte[] blobhash, BlobLocation.BlobType blobtype, Dictionary <string, (int frequency, BlobLocation blocation)> hashfreqsize)