Exemplo n.º 1
0
        /// <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);
        }
Exemplo n.º 2
0
 /// <summary>
 /// Loads a BackupSet from a file.
 /// </summary>
 /// <param name="backuplistfile"></param>
 /// <param name="blobs"></param>
 /// <returns>A previously stored BackupStore object</returns>
 public BackupSet LoadBackupSet(string bsname)
 {
     return(BackupSet.deserialize(Dependencies.LoadBackupSetData(bsname)));
 }
Exemplo n.º 3
0
 /// <summary>
 /// Attempts to save the BackupStore to disk.
 /// If saving fails an error is thrown.
 /// </summary>
 /// <param name="path"></param>
 public void SaveBackupSet(BackupSet bset, string bsname)
 {
     // NOTE: This overwrites the previous file every time.
     // This should be okay as the serialized BackupStore filesize should always be small.
     Dependencies.StoreBackupSetData(bsname, bset.serialize());
 }
Exemplo n.º 4
0
        /// <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);
        }