public BackupRecord GetBackupRecord(string bsname, byte[] hash) { if (hash == null) { return(GetBackupRecord(bsname)); } return(BackupRecord.deserialize(Dependencies.Blobs.RetrieveData(hash))); }
/// <summary> /// /// </summary> /// <param name="bsname"></param> /// <param name="message"></param> /// <param name="metadatatreehash"></param> /// <param name="shallow"></param> /// <returns>The hash of the new backup</returns> public byte[] AddBackup(string bsname, string message, byte[] metadatatreehash, bool shallow, DateTime backupTime, BackupSet bset = null) { if (bset == null) { bset = LoadBackupSet(bsname); } BackupRecord newbackup = new BackupRecord(message, metadatatreehash, backupTime); byte[] brbytes = newbackup.serialize(); byte[] backuphash = BlobStore.StoreData(new List <BlobStore>(1) { Dependencies.Blobs }, bsname, brbytes); bset.Backups.Add((backuphash, shallow)); return(backuphash); }
/// <summary> /// Syncs a cache with this backup store for the given bsname. /// Moves blobs only present in cache to the blobstore tied to this BackupStore /// Does not trigger a save of either cache or this backup set /// </summary> /// <param name="cache"></param> /// <param name="bsname"></param> /// <param name="dstbset"></param> /// <param name="cachebset"></param> public (BackupSet dstbset, BackupSet cachebset) SyncCache(BackupStore cache, string bsname, BackupSet dstbset = null, BackupSet cachebset = null) { int cacheindex = 0; int dstindex = 0; BackupRecord cachebr = null; BackupRecord dstbr = null; string cachebsname = bsname + Core.CacheSuffix; if (dstbset == null) { dstbset = LoadBackupSet(bsname); } if (cachebset == null) { cachebset = cache.LoadBackupSet(cachebsname); } if (cachebset.Backups.Count > 0 && dstbset.Backups.Count > 0) { while (cachebset.Backups.Count > cacheindex && dstbset.Backups.Count > dstindex) { if (!cachebset.Backups[cacheindex].hash.SequenceEqual(dstbset.Backups[dstindex].hash)) { if (cachebr == null) { cachebr = cache.GetBackupRecord(cachebsname, cachebset.Backups[cacheindex].hash); } if (dstbr == null) { dstbr = GetBackupRecord(bsname, dstbset.Backups[dstindex].hash); } if (cachebr.BackupTime < dstbr.BackupTime) { if (cachebset.Backups[cacheindex].shallow) { // Remove shallow backups from cache not present in dst cache.Dependencies.Blobs.DecrementReferenceCount(cachebsname, cachebset.Backups[cacheindex].hash, BlobLocation.BlobType.BackupRecord, false); cachebset.Backups.RemoveAt(cacheindex); } else { // Add non shallow backups from cache not present in dst dstbset.Backups.Insert(dstindex, (cachebset.Backups[cacheindex].hash, false)); cache.Dependencies.Blobs.TransferBackup(Dependencies.Blobs, bsname, cachebset.Backups[cacheindex].hash, true); // After transfer, make the cache backup shallow // Since no clean way to only get file references and not "parent" references, // we delete the entire backup data from cache, then add it back shallow // TODO: Means to iterate through blobs only including files cache.Dependencies.Blobs.DecrementReferenceCount(cachebsname, cachebset.Backups[cacheindex].hash, BlobLocation.BlobType.BackupRecord, true); Dependencies.Blobs.TransferBackup(cache.Dependencies.Blobs, cachebsname, dstbset.Backups[dstindex].hash, false); dstindex += 1; // After insert and increment j still referes to the same backup (dstbr) cacheindex += 1; } cachebr = null; } else // (srcbr.BackupTime > dstbr.BackupTime) { // Add (as shallow) backups in dst not present in cache cachebset.Backups.Insert(cacheindex, (dstbset.Backups[dstindex].hash, true)); Dependencies.Blobs.TransferBackup(cache.Dependencies.Blobs, cachebsname, dstbset.Backups[dstindex].hash, false); cacheindex += 1; dstindex += 1; dstbr = null; } } else { cacheindex += 1; cachebr = null; dstindex += 1; dstbr = null; } } } // Handle backups "dangling" after merge while (cacheindex < cachebset.Backups.Count) { if (cachebset.Backups[cacheindex].shallow) { // Remove shallow backups from cache not present in dst cache.Dependencies.Blobs.DecrementReferenceCount(cachebsname, cachebset.Backups[cacheindex].hash, BlobLocation.BlobType.BackupRecord, false); cachebset.Backups.RemoveAt(cacheindex); } else { // Add non shallow backups from cache not present in dst dstbset.Backups.Add((cachebset.Backups[cacheindex].hash, false)); cache.Dependencies.Blobs.TransferBackup(Dependencies.Blobs, bsname, cachebset.Backups[cacheindex].hash, true); dstindex += 1; // After insert and increment j still referes to the same backup (dstbr) cacheindex += 1; } cachebr = null; } while (dstindex < dstbset.Backups.Count) { // Add (as shallow) backups in dst not present in cache cachebset.Backups.Add((dstbset.Backups[dstindex].hash, true)); Dependencies.Blobs.TransferBackup(cache.Dependencies.Blobs, cachebsname, dstbset.Backups[dstindex].hash, false); cacheindex += 1; dstindex += 1; dstbr = null; } Dependencies.Blobs.CacheBlobList(bsname, cache.Dependencies.Blobs); return(dstbset, cachebset); }