1
0
mirror of https://github.com/gilbertchen/duplicacy synced 2025-12-06 00:03:38 +00:00

Compare commits

...

13 Commits

Author SHA1 Message Date
Gilbert Chen
fc35ddf7d1 Bump version to 2.2.2 2019-06-20 22:22:41 -04:00
gilbertchen
6efcd37c5c Merge pull request #562 from gilbertchen/azure_retry
Retry on broken pipe in Azure backend
2019-06-20 12:14:48 -04:00
gilbertchen
58558b8a2f Merge pull request #566 from TheBestPessimist/patch-1
Update the issue template
2019-06-20 12:14:08 -04:00
Gilbert Chen
045be3905b Better handling of B2 authorization failures
This commit fixed 2 issues wrt Backblaze B2 authorization:
* every thread may call b2_authorize_account at the same time when there
are 401 errors
* if B2 has a login outage, then all threads will call b2_authorize_account
repeatedly without delay

A simple solution is to limit one b2_authorize_account call to once every
30 second regardless of how many threads there are.  If the call to
b2_authorize_account is not allowed, the random exponential backoff will
be performed.
2019-06-13 22:43:07 -04:00
Gilbert Chen
4da7f7b6f9 Check -files may download a chunk multple times
This commit fixed a bug that caused 'check -files' to download the same chunk
multiple times if shared by multiple small files.
2019-06-13 14:47:21 -04:00
Gilbert Chen
41668d4bbd Update dependency github.com/gilbertchen/go.dbus 2019-06-07 15:17:46 -04:00
Gilbert Chen
9d4ac34f4b Don't compare hashes of empty files in the diff command
Empty files may or may not have a hash depending if the -hash option is used
during backup.
2019-06-06 12:35:34 -04:00
Gilbert Chen
eba5aa6eea Bump version to 2.2.1 2019-06-04 22:28:04 -04:00
Gilbert Chen
47c4c25d8b Fixed a bug that restoring files doesn't work due to missing parent directory
The root cause was path.Dir can't handle Windows paths that use \ as the
separator.
2019-06-04 21:57:10 -04:00
Gilbert Chen
37781f9540 Swtich CLI licensing to per-computer 2019-05-30 13:35:09 -04:00
TheBestPessimist
282fe4edd2 Update the issue template 2019-05-24 21:10:14 +03:00
TheBestPessimist
33c71ca5f8 Update the issue template
Use the new template format and ask people to use the forum **more thoroughly**.
2019-05-24 16:19:59 +03:00
Gilbert Chen
6e7d45caac Add a TRACE message when skipping a file to be restored 2019-05-22 12:03:21 -04:00
13 changed files with 71 additions and 22 deletions

View File

