Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb746ab5e5 |
@@ -40,7 +40,8 @@ Features:
|
||||
|
||||
* modern encryption ([age](https://age-encryption.org/), X25519 + ChaCha20-Poly1305)
|
||||
* content-defined chunking with deduplication (FastCDC)
|
||||
* incremental backups (only changed files are re-chunked)
|
||||
* incremental backups (a file is re-chunked only when it changed or a
|
||||
chunk it lists is held by no uploaded blob)
|
||||
* multithreaded zstd compression at configurable levels
|
||||
* content-addressed immutable storage
|
||||
* local state tracking in SQLite (enables write-only incremental backups)
|
||||
@@ -499,8 +500,9 @@ format does and does not protect.
|
||||
|
||||
* Content-defined chunking using the FastCDC algorithm
|
||||
* Average chunk size: configurable (default 10MB)
|
||||
* Deduplication at file level (unchanged files skipped) and chunk level
|
||||
(identical chunks across files stored once)
|
||||
* Deduplication at file level (unchanged files skipped, unless a chunk
|
||||
the file lists is held by no uploaded blob) and chunk level (identical
|
||||
chunks across files stored once)
|
||||
* Multiple chunks packed into blobs to reduce object count
|
||||
|
||||
### encryption
|
||||
|
||||
@@ -268,9 +268,9 @@ func (r *FileRepository) ListByPrefix(
|
||||
|
||||
// ListIDsWithChunksNotInUploadedBlobs returns the IDs of the files whose
|
||||
// path starts with prefix and that list at least one chunk held by no
|
||||
// blob whose upload has completed (uploaded_ts set). Such a file's
|
||||
// metadata can still match the file on disk while part of its data is
|
||||
// not in remote storage, so a backup must not treat it as unchanged.
|
||||
// blob whose upload has completed (uploaded_ts set). A new snapshot
|
||||
// cannot reference such a chunk, so a backup must not treat the file as
|
||||
// unchanged even when its metadata matches the file on disk.
|
||||
func (r *FileRepository) ListIDsWithChunksNotInUploadedBlobs(
|
||||
ctx context.Context, prefix string,
|
||||
) ([]types.FileID, error) {
|
||||
|
||||
@@ -344,7 +344,9 @@ func (s *Scanner) loadDatabaseState(
|
||||
// while a blob row is deleted once no snapshot references it. Removing
|
||||
// the only snapshot that references a changed file's current blob
|
||||
// therefore leaves an older snapshot keeping a file row whose metadata
|
||||
// matches the disk but whose data is not in remote storage.
|
||||
// matches the disk while no blob the local index records as uploaded
|
||||
// holds its chunks, so a new snapshot cannot reference them. The dropped
|
||||
// blob can still be in remote storage until prune removes it.
|
||||
func (s *Scanner) loadFilesToRechunk(ctx context.Context, path string) error {
|
||||
ids, err := s.repos.Files.ListIDsWithChunksNotInUploadedBlobs(ctx, path)
|
||||
if err != nil {
|
||||
@@ -1244,7 +1246,7 @@ func (s *Scanner) checkFileInMemory(
|
||||
return file, true
|
||||
}
|
||||
|
||||
// Part of its data is not in remote storage (see loadFilesToRechunk)
|
||||
// No uploaded blob holds one of its chunks (see loadFilesToRechunk)
|
||||
if _, rechunk := s.filesToRechunk[fileID]; rechunk {
|
||||
return file, true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user