Files
markbase/filetree-sled/src/migrate.rs
Warren 1300a4e223
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
MarkBase架构升级:Multi-Volume Virtual Tree + Dual-View Management + Git Remote修正
核心功能:
-  Categories/Series双视图管理(category_view.rs + import_markdown.rs)
-  FUSE Multi-Volume支持(tree_type参数)
-  SSH/SFTP/SCP/rsync协议完整实现(4042行)
-  NFS/SMB Module Phase 1-3完成
-  Archive Module Phase 1-4完成(2916行)
-  Download Center API完整实现
-  S3兼容API实现(560行)

Git配置修正:
-  删除错误origin(gitea.momentry.ddns.net)
-  删除m5max128(指向机器名)
-  设置origin = m5max128gitea.momentry.ddns.net/admin/markbase
-  设置m4minigitea = m4minigitea.momentry.ddns.net/warren/markbase

数据清理:
-  删除38个临时SQLite(保留accusys.sqlite、demo.sqlite)
-  删除.bak、test_*.bin、调试脚本等临时文件
-  删除临时目录(build/、download files/、raid_test/等)
-  更新.gitignore排除临时文件

架构优化:
- 52个文件修改,2434行新增,4739行删除
- Workspace成员整合(16个crate)
- 数据库状态:accusys.sqlite保留(主demo测试)

远程同步:
-  准备推送到m5max128gitea(远程Gitea)
-  准备推送到m4minigitea(本地Gitea)
2026-06-12 12:59:54 +08:00

131 lines
4.7 KiB
Rust

use anyhow::{Context, Result};
use filetree_sled::FileTreeSled;
use rusqlite::Connection;
use std::time::Instant;
fn main() -> Result<()> {
println!("=== SQLite → Sled Migration Test ===\n");
let sqlite_path = "data/users/warren.sqlite";
let sled_path = "data/users_sled/warren.sled";
println!("Step 1: Open SQLite database...");
let conn =
Connection::open(sqlite_path).with_context(|| format!("Failed to open {}", sqlite_path))?;
let node_count: i64 =
conn.query_row("SELECT COUNT(*) FROM file_nodes", [], |row| row.get(0))?;
println!(" ✓ SQLite nodes count: {}", node_count);
println!("\nStep 2: Read all nodes from SQLite...");
let start = Instant::now();
let mut stmt = conn.prepare(
"SELECT node_id, label, aliases_json, file_uuid, sha256, parent_id, children_json,
node_type, icon, color, bg_color, file_size, registered_at,
created_at, updated_at, sort_order
FROM file_nodes",
)?;
let nodes: Vec<filetree_sled::FileNode> = stmt
.query_map([], |row| {
let children_json: String = row.get(6)?;
let children: Vec<String> = serde_json::from_str(&children_json).unwrap_or_default();
let node_type_str: String = row.get(7)?;
Ok(filetree_sled::FileNode {
node_id: row.get(0)?,
label: row.get(1)?,
aliases: filetree_sled::Aliases::from_json(&row.get::<_, String>(2)?),
file_uuid: row.get(3)?,
sha256: row.get(4)?,
parent_id: row.get(5)?,
children,
node_type: std::str::FromStr::from_str(&node_type_str)
.unwrap_or(filetree_sled::NodeType::Folder),
icon: row.get(8)?,
color: row.get(9)?,
bg_color: row.get(10)?,
file_size: row.get(11)?,
registered_at: row.get(12)?,
created_at: row.get(13)?,
updated_at: row.get(14)?,
sort_order: row.get(15)?,
})
})?
.collect::<Result<Vec<_>, _>>()?;
let read_time = start.elapsed();
let read_throughput = nodes.len() as f64 / read_time.as_secs_f64();
println!(" ✓ Read time: {:?}", read_time);
println!(" ✓ Nodes read: {}", nodes.len());
println!(" ✓ Throughput: {:.2} nodes/sec", read_throughput);
println!("\nStep 3: Initialize Sled database...");
let start = Instant::now();
let sled_tree = FileTreeSled::init_user_db("warren")?;
let init_time = start.elapsed();
println!(" ✓ Init time: {:?}", init_time);
println!("\nStep 4: Import nodes to Sled (batch insert)...");
let start = Instant::now();
sled_tree.insert_node_batch(&nodes)?;
let import_time = start.elapsed();
let import_throughput = nodes.len() as f64 / import_time.as_secs_f64();
println!(" ✓ Import time: {:?}", import_time);
println!(" ✓ Throughput: {:.2} nodes/sec", import_throughput);
println!("\nStep 5: Verify import...");
let sled_count = sled_tree.count_nodes()?;
println!(" ✓ Sled nodes count: {}", sled_count);
println!(" ✓ Match: {}", sled_count == nodes.len());
println!("\nStep 6: Query test (1000 random nodes)...");
let test_nodes = &nodes[..1000.min(nodes.len())];
let start = Instant::now();
for node in test_nodes {
let _ = sled_tree.get_node(&node.node_id)?;
}
let query_time = start.elapsed();
let query_latency = query_time.as_nanos() as f64 / test_nodes.len() as f64;
println!(" ✓ Query time: {:?}", query_time);
println!(" ✓ Average latency: {:.2} ns", query_latency);
println!("\nStep 7: Database size comparison...");
let sqlite_size = std::fs::metadata(sqlite_path)?.len();
let sled_size = std::fs::metadata(sled_path)?.len();
println!(
" ✓ SQLite size: {} bytes ({:.2} MB)",
sqlite_size,
sqlite_size as f64 / 1024.0 / 1024.0
);
println!(
" ✓ Sled size: {} bytes ({:.2} MB)",
sled_size,
sled_size as f64 / 1024.0 / 1024.0
);
println!(
" ✓ Size ratio: {:.2}x",
sled_size as f64 / sqlite_size as f64
);
println!("\n=== Migration Summary ===");
println!("SQLite nodes: {}", node_count);
println!("Imported nodes: {}", nodes.len());
println!("Import throughput: {:.2} nodes/sec", import_throughput);
println!("Query latency: {:.2} ns", query_latency);
println!("Size ratio: {:.2}x", sled_size as f64 / sqlite_size as f64);
println!("\nStep 8: Cleanup...");
std::fs::remove_dir_all(sled_path)?;
println!(" ✓ Test database removed");
println!("\n✅ Migration test completed successfully!");
Ok(())
}