@@ -1,5 +1,17 @@
Please submit an issue for bug reports or feature requests. If you have any questions please post them on https://forum.duplicacy.com.
---
name: Please use the official forum
about: Please use the official forum instead of Github
title: 'Please use the official forum'
labels: ''
assignees: ''
When you're reporting a bug, please specify the OS, version, command line arguments, or any info that you think is helpful for the diagnosis. If Duplicacy reports an error, please post the program output here.
---
Note that this repository hosts the CLI version of Duplicacy only. If you're reporting anything related to the GUI version, please visit https://forum.duplicacy.com.
Please **use the [Duplicacy Forum](https://forum.duplicacy.com/)** when reporting bugs, making feature requests, asking for help or simply praising Duplicacy for its ease of use.
We strongly encourage you to create an account on the forum and use that platform for discussion as there is a higher chance that someone there will talk to you.
There is a handful of people watching the Github Issues and we are in the process of moving **all** of them to the forum as well. Most likely you will not receive an answer here or it will be very slow and you will be pointed to the forum.
We have already created a comprehensive [Guide](https://forum.duplicacy.com/t/duplicacy-user-guide/1197), and a [How-To](https://forum.duplicacy.com/c/how-to) category which stores more wisdom than these issues on Github.

2
Gopkg.lock generated
View File

@@ -71,7 +71,7 @@
branch = "master"
name = "github.com/gilbertchen/go.dbus"
packages = ["."]
revision = "9e442e6378618c083fd3b85b703ffd202721fb17"
revision = "8591994fa32f1dbe3fa9486bc6f4d4361ac16649"
[[projects]]
branch = "master"

View File

@@ -1,8 +1,7 @@
Copyright © 2017 Acrosync LLC
* Free for personal use or commercial trial
* Non-trial commercial use requires per-user CLI licenses available from [duplicacy.com](https://duplicacy.com/buy) at a cost of $20 per year
* A user is defined as the computer account that creates or edits the files to be backed up; if a backup contains files created or edited by multiple users for commercial purposes, one CLI license is required for each user
* Non-trial commercial use requires per-computer CLI licenses available from [duplicacy.com](https://duplicacy.com/buy.html) at a cost of $50 per year
* The computer with a valid commercial license for the GUI version may run the CLI version without a CLI license
* CLI licenses are not required to restore or manage backups; only the backup command requires valid CLI licenses
* Modification and redistribution are permitted, but commercial use of derivative works is subject to the same requirements of this license

View File

@@ -90,8 +90,7 @@ The following table compares the feature lists of all these backup tools:
## License
* Free for personal use or commercial trial
* Non-trial commercial use requires per-user CLI licenses available from [duplicacy.com](https://duplicacy.com/buy) at a cost of $20 per year
* A user is defined as the computer account that creates or edits the files to be backed up; if a backup contains files created or edited by multiple users for commercial purposes, one CLI license is required for each user
* Non-trial commercial use requires per-computer CLI licenses available from [duplicacy.com](https://duplicacy.com/buy.html) at a cost of $50 per year
* The computer with a valid commercial license for the GUI version may run the CLI version without a CLI license
* CLI licenses are not required to restore or manage backups; only the backup command requires valid CLI licenses
* Modification and redistribution are permitted, but commercial use of derivative works is subject to the same requirements of this license

View File

@@ -1981,7 +1981,7 @@ func main() {
app.Name = "duplicacy"
app.HelpName = "duplicacy"
app.Usage = "A new generation cloud backup tool based on lock-free deduplication"
app.Version = "2.2.0" + " (" + GitCommit + ")"
app.Version = "2.2.2" + " (" + GitCommit + ")"
// If the program is interrupted, call the RunAtError function.
c := make(chan os.Signal, 1)

View File

@@ -62,6 +62,8 @@ type B2Client struct {
Threads int
MaximumRetries int
TestMode bool
LastAuthorizationTime int64
}
// URL encode the given path but keep the slashes intact
@@ -253,8 +255,12 @@ func (client *B2Client) call(threadIndex int, requestURL string, method string,
if requestURL == B2AuthorizationURL {
return nil, nil, 0, fmt.Errorf("Authorization failure")
}
client.AuthorizeAccount(threadIndex)
continue
// Attempt authorization again. If authorization is actually not done, run the random backoff
_, allowed := client.AuthorizeAccount(threadIndex)
if allowed {
continue
}
} else if response.StatusCode == 403 {
if !client.TestMode {
return nil, nil, 0, fmt.Errorf("B2 cap exceeded")
@@ -291,13 +297,18 @@ type B2AuthorizeAccountOutput struct {
DownloadURL string
}
func (client *B2Client) AuthorizeAccount(threadIndex int) (err error) {
func (client *B2Client) AuthorizeAccount(threadIndex int) (err error, allowed bool) {
client.Lock.Lock()
defer client.Lock.Unlock()
// Don't authorize if the previous one was done less than 30 seconds ago
if client.LastAuthorizationTime != 0 && client.LastAuthorizationTime > time.Now().Unix() - 30 {
return nil, false
}
readCloser, _, _, err := client.call(threadIndex, B2AuthorizationURL, http.MethodPost, nil, make(map[string]string))
if err != nil {
return err
return err, true
}
defer readCloser.Close()
@@ -305,7 +316,7 @@ func (client *B2Client) AuthorizeAccount(threadIndex int) (err error) {
output := &B2AuthorizeAccountOutput{}
if err = json.NewDecoder(readCloser).Decode(&output); err != nil {
return err
return err, true
}
// The account id may be different from the application key id so we're getting the account id from the returned
@@ -317,7 +328,9 @@ func (client *B2Client) AuthorizeAccount(threadIndex int) (err error) {
client.DownloadURL = output.DownloadURL
client.IsAuthorized = true
return nil
client.LastAuthorizationTime = time.Now().Unix()
return nil, true
}
type ListBucketOutput struct {

View File

@@ -50,7 +50,7 @@ func TestB2Client(t *testing.T) {
b2Client.TestMode = true
err := b2Client.AuthorizeAccount(0)
err, _ := b2Client.AuthorizeAccount(0)
if err != nil {
t.Errorf("Failed to authorize the b2 account: %v", err)
return

View File

@@ -19,7 +19,7 @@ func CreateB2Storage(accountID string, applicationKey string, bucket string, sto
client := NewB2Client(accountID, applicationKey, storageDir, threads)
err = client.AuthorizeAccount(0)
err, _ = client.AuthorizeAccount(0)
if err != nil {
return nil, err
}

View File

@@ -807,6 +807,7 @@ func (manager *BackupManager) Restore(top string, revision int, inPlace bool, qu
if compare == 0 {
i++
if quickMode && local.IsSameAs(entry) {
LOG_TRACE("RESTORE_SKIP", "File %s unchanged (by size and timestamp)", local.Path)
skipped = true
}
}
@@ -898,7 +899,8 @@ func (manager *BackupManager) Restore(top string, revision int, inPlace bool, qu
continue
}
} else {
err = os.MkdirAll(path.Dir(fullPath), 0744)
parent, _ := SplitDir(fullPath)
err = os.MkdirAll(parent, 0744)
if err != nil {
LOG_ERROR("DOWNLOAD_MKDIR", "Failed to create directory: %v", err)
}

View File

@@ -197,6 +197,16 @@ func (downloader *ChunkDownloader) Reclaim(chunkIndex int) {
downloader.lastChunkIndex = chunkIndex
}
// Return the chunk last downloaded and its hash
func (downloader *ChunkDownloader) GetLastDownloadedChunk() (chunk *Chunk, chunkHash string) {
if downloader.lastChunkIndex >= len(downloader.taskList) {
return nil, ""
}
task := downloader.taskList[downloader.lastChunkIndex]
return task.chunk, task.chunkHash
}
// WaitForChunk waits until the specified chunk is ready
func (downloader *ChunkDownloader) WaitForChunk(chunkIndex int) (chunk *Chunk) {

View File

@@ -1194,7 +1194,6 @@ func (manager *SnapshotManager) RetrieveFile(snapshot *Snapshot, file *Entry, ou
}
var chunk *Chunk
currentHash := ""
for i := file.StartChunk; i <= file.EndChunk; i++ {
start := 0
@@ -1207,10 +1206,12 @@ func (manager *SnapshotManager) RetrieveFile(snapshot *Snapshot, file *Entry, ou
}
hash := snapshot.ChunkHashes[i]
if currentHash != hash {
lastChunk, lastChunkHash := manager.chunkDownloader.GetLastDownloadedChunk()
if lastChunkHash != hash {
i := manager.chunkDownloader.AddChunk(hash)
chunk = manager.chunkDownloader.WaitForChunk(i)
currentHash = hash
} else {
chunk = lastChunk
}
output(chunk.GetBytes()[start:end])
@@ -1482,7 +1483,11 @@ func (manager *SnapshotManager) Diff(top string, snapshotID string, revisions []
same = right.IsSameAs(left)
}
} else {
same = left.Hash == right.Hash
if left.Size == 0 && right.Size == 0 {
same = true
} else {
same = left.Hash == right.Hash
}
}
if !same {

View File

@@ -88,3 +88,7 @@ func (entry *Entry) SetAttributesToFile(fullPath string) {
func joinPath(components ...string) string {
return path.Join(components...)
}
func SplitDir(fullPath string) (dir string, file string) {
return path.Split(fullPath)
}

View File

@@ -126,3 +126,8 @@ func joinPath(components ...string) string {
}
return combinedPath
}
func SplitDir(fullPath string) (dir string, file string) {
i := strings.LastIndex(fullPath, "\\")
return fullPath[:i+1], fullPath[i+1:]
}