fix(cloud-files): Platzhalter nicht als lokale Aenderung hochladen + Logging
Ursache des "voll gesynct"-Problems: der notify-Watcher feuerte auf die cfapi-Platzhalter, die wir selbst beim Aktivieren angelegt haben. Der sync_loop hat die dann als lokale Aenderung hochgeladen, was implizit die Hydration ausgeloest hat. Ergebnis: keine On-Demand-Platzhalter, sondern voller Sync. - is_cfapi_placeholder() prueft FILE_ATTRIBUTE_OFFLINE / RECALL_ON_DATA_ACCESS / RECALL_ON_OPEN - solche Dateien werden beim Upload uebersprungen - Log-Datei liegt jetzt NEBEN dem Mount (nicht drin), damit sie nicht selbst als Cloud-Datei behandelt wird - FETCH_DATA loggt jetzt auch Success, damit man sieht dass der Callback ueberhaupt feuert Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
be121190b3
commit
601e0741b1
|
|
@ -151,6 +151,28 @@ async fn upload_local_change(
|
|||
if !path.is_file() {
|
||||
return Ok(());
|
||||
}
|
||||
// cfapi-Platzhalter oder gerade hydrierende Dateien NICHT hochladen -
|
||||
// sonst wird jede Wolken-Datei sofort komplett gesynct und wir haben
|
||||
// keinen On-Demand-Modus mehr.
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if super::windows::is_cfapi_placeholder(path) {
|
||||
super::windows::log_msg(
|
||||
&cfg.mount_point,
|
||||
&format!("skip upload (placeholder): {}", path.display()),
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
// Eigene Log-Datei nicht mit hochladen.
|
||||
if path
|
||||
.file_name()
|
||||
.and_then(|n| n.to_str())
|
||||
.map(|n| n.starts_with(".minicloud-"))
|
||||
.unwrap_or(false)
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
// Relativer Pfad im Mount = Ziel-Pfad auf Server
|
||||
let rel = path
|
||||
.strip_prefix(&cfg.mount_point)
|
||||
|
|
|
|||
|
|
@ -171,25 +171,60 @@ unsafe extern "system" fn on_fetch_data(
|
|||
// HTTPS-Download im separaten Thread (Callback darf nicht blockieren).
|
||||
let ctx = ctx_snapshot();
|
||||
std::thread::spawn(move || {
|
||||
if let Err(e) = transfer_range(connection_key, transfer_key, file_id, offset, length, &ctx)
|
||||
{
|
||||
log_err(&ctx.mount_point, &format!(
|
||||
"fetch file_id={file_id} offset={offset} len={length} FAILED: {e}"
|
||||
));
|
||||
// Garantiert Fehler-Completion, damit Windows nicht in Timeout laeuft.
|
||||
let _ = complete_transfer(connection_key, transfer_key, None, offset, length);
|
||||
log_msg(&ctx.mount_point, &format!(
|
||||
"FETCH_DATA file_id={file_id} offset={offset} len={length}"
|
||||
));
|
||||
match transfer_range(connection_key, transfer_key, file_id, offset, length, &ctx) {
|
||||
Ok(()) => log_msg(&ctx.mount_point, &format!(
|
||||
"fetch file_id={file_id} OK"
|
||||
)),
|
||||
Err(e) => {
|
||||
log_err(&ctx.mount_point, &format!(
|
||||
"fetch file_id={file_id} offset={offset} len={length} FAILED: {e}"
|
||||
));
|
||||
// Garantiert Fehler-Completion, damit Windows nicht in Timeout laeuft.
|
||||
let _ = complete_transfer(connection_key, transfer_key, None, offset, length);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn log_err(mount: &Path, msg: &str) {
|
||||
pub fn log_msg(mount: &Path, msg: &str) {
|
||||
use std::io::Write;
|
||||
let log = mount.join(".minicloud-cloudfiles.log");
|
||||
// Log-Datei NEBEN den Mount, damit sie nicht selbst als Platzhalter
|
||||
// behandelt wird.
|
||||
let log = mount
|
||||
.parent()
|
||||
.map(|p| p.join(".minicloud-cloudfiles.log"))
|
||||
.unwrap_or_else(|| PathBuf::from(".minicloud-cloudfiles.log"));
|
||||
if let Ok(mut f) = std::fs::OpenOptions::new().create(true).append(true).open(&log) {
|
||||
let _ = writeln!(f, "[{}] {}", chrono::Utc::now().to_rfc3339(), msg);
|
||||
}
|
||||
}
|
||||
|
||||
fn log_err(mount: &Path, msg: &str) {
|
||||
log_msg(mount, msg);
|
||||
}
|
||||
|
||||
/// True wenn die Datei ein cfapi-Platzhalter ist (noch nicht hydriert)
|
||||
/// oder gerade vom Cloud-Filter verwaltet wird. Fuer solche Dateien
|
||||
/// duerfen wir KEINEN Upload ausloesen, sonst verwandelt der Sync-Loop
|
||||
/// jeden Platzhalter sofort in eine vollstaendig lokale Datei.
|
||||
pub fn is_cfapi_placeholder(path: &Path) -> bool {
|
||||
use windows::Win32::Storage::FileSystem::GetFileAttributesW;
|
||||
let Ok(w) = U16CString::from_str(path.to_string_lossy().as_ref()) else {
|
||||
return false;
|
||||
};
|
||||
let attrs = unsafe { GetFileAttributesW(PCWSTR(w.as_ptr())) };
|
||||
if attrs == u32::MAX {
|
||||
return false;
|
||||
}
|
||||
// FILE_ATTRIBUTE_OFFLINE (0x1000) oder
|
||||
// FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS (0x400000) oder
|
||||
// FILE_ATTRIBUTE_RECALL_ON_OPEN (0x40000)
|
||||
(attrs & 0x0040_1000) != 0 || (attrs & 0x0004_0000) != 0
|
||||
}
|
||||
|
||||
fn transfer_range(
|
||||
connection_key: CF::CF_CONNECTION_KEY,
|
||||
transfer_key: i64,
|
||||
|
|
|
|||
Loading…
Reference in New Issue