Fix backup creation for collections > 1 GiB (#2423)
Co-authored-by: Damien Elmes <dae@users.noreply.github.com>
This commit is contained in:
parent
430a58a0d4
commit
0d92bd2ca8
@ -16,7 +16,7 @@ use itertools::Itertools;
|
||||
use tracing::error;
|
||||
|
||||
use crate::import_export::package::export_colpkg_from_data;
|
||||
use crate::io::read_file;
|
||||
use crate::io::read_locked_db_file;
|
||||
use crate::pb::config::preferences::BackupLimits;
|
||||
use crate::prelude::*;
|
||||
|
||||
@ -39,7 +39,7 @@ impl Collection {
|
||||
} else {
|
||||
let tr = self.tr.clone();
|
||||
self.storage.checkpoint()?;
|
||||
let col_data = read_file(&self.col_path)?;
|
||||
let col_data = read_locked_db_file(&self.col_path)?;
|
||||
self.update_last_backup_timestamp()?;
|
||||
Ok(Some(thread::spawn(move || {
|
||||
backup_inner(&col_data, &backup_folder, limits, &tr)
|
||||
|
@ -2,6 +2,8 @@
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::io::Seek;
|
||||
use std::path::Component;
|
||||
use std::path::Path;
|
||||
|
||||
@ -63,6 +65,34 @@ pub(crate) fn read_file(path: impl AsRef<Path>) -> Result<Vec<u8>> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Like [read_file], but skips the section that is potentially locked by
|
||||
/// SQLite.
|
||||
pub(crate) fn read_locked_db_file(path: impl AsRef<Path>) -> Result<Vec<u8>> {
|
||||
read_locked_db_file_inner(&path).context(FileIoSnafu {
|
||||
path: path.as_ref(),
|
||||
op: FileOp::Read,
|
||||
})
|
||||
}
|
||||
|
||||
const LOCKED_SECTION_START_BYTE: usize = 1024 * 1024 * 1024;
|
||||
const LOCKED_SECTION_LEN_BYTES: usize = 512;
|
||||
const LOCKED_SECTION_END_BYTE: usize = LOCKED_SECTION_START_BYTE + LOCKED_SECTION_LEN_BYTES;
|
||||
|
||||
fn read_locked_db_file_inner(path: impl AsRef<Path>) -> std::io::Result<Vec<u8>> {
|
||||
let size = std::fs::metadata(&path)?.len() as usize;
|
||||
if size < LOCKED_SECTION_END_BYTE {
|
||||
return std::fs::read(path);
|
||||
}
|
||||
|
||||
let mut file = File::open(&path)?;
|
||||
let mut buf = vec![0; size];
|
||||
file.read_exact(&mut buf[..LOCKED_SECTION_START_BYTE])?;
|
||||
file.seek(std::io::SeekFrom::Current(LOCKED_SECTION_LEN_BYTES as i64))?;
|
||||
file.read_exact(&mut buf[LOCKED_SECTION_END_BYTE..])?;
|
||||
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
pub(crate) fn new_tempfile() -> Result<NamedTempFile> {
|
||||
NamedTempFile::new().context(FileIoSnafu {
|
||||
path: std::env::temp_dir(),
|
||||
|
Loading…
Reference in New Issue
Block a user