/// <summary> /// Loads a lagern index. /// </summary> /// <returns></returns> private (BlobStore blobs, BackupStore backups) LoadIndex() { BlobStoreDependencies blobStoreDependencies = new BlobStoreDependencies(DstFSInterop); BlobStore blobs = BlobStore.deserialize(DstFSInterop.LoadIndexFileAsync(null, IndexFileType.BlobIndex).Result, blobStoreDependencies); BackupStoreDependencies backupStoreDependencies = new BackupStoreDependencies(DstFSInterop, blobs); BackupStore backups = new BackupStore(backupStoreDependencies); return(blobs, backups); }
/// <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; BackupSetReference cachebsname = new(bsname, false, true, false); if (dstbset == null) { dstbset = LoadBackupSet(new BackupSetReference(bsname, false, false, false)); } if (cachebset == null) { cachebset = cache.LoadBackupSet(new BackupSetReference(bsname, false, false, false)); } 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(new BackupSetReference(bsname, false, false, false), 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, new BackupSetReference(bsname, false, false, false), 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, new BackupSetReference(bsname, false, false, false), cachebset.Backups[cacheindex].hash, true); dstindex += 1; // After insert and increment j still referes to the same backup (dstbr) cacheindex += 1; } } 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; } Dependencies.Blobs.CacheBlobList(bsname, cache.Dependencies.Blobs); return(dstbset, cachebset); }