WebDAV improvements: flush fix, RwLock recovery, expired lock cleanup, atomic set_times
P0 fixes: - flush(): add flushed flag, proper error logging, Drop warning for data loss - props_data RwLock: replace unwrap() with try_read/try_write recovery - PersistedLs: add is_expired() + cleanup_expired_locks() helper P1 improvements: - Props persistence via VFS (load_props/save_props/patch_props) - COPY/MOVE sync dead props (copy on COPY, move key on rename) - Atomic set_atime/set_mtime via filetime crate (no race condition) New files: - webdav_locks.rs: PersistedLs with lock persistence + expiry cleanup Tests: 288 passed, 0 failed
This commit is contained in:
@@ -28,11 +28,31 @@ pub struct VersionHistory {
|
||||
pub struct WebDavVersioning {
|
||||
db: Arc<RwLock<HashMap<String, Vec<u8>>>>,
|
||||
version_storage: PathBuf,
|
||||
index_path: PathBuf,
|
||||
}
|
||||
|
||||
impl WebDavVersioning {
|
||||
pub fn new(db: Arc<RwLock<HashMap<String, Vec<u8>>>>, version_storage: PathBuf) -> Self {
|
||||
Self { db, version_storage }
|
||||
pub fn new(version_storage: PathBuf) -> Self {
|
||||
let index_path = version_storage.join("version_index.json");
|
||||
let db = Arc::new(RwLock::new(HashMap::new()));
|
||||
|
||||
// Load persisted index from disk
|
||||
if index_path.exists() {
|
||||
if let Ok(json) = std::fs::read_to_string(&index_path) {
|
||||
if let Ok(map) = serde_json::from_str::<HashMap<String, Vec<u8>>>(&json) {
|
||||
*db.write().unwrap() = map;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Self { db, version_storage, index_path }
|
||||
}
|
||||
|
||||
fn save_index(&self) -> Result<(), VersionError> {
|
||||
let db = self.db.read().unwrap();
|
||||
let json = serde_json::to_string(&*db)?;
|
||||
std::fs::write(&self.index_path, json)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn create_version(
|
||||
@@ -71,9 +91,10 @@ impl WebDavVersioning {
|
||||
let value = serde_json::to_vec(&version_info)?;
|
||||
self.db.write().unwrap().insert(key, value);
|
||||
|
||||
let history_key = Self::history_key(file_path);
|
||||
self.update_version_history(file_path, &version_id)?;
|
||||
|
||||
self.save_index()?;
|
||||
|
||||
Ok(version_info)
|
||||
}
|
||||
|
||||
@@ -144,6 +165,8 @@ impl WebDavVersioning {
|
||||
|
||||
self.update_version_history(file_path, &new_version_id)?;
|
||||
|
||||
self.save_index()?;
|
||||
|
||||
Ok(new_version_info)
|
||||
}
|
||||
|
||||
@@ -165,6 +188,8 @@ impl WebDavVersioning {
|
||||
let current = self.get_current_version(file_path)?;
|
||||
self.update_version_history(file_path, ¤t.version_id)?;
|
||||
|
||||
self.save_index()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -249,14 +274,12 @@ impl From<serde_json::Error> for VersionError {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::sync::Arc;
|
||||
use tempfile::TempDir;
|
||||
|
||||
fn setup_versioning() -> (WebDavVersioning, TempDir) {
|
||||
let version_dir = TempDir::new().unwrap();
|
||||
|
||||
let db = Arc::new(RwLock::new(HashMap::new()));
|
||||
let versioning = WebDavVersioning::new(db, version_dir.path().to_path_buf());
|
||||
let versioning = WebDavVersioning::new(version_dir.path().to_path_buf());
|
||||
|
||||
(versioning, version_dir)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user