let env_type = rpcenv.env_type();
let backup_group = BackupGroup::new(backup_type, backup_id);
- let owner = datastore.create_backup_group(&backup_group, &username)?;
+
+ // lock backup group to only allow one backup per group at a time
+ let (owner, _group_guard) = datastore.create_locked_backup_group(&backup_group, &username)?;
+
// permission check
if owner != username { // only the owner is allowed to create additional snapshots
bail!("backup owner check failed ({} != {})", username, owner);
}
}
- // lock backup group to only allow one backup per group at a time
- let _group_guard = backup_group.lock(&datastore.base_path())?;
-
let (path, is_new) = datastore.create_backup_dir(&backup_dir)?;
if !is_new { bail!("backup directory already exists."); }
use lazy_static::lazy_static;
use chrono::{DateTime, Utc};
-use super::backup_info::{BackupGroup, BackupDir, BackupInfo};
+use super::backup_info::{BackupGroup, BackupGroupGuard, BackupDir, BackupInfo};
use super::chunk_store::ChunkStore;
use super::dynamic_index::{DynamicIndexReader, DynamicIndexWriter};
use super::fixed_index::{FixedIndexReader, FixedIndexWriter};
Ok(())
}
- /// Create a backup group if it does not already exists.
+ /// Create (if it does not already exists) and lock a backup group
///
/// And set the owner to 'userid'. If the group already exists, it returns the
/// current owner (instead of setting the owner).
- pub fn create_backup_group(&self, backup_group: &BackupGroup, userid: &str) -> Result<String, Error> {
+ ///
+ /// This also aquires an exclusive lock on the directory and returns the lock guard.
+ pub fn create_locked_backup_group(&self, backup_group: &BackupGroup, userid: &str) -> Result<(String, BackupGroupGuard), Error> {
// create intermediate path first:
let base_path = self.base_path();
// create the last component now
match std::fs::create_dir(&full_path) {
Ok(_) => {
+ let guard = backup_group.lock(&base_path)?;
self.set_owner(backup_group, userid, false)?;
let owner = self.get_owner(backup_group)?; // just to be sure
- Ok(owner)
+ Ok((owner, guard))
}
Err(ref err) if err.kind() == io::ErrorKind::AlreadyExists => {
+ let guard = backup_group.lock(&base_path)?;
let owner = self.get_owner(backup_group)?; // just to be sure
- Ok(owner)
+ Ok((owner, guard))
}
Err(err) => bail!("unable to create backup group {:?} - {}", full_path, err),
}
for item in list {
let group = BackupGroup::new(&item.backup_type, &item.backup_id);
- let owner = tgt_store.create_backup_group(&group, &username)?;
+ let (owner, _lock_guard) = tgt_store.create_locked_backup_group(&group, &username)?;
// permission check
if owner != username { // only the owner is allowed to create additional snapshots
worker.log(format!("sync group {}/{} failed - owner check failed ({} != {})",