public void FinalizeBackupAddition(BackupSetReference bsname, byte[] backuphash, byte[] mtreehash, HashTreeNode mtreereferences) { BlobLocation backupblocation = GetBlobLocation(backuphash); int? backupRefCount = backupblocation.GetBSetReferenceCount(bsname); if (!backupRefCount.HasValue || backupRefCount == 0) { BlobLocation mtreeblocation = GetBlobLocation(mtreehash); int? mtreeRefCount = mtreeblocation.GetBSetReferenceCount(bsname); if (!mtreeRefCount.HasValue || mtreeRefCount == 0) { ISkippableChildrenIterator <byte[]> childReferences = mtreereferences.GetChildIterator(); foreach (var blobhash in childReferences) { BlobLocation blocation = GetBlobLocation(blobhash); int? refCount = blocation.GetBSetReferenceCount(bsname); if (refCount.HasValue && refCount > 0) // This was already stored { childReferences.SkipChildrenOfCurrent(); } else if (blocation.BlockHashes != null) { foreach (var mbref in blocation.BlockHashes) { IncrementReferenceCountNoRecurse(bsname, mbref, 1); } } IncrementReferenceCountNoRecurse(bsname, blocation, blobhash, 1); } IncrementReferenceCountNoRecurse(bsname, mtreeblocation, mtreehash, 1); } IncrementReferenceCountNoRecurse(bsname, backupblocation, backuphash, 1); } }
public void DecrementReferenceCount(BackupSetReference backupsetname, byte[] blobhash, BlobLocation.BlobType blobtype, bool includefiles) { BlobLocation rootBlobLocation = GetBlobLocation(blobhash); if (rootBlobLocation.GetBSetReferenceCount(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)); try { if (blocation.GetBSetReferenceCount(backupsetname) != 1) // Not to be deleted? { // Dont need to decrement child references if this wont be deleted blobReferences.SkipChildrenOfCurrent(); } } catch (KeyNotFoundException) { throw; } } } IncrementReferenceCountNoRecurse(backupsetname, rootBlobLocation, blobhash, -1); // must delete parent last so parent can be loaded/used in GetAllBlobReferences() }
private void IncrementReferenceCountNoRecurse(BackupSetReference backupset, BlobLocation blocation, byte[] blobhash, int amount) { bool originallyshallow = blocation.TotalNonShallowReferenceCount == 0; int? refCount = blocation.GetBSetReferenceCount(backupset); int newRefCount = refCount.GetValueOrDefault(0) + amount; blocation.SetBSetReferenceCount(backupset, newRefCount); if (newRefCount == 0) { blocation.RemoveBSetReference(backupset); } else if (newRefCount < 0) { throw new Exception("Negative reference count in blobstore"); } if (blocation.BlockHashes == null) // Can't delete from disk if this is a multiblock reference (does not directly store data on disk) { if (blocation.TotalNonShallowReferenceCount == 0) { if (!originallyshallow) { try { if (blocation.EncryptedHash == null) { throw new Exception("Hash should not be null"); } Dependencies.DeleteBlob(blocation.EncryptedHash, blocation.RelativeFilePath); } catch (Exception e) { throw new Exception("Error deleting unreferenced file.", e); } } } } if (blocation.TotalReferenceCount == 0) { IndexStore.Remove(blobhash); } }