This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
/// Windows Cloud Filter API 平台适配器
|
||||
/// 仅在 windows-cfapi feature 启用时编译
|
||||
#[cfg(feature = "windows-cfapi")]
|
||||
use std::path::Path;
|
||||
#[cfg(feature = "windows-cfapi")]
|
||||
use std::sync::Arc;
|
||||
#[cfg(feature = "windows-cfapi")]
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
#[cfg(feature = "windows-cfapi")]
|
||||
use crate::api_client::ApiClient;
|
||||
#[cfg(feature = "windows-cfapi")]
|
||||
use crate::errors::Result;
|
||||
#[cfg(feature = "windows-cfapi")]
|
||||
use crate::models::SyncConfig;
|
||||
#[cfg(feature = "windows-cfapi")]
|
||||
use crate::sync_db::SyncDb;
|
||||
#[cfg(feature = "windows-cfapi")]
|
||||
use crate::worker::PlaceholderCreator;
|
||||
|
||||
#[cfg(feature = "windows-cfapi")]
|
||||
pub struct WcfPlatformAdapter {
|
||||
adapter: std::sync::Mutex<sync_windows::WindowsAdapter>,
|
||||
fetch_rx: std::sync::Mutex<Option<mpsc::Receiver<sync_windows::FetchDataRequest>>>,
|
||||
#[allow(dead_code)]
|
||||
db: Arc<SyncDb>,
|
||||
#[allow(dead_code)]
|
||||
api: Arc<ApiClient>,
|
||||
#[allow(dead_code)]
|
||||
config: SyncConfig,
|
||||
}
|
||||
|
||||
#[cfg(feature = "windows-cfapi")]
|
||||
impl WcfPlatformAdapter {
|
||||
pub fn new(
|
||||
db: Arc<SyncDb>,
|
||||
api: Arc<ApiClient>,
|
||||
config: SyncConfig,
|
||||
) -> anyhow::Result<Self> {
|
||||
let mut adapter = sync_windows::WindowsAdapter::new();
|
||||
|
||||
// 注册同步根目录
|
||||
adapter.register_sync_root(
|
||||
&config.local_root,
|
||||
"Cloudreve4",
|
||||
"1.0",
|
||||
)?;
|
||||
|
||||
// 连接同步根,注册回调
|
||||
adapter.connect_sync_root(&config.local_root)?;
|
||||
let fetch_rx = adapter.take_callback_receiver();
|
||||
|
||||
tracing::info!("WcfPlatformAdapter 初始化完成: {}", config.local_root.display());
|
||||
|
||||
Ok(Self {
|
||||
adapter: std::sync::Mutex::new(adapter),
|
||||
fetch_rx: std::sync::Mutex::new(fetch_rx),
|
||||
db,
|
||||
api,
|
||||
config,
|
||||
})
|
||||
}
|
||||
|
||||
/// 取走 FETCH_DATA 回调接收端(供 SyncEngine 持续同步消费)
|
||||
pub fn take_fetch_receiver(&self) -> Option<mpsc::Receiver<sync_windows::FetchDataRequest>> {
|
||||
self.fetch_rx.lock().unwrap().take()
|
||||
}
|
||||
|
||||
/// 创建占位符文件
|
||||
pub fn create_placeholder_for_remote(
|
||||
&self,
|
||||
base_dir: &Path,
|
||||
file_name: &str,
|
||||
file_size: u64,
|
||||
remote_uri: &str,
|
||||
remote_hash: Option<&str>,
|
||||
remote_mtime_ms: i64,
|
||||
) -> Result<()> {
|
||||
let file_identity = serde_json::to_vec(&serde_json::json!({
|
||||
"uri": remote_uri,
|
||||
"size": file_size,
|
||||
"hash": remote_hash.unwrap_or(""),
|
||||
"mtime_ms": remote_mtime_ms,
|
||||
})).unwrap_or_default();
|
||||
|
||||
self.adapter.lock().unwrap().create_single_placeholder(
|
||||
base_dir,
|
||||
file_name,
|
||||
file_size,
|
||||
&file_identity,
|
||||
).map_err(|e| crate::errors::SyncError::FileSystem(e.to_string()))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 水合文件(按需下载)
|
||||
pub fn hydrate_file(&self, local_path: &Path) -> Result<()> {
|
||||
self.adapter.lock().unwrap().hydrate_placeholder(local_path)
|
||||
.map_err(|e| crate::errors::SyncError::FileSystem(e.to_string()))
|
||||
}
|
||||
|
||||
/// 脱水文件(释放本地空间)
|
||||
pub fn dehydrate_file(&self, local_path: &Path) -> Result<()> {
|
||||
self.adapter.lock().unwrap().dehydrate_placeholder(local_path)
|
||||
.map_err(|e| crate::errors::SyncError::FileSystem(e.to_string()))
|
||||
}
|
||||
|
||||
/// 通过 CfExecute 将数据推送回 CFApi(内核层写入,绕过文件锁)
|
||||
pub fn fulfill_fetch_data(
|
||||
connection_key: i64,
|
||||
transfer_key: i64,
|
||||
data: &[u8],
|
||||
offset: i64,
|
||||
) -> Result<()> {
|
||||
sync_windows::WindowsAdapter::fulfill_fetch_data(connection_key, transfer_key, data, offset)
|
||||
.map_err(|e| crate::errors::SyncError::FileSystem(e.to_string()))
|
||||
}
|
||||
|
||||
/// 通过 CfExecute 报告水合失败
|
||||
pub fn reject_fetch_data(
|
||||
connection_key: i64,
|
||||
transfer_key: i64,
|
||||
) -> Result<()> {
|
||||
sync_windows::WindowsAdapter::reject_fetch_data(connection_key, transfer_key)
|
||||
.map_err(|e| crate::errors::SyncError::FileSystem(e.to_string()))
|
||||
}
|
||||
|
||||
/// 断开连接
|
||||
pub fn disconnect(&self) -> Result<()> {
|
||||
self.adapter.lock().unwrap().disconnect()
|
||||
.map_err(|e| crate::errors::SyncError::FileSystem(e.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "windows-cfapi")]
|
||||
#[async_trait::async_trait]
|
||||
impl PlaceholderCreator for WcfPlatformAdapter {
|
||||
async fn create_placeholder_file(
|
||||
&self,
|
||||
base_dir: &Path,
|
||||
file_name: String,
|
||||
file_size: u64,
|
||||
file_identity: &[u8],
|
||||
) -> Result<()> {
|
||||
self.adapter.lock().unwrap().create_single_placeholder(
|
||||
base_dir,
|
||||
&file_name,
|
||||
file_size,
|
||||
file_identity,
|
||||
).map_err(|e| crate::errors::SyncError::FileSystem(e.to_string()))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user