mirror of
https://github.com/gilbertchen/duplicacy
synced 2025-12-16 00:03:34 +00:00
Add a -vss-timeout option to set VSS creation timeout
This commit is contained in:
@@ -689,6 +689,7 @@ func backupRepository(context *cli.Context) {
|
|||||||
showStatistics := context.Bool("stats")
|
showStatistics := context.Bool("stats")
|
||||||
|
|
||||||
enableVSS := context.Bool("vss")
|
enableVSS := context.Bool("vss")
|
||||||
|
vssTimeout := context.Int("vss-timeout")
|
||||||
|
|
||||||
dryRun := context.Bool("dry-run")
|
dryRun := context.Bool("dry-run")
|
||||||
uploadRateLimit := context.Int("limit-rate")
|
uploadRateLimit := context.Int("limit-rate")
|
||||||
@@ -698,7 +699,7 @@ func backupRepository(context *cli.Context) {
|
|||||||
|
|
||||||
backupManager.SetupSnapshotCache(preference.Name)
|
backupManager.SetupSnapshotCache(preference.Name)
|
||||||
backupManager.SetDryRun(dryRun)
|
backupManager.SetDryRun(dryRun)
|
||||||
backupManager.Backup(repository, quickMode, threads, context.String("t"), showStatistics, enableVSS)
|
backupManager.Backup(repository, quickMode, threads, context.String("t"), showStatistics, enableVSS, vssTimeout)
|
||||||
|
|
||||||
runScript(context, preference.Name, "post")
|
runScript(context, preference.Name, "post")
|
||||||
}
|
}
|
||||||
@@ -1325,6 +1326,12 @@ func main() {
|
|||||||
Name: "vss",
|
Name: "vss",
|
||||||
Usage: "enable the Volume Shadow Copy service (Windows only)",
|
Usage: "enable the Volume Shadow Copy service (Windows only)",
|
||||||
},
|
},
|
||||||
|
cli.IntFlag{
|
||||||
|
Name: "vss-timeout",
|
||||||
|
Value: 0,
|
||||||
|
Usage: "the timeout in seconds to wait for the Volume Shadow Copy operation to complete",
|
||||||
|
Argument: "<timeout>",
|
||||||
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "storage",
|
Name: "storage",
|
||||||
Usage: "backup to the specified storage instead of the default one",
|
Usage: "backup to the specified storage instead of the default one",
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ func setEntryContent(entries []*Entry, chunkLengths []int, offset int) {
|
|||||||
// unmodified files with last backup). Otherwise (or if this is the first backup), the entire repository will
|
// unmodified files with last backup). Otherwise (or if this is the first backup), the entire repository will
|
||||||
// be scanned to create the snapshot. 'tag' is the tag assigned to the new snapshot.
|
// be scanned to create the snapshot. 'tag' is the tag assigned to the new snapshot.
|
||||||
func (manager *BackupManager) Backup(top string, quickMode bool, threads int, tag string,
|
func (manager *BackupManager) Backup(top string, quickMode bool, threads int, tag string,
|
||||||
showStatistics bool, shadowCopy bool) bool {
|
showStatistics bool, shadowCopy bool, shadowCopyTimeout int) bool {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
top, err = filepath.Abs(top)
|
top, err = filepath.Abs(top)
|
||||||
@@ -180,7 +180,7 @@ func (manager *BackupManager) Backup(top string, quickMode bool, threads int, ta
|
|||||||
LOG_INFO("BACKUP_START", "Last backup at revision %d found", remoteSnapshot.Revision)
|
LOG_INFO("BACKUP_START", "Last backup at revision %d found", remoteSnapshot.Revision)
|
||||||
}
|
}
|
||||||
|
|
||||||
shadowTop := CreateShadowCopy(top, shadowCopy)
|
shadowTop := CreateShadowCopy(top, shadowCopy, shadowCopyTimeout)
|
||||||
defer DeleteShadowCopy()
|
defer DeleteShadowCopy()
|
||||||
|
|
||||||
LOG_INFO("BACKUP_INDEXING", "Indexing %s", top)
|
LOG_INFO("BACKUP_INDEXING", "Indexing %s", top)
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ func TestBackupManager(t *testing.T) {
|
|||||||
backupManager.SetupSnapshotCache("default")
|
backupManager.SetupSnapshotCache("default")
|
||||||
|
|
||||||
SetDuplicacyPreferencePath(testDir + "/repository1/.duplicacy")
|
SetDuplicacyPreferencePath(testDir + "/repository1/.duplicacy")
|
||||||
backupManager.Backup(testDir+"/repository1" /*quickMode=*/, true, threads, "first", false, false)
|
backupManager.Backup(testDir+"/repository1" /*quickMode=*/, true, threads, "first", false, false, 0)
|
||||||
time.Sleep(time.Duration(delay) * time.Second)
|
time.Sleep(time.Duration(delay) * time.Second)
|
||||||
SetDuplicacyPreferencePath(testDir + "/repository2/.duplicacy")
|
SetDuplicacyPreferencePath(testDir + "/repository2/.duplicacy")
|
||||||
backupManager.Restore(testDir+"/repository2", threads, /*inPlace=*/false, /*quickMode=*/false, threads, /*overwrite=*/true,
|
backupManager.Restore(testDir+"/repository2", threads, /*inPlace=*/false, /*quickMode=*/false, threads, /*overwrite=*/true,
|
||||||
@@ -267,7 +267,7 @@ func TestBackupManager(t *testing.T) {
|
|||||||
modifyFile(testDir+"/repository1/dir1/file3", 0.3)
|
modifyFile(testDir+"/repository1/dir1/file3", 0.3)
|
||||||
|
|
||||||
SetDuplicacyPreferencePath(testDir + "/repository1/.duplicacy")
|
SetDuplicacyPreferencePath(testDir + "/repository1/.duplicacy")
|
||||||
backupManager.Backup(testDir+"/repository1" /*quickMode=*/, true, threads, "second", false, false)
|
backupManager.Backup(testDir+"/repository1" /*quickMode=*/, true, threads, "second", false, false, 0)
|
||||||
time.Sleep(time.Duration(delay) * time.Second)
|
time.Sleep(time.Duration(delay) * time.Second)
|
||||||
SetDuplicacyPreferencePath(testDir + "/repository2/.duplicacy")
|
SetDuplicacyPreferencePath(testDir + "/repository2/.duplicacy")
|
||||||
backupManager.Restore(testDir+"/repository2", 2, /*inPlace=*/true, /*quickMode=*/true, threads, /*overwrite=*/true,
|
backupManager.Restore(testDir+"/repository2", 2, /*inPlace=*/true, /*quickMode=*/true, threads, /*overwrite=*/true,
|
||||||
@@ -287,7 +287,7 @@ func TestBackupManager(t *testing.T) {
|
|||||||
os.Mkdir(testDir+"/repository1/dir2/dir3", 0700)
|
os.Mkdir(testDir+"/repository1/dir2/dir3", 0700)
|
||||||
os.Mkdir(testDir+"/repository1/dir4", 0700)
|
os.Mkdir(testDir+"/repository1/dir4", 0700)
|
||||||
SetDuplicacyPreferencePath(testDir + "/repository1/.duplicacy")
|
SetDuplicacyPreferencePath(testDir + "/repository1/.duplicacy")
|
||||||
backupManager.Backup(testDir+"/repository1" /*quickMode=*/, false, threads, "third", false, false)
|
backupManager.Backup(testDir+"/repository1" /*quickMode=*/, false, threads, "third", false, false, 0)
|
||||||
time.Sleep(time.Duration(delay) * time.Second)
|
time.Sleep(time.Duration(delay) * time.Second)
|
||||||
|
|
||||||
// Create some directories and files under repository2 that will be deleted during restore
|
// Create some directories and files under repository2 that will be deleted during restore
|
||||||
@@ -350,7 +350,7 @@ func TestBackupManager(t *testing.T) {
|
|||||||
}
|
}
|
||||||
backupManager.SnapshotManager.CheckSnapshots( /*snapshotID*/ "host1" /*revisions*/, []int{2, 3} /*tag*/, "",
|
backupManager.SnapshotManager.CheckSnapshots( /*snapshotID*/ "host1" /*revisions*/, []int{2, 3} /*tag*/, "",
|
||||||
/*showStatistics*/ false /*showTabular*/, false /*checkFiles*/, false /*searchFossils*/, false /*resurrect*/, false)
|
/*showStatistics*/ false /*showTabular*/, false /*checkFiles*/, false /*searchFossils*/, false /*resurrect*/, false)
|
||||||
backupManager.Backup(testDir+"/repository1" /*quickMode=*/, false, threads, "fourth", false, false)
|
backupManager.Backup(testDir+"/repository1" /*quickMode=*/, false, threads, "fourth", false, false, 0)
|
||||||
backupManager.SnapshotManager.PruneSnapshots("host1", "host1" /*revisions*/, nil /*tags*/, nil /*retentions*/, nil,
|
backupManager.SnapshotManager.PruneSnapshots("host1", "host1" /*revisions*/, nil /*tags*/, nil /*retentions*/, nil,
|
||||||
/*exhaustive*/ false /*exclusive=*/, true /*ignoredIDs*/, nil /*dryRun*/, false /*deleteOnly*/, false /*collectOnly*/, false)
|
/*exhaustive*/ false /*exclusive=*/, true /*ignoredIDs*/, nil /*dryRun*/, false /*deleteOnly*/, false /*collectOnly*/, false)
|
||||||
numberOfSnapshots = backupManager.SnapshotManager.ListSnapshots( /*snapshotID*/ "host1" /*revisionsToList*/, nil /*tag*/, "" /*showFiles*/, false /*showChunks*/, false)
|
numberOfSnapshots = backupManager.SnapshotManager.ListSnapshots( /*snapshotID*/ "host1" /*revisionsToList*/, nil /*tag*/, "" /*showFiles*/, false /*showChunks*/, false)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
package duplicacy
|
package duplicacy
|
||||||
|
|
||||||
func CreateShadowCopy(top string, shadowCopy bool) (shadowTop string) {
|
func CreateShadowCopy(top string, shadowCopy bool, timeoutInSeconds int) (shadowTop string) {
|
||||||
return top
|
return top
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -353,12 +353,15 @@ func DeleteShadowCopy() {
|
|||||||
ole.CoUninitialize()
|
ole.CoUninitialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateShadowCopy(top string, shadowCopy bool) (shadowTop string) {
|
func CreateShadowCopy(top string, shadowCopy bool, timeoutInSeconds int) (shadowTop string) {
|
||||||
|
|
||||||
if !shadowCopy {
|
if !shadowCopy {
|
||||||
return top
|
return top
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if timeoutInSeconds <= 60 {
|
||||||
|
timeoutInSeconds = 60
|
||||||
|
}
|
||||||
ole.CoInitialize(0)
|
ole.CoInitialize(0)
|
||||||
defer ole.CoUninitialize()
|
defer ole.CoUninitialize()
|
||||||
|
|
||||||
@@ -416,7 +419,7 @@ func CreateShadowCopy(top string, shadowCopy bool) (shadowTop string) {
|
|||||||
return top
|
return top
|
||||||
}
|
}
|
||||||
|
|
||||||
if !async.Wait(60) {
|
if !async.Wait(timeoutInSeconds) {
|
||||||
LOG_ERROR("VSS_GATHER", "Shadow copy creation failed: GatherWriterMetadata didn't finish properly")
|
LOG_ERROR("VSS_GATHER", "Shadow copy creation failed: GatherWriterMetadata didn't finish properly")
|
||||||
return top
|
return top
|
||||||
}
|
}
|
||||||
@@ -456,7 +459,7 @@ func CreateShadowCopy(top string, shadowCopy bool) (shadowTop string) {
|
|||||||
return top
|
return top
|
||||||
}
|
}
|
||||||
|
|
||||||
if !async.Wait(60) {
|
if !async.Wait(timeoutInSeconds) {
|
||||||
LOG_ERROR("VSS_PREPARE", "Shadow copy creation failed: PrepareForBackup didn't finish properly")
|
LOG_ERROR("VSS_PREPARE", "Shadow copy creation failed: PrepareForBackup didn't finish properly")
|
||||||
return top
|
return top
|
||||||
}
|
}
|
||||||
@@ -473,7 +476,7 @@ func CreateShadowCopy(top string, shadowCopy bool) (shadowTop string) {
|
|||||||
return top
|
return top
|
||||||
}
|
}
|
||||||
|
|
||||||
if !async.Wait(180) {
|
if !async.Wait(timeoutInSeconds) {
|
||||||
LOG_ERROR("VSS_SNAPSHOT", "Shadow copy creation failed: DoSnapshotSet didn't finish properly")
|
LOG_ERROR("VSS_SNAPSHOT", "Shadow copy creation failed: DoSnapshotSet didn't finish properly")
|
||||||
return top
|
return top
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user