Ejemplo n.º 1
0
 /// <summary>
 /// Restores a single backup entry to the file system
 /// </summary>
 /// <param name="restoreEntry">
 /// The entry to restore
 /// </param>
 void RestoreEntry(SkyFloe.Restore.Entry restoreEntry)
 {
     // fetch the corresponding backup entry
      var backupEntry = this.Archive.BackupIndex.FetchEntry(restoreEntry.BackupEntryID);
      ReportProgress(
     new ProgressEventArgs()
     {
        Operation = "BeginRestoreEntry",
        BackupSession = backupEntry.Session,
        BackupEntry = backupEntry,
        RestoreSession = this.Session,
        RestoreEntry = restoreEntry
     }
      );
      var path = IO.Path.Empty;
      try
      {
     // determine whether to restore the entry
     path = PrepareFile(backupEntry);
     if (!path.IsEmpty)
     {
        // restore or delete the entry
        if (backupEntry.State != SkyFloe.Backup.EntryState.Deleted)
           RestoreFile(path, backupEntry, restoreEntry);
        else if (this.Session.EnableDeletes)
           IO.FileSystem.Delete(path);
        this.Session.RestoreLength += restoreEntry.Length;
     }
     // the restore was successful or skipped, so commit it to the index
     restoreEntry.State = SkyFloe.Restore.EntryState.Completed;
     using (var txn = new TransactionScope())
     {
        this.Archive.RestoreIndex.UpdateEntry(restoreEntry);
        this.Archive.RestoreIndex.UpdateSession(this.Session);
        txn.Complete();
     }
      }
      catch (Exception e)
      {
     if (!path.IsEmpty)
        try { IO.FileSystem.Delete(path); }
        catch { }
     switch (ReportError("RestoreEntry", e))
     {
        case ErrorResult.Retry:
           // the client chose to retry, so leave the entry pending
           break;
        case ErrorResult.Fail:
           // the client chose to ignore the failed entry,
           // so mark it as failed and continue
           restoreEntry = this.Archive.RestoreIndex.FetchEntry(restoreEntry.ID);
           restoreEntry.State = SkyFloe.Restore.EntryState.Failed;
           this.Archive.RestoreIndex.UpdateEntry(restoreEntry);
           break;
        default:
           // the client chose to abort, so propagate the exception
           throw;
     }
      }
      if (restoreEntry.State == SkyFloe.Restore.EntryState.Completed)
     ReportProgress(
        new ProgressEventArgs()
        {
           Operation = "EndRestoreEntry",
           BackupSession = backupEntry.Session,
           BackupEntry = backupEntry,
           RestoreSession = this.Session,
           RestoreEntry = restoreEntry
        }
     );
 }
Ejemplo n.º 2
0
 /// <summary>
 /// Backs up a single file entry to the attached archive
 /// </summary>
 /// <param name="entry">
 /// The entry to store
 /// </param>
 private void BackupEntry(SkyFloe.Backup.Entry entry)
 {
     ReportProgress(
     new ProgressEventArgs()
     {
        Operation = "BeginBackupEntry",
        BackupSession = this.Session,
        BackupEntry = entry
     }
      );
      try
      {
     using (var input = new IO.StreamStack())
     {
        // create the input stream stack, consisting of the following
        // . source file
        // . CRC calculation filter
        // . optional compressor
        // . encryptor
        // . read rate limiter
        input.Push(
           IO.FileSystem.Open(entry.Node.GetAbsolutePath())
        );
        input.Push(
           new IO.CrcFilter(input.Top)
        );
        if (this.Session.Compress)
           input.Push(
              new IO.CompressionStream(
                 input.Top,
                 IO.CompressionMode.Compress
              )
           );
        input.Push(
           new CryptoStream(
              input.Top,
              this.Crypto.CreateEncryptor(),
              CryptoStreamMode.Read
           )
        );
        input.Push(
           this.limiter.CreateStreamFilter(input.Top)
        );
        // send the stream stack to the backup plugin
        // and record the calculated CRC value in the entry
        this.backup.Backup(entry, input);
        entry.Crc32 = input.GetStream<IO.CrcFilter>().Value;
     }
     // commit the archive entry to the index
     // at this point, the entry is locally durable
     // until the next checkpoint, when it becomes permanent
     entry.State = SkyFloe.Backup.EntryState.Completed;
     entry.Blob.Length += entry.Length;
     this.Session.ActualLength += entry.Length;
     using (var txn = new TransactionScope())
     {
        this.Archive.BackupIndex.UpdateEntry(entry);
        this.Archive.BackupIndex.UpdateBlob(entry.Blob);
        this.Archive.BackupIndex.UpdateSession(this.Session);
        txn.Complete();
     }
      }
      catch (Exception e)
      {
     switch (ReportError("BackupEntry", e))
     {
        case ErrorResult.Retry:
           // the client chose to retry, so leave the entry pending
           break;
        case ErrorResult.Fail:
           // the client chose to ignore the failed entry,
           // so mark it as failed and continue
           entry = this.Archive.BackupIndex.FetchEntry(entry.ID);
           entry.State = SkyFloe.Backup.EntryState.Failed;
           this.Archive.BackupIndex.UpdateEntry(entry);
           break;
        default:
           // the client chose to abort, so propagate the exception
           throw;
     }
      }
      if (entry.State == SkyFloe.Backup.EntryState.Completed)
     ReportProgress(
        new ProgressEventArgs()
        {
           Operation = "EndBackupEntry",
           BackupSession = this.Session,
           BackupEntry = entry
        }
     );
 }