Files
markbase/MarkBaseFS/MarkBaseFS/FileTreeImporter.swift
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

360 lines
12 KiB
Swift

import Foundation
import SQLite3
public class FileTreeImporter {
// MarkBase FileTree Importer
// Imports warren.sqlite file_nodes to MarkBaseFS Frame Index Table
// Maps file_nodes frame_records
private var markBaseDB: OpaquePointer?
private var markBaseFSDB: OpaquePointer?
private let markBaseDBPath: String = "/Users/accusys/markbase/data/users/warren.sqlite"
private let markBaseFSDBPath: String
private var importedNodes: Int = 0
private var importedFiles: Int = 0
private var importedFolders: Int = 0
public init(markBaseFSDBPath: String) {
self.markBaseFSDBPath = markBaseFSDBPath
print("FileTreeImporter initializing...")
print(" - MarkBase DB: \(markBaseDBPath)")
print(" - MarkBaseFS DB: \(markBaseFSDBPath)")
}
public func importFileTree() -> Bool {
print("\n=== Importing MarkBase FileTree to MarkBaseFS ===")
// Open databases
if !openMarkBaseDB() {
return false
}
if !openMarkBaseFSDB() {
closeMarkBaseDB()
return false
}
// Import file_nodes
importFileNodes()
// Import file_registry
importFileRegistry()
// Import file_locations
importFileLocations()
// Report results
reportImportResults()
// Close databases
closeMarkBaseDB()
closeMarkBaseFSDB()
return true
}
// MARK: - Database Operations
private func openMarkBaseDB() -> Bool {
if sqlite3_open(markBaseDBPath, &markBaseDB) != SQLITE_OK {
print("Error opening MarkBase database: \(markBaseDBPath)")
return false
}
print("MarkBase database opened successfully")
return true
}
private func openMarkBaseFSDB() -> Bool {
if sqlite3_open(markBaseFSDBPath, &markBaseFSDB) != SQLITE_OK {
print("Error opening MarkBaseFS database: \(markBaseFSDBPath)")
return false
}
print("MarkBaseFS database opened successfully")
return true
}
private func closeMarkBaseDB() {
if markBaseDB != nil {
sqlite3_close(markBaseDB)
markBaseDB = nil
}
}
private func closeMarkBaseFSDB() {
if markBaseFSDB != nil {
sqlite3_close(markBaseFSDB)
markBaseFSDB = nil
}
}
// MARK: - Import Operations
private func importFileNodes() {
print("\nImporting file_nodes...")
let selectQuery = "SELECT node_id, label, parent_id, node_type, file_size, sha256 FROM file_nodes;"
var statement: OpaquePointer?
if sqlite3_prepare_v2(markBaseDB, selectQuery, -1, &statement, nil) == SQLITE_OK {
while sqlite3_step(statement) == SQLITE_ROW {
let nodeId = String(cString: sqlite3_column_text(statement, 0))
let label = String(cString: sqlite3_column_text(statement, 1))
// Handle NULL parent_id (Home folder has no parent)
let parentId: String
if let parentIdPtr = sqlite3_column_text(statement, 2) {
parentId = String(cString: parentIdPtr)
} else {
parentId = "root"
}
let nodeType = String(cString: sqlite3_column_text(statement, 3))
let fileSize = sqlite3_column_int(statement, 4)
// Handle NULL sha256 (folders don't have sha256)
let sha256: String
if let sha256Ptr = sqlite3_column_text(statement, 5) {
sha256 = String(cString: sha256Ptr)
} else {
sha256 = ""
}
// Insert to MarkBaseFS frame_records
insertToFrameRecords(
nodeId: nodeId,
label: label,
parentId: parentId,
nodeType: nodeType,
fileSize: Int(fileSize),
sha256: sha256
)
importedNodes += 1
if nodeType == "folder" {
importedFolders += 1
} else {
importedFiles += 1
}
if importedNodes % 1000 == 0 {
print(" - Imported \(importedNodes) nodes...")
}
}
}
sqlite3_finalize(statement)
print("file_nodes import complete: \(importedNodes) nodes")
}
private func importFileRegistry() {
print("\nImporting file_registry...")
let selectQuery = "SELECT file_uuid, original_name, file_size, file_type FROM file_registry;"
var statement: OpaquePointer?
var registryCount: Int = 0
if sqlite3_prepare_v2(markBaseDB, selectQuery, -1, &statement, nil) == SQLITE_OK {
while sqlite3_step(statement) == SQLITE_ROW {
let fileUuid = String(cString: sqlite3_column_text(statement, 0))
let originalName = String(cString: sqlite3_column_text(statement, 1))
let fileSize = sqlite3_column_int(statement, 2)
let fileType = String(cString: sqlite3_column_text(statement, 3))
// Insert to video_metadata (using file_uuid as video_id)
insertToVideoMetadata(
videoId: fileUuid,
videoName: originalName,
fileSize: Int(fileSize),
fileType: fileType
)
registryCount += 1
}
}
sqlite3_finalize(statement)
print("file_registry import complete: \(registryCount) files")
}
private func importFileLocations() {
print("\nImporting file_locations...")
let selectQuery = "SELECT file_uuid, location, label FROM file_locations;"
var statement: OpaquePointer?
var locationCount: Int = 0
if sqlite3_prepare_v2(markBaseDB, selectQuery, -1, &statement, nil) == SQLITE_OK {
while sqlite3_step(statement) == SQLITE_ROW {
let fileUuid = String(cString: sqlite3_column_text(statement, 0))
let location = String(cString: sqlite3_column_text(statement, 1))
let label = String(cString: sqlite3_column_text(statement, 2))
// Store location as frame_file path
updateFrameLocation(fileUuid: fileUuid, location: location)
locationCount += 1
}
}
sqlite3_finalize(statement)
print("file_locations import complete: \(locationCount) locations")
}
// MARK: - Insert Operations
private func insertToFrameRecords(nodeId: String, label: String, parentId: String, nodeType: String, fileSize: Int, sha256: String) {
let insertQuery = """
INSERT INTO frame_records (frame_id, video_id, frame_index, frame_file, frame_offset, frame_size, frame_checksum)
VALUES (?, ?, ?, ?, ?, ?, ?);
"""
var statement: OpaquePointer?
if sqlite3_prepare_v2(markBaseFSDB, insertQuery, -1, &statement, nil) == SQLITE_OK {
// frame_id = node_id
sqlite3_bind_text(statement, 1, (nodeId as NSString).utf8String, -1, nil)
// video_id = parent_id (treating parent folder as video)
sqlite3_bind_text(statement, 2, (parentId as NSString).utf8String, -1, nil)
// frame_index = 0 (all nodes are frame 0 for now)
sqlite3_bind_int(statement, 3, 0)
// frame_file = label (filename)
sqlite3_bind_text(statement, 4, (label as NSString).utf8String, -1, nil)
// frame_offset = 0
sqlite3_bind_int(statement, 5, 0)
// frame_size = file_size
sqlite3_bind_int(statement, 6, Int32(fileSize))
// frame_checksum = sha256
sqlite3_bind_text(statement, 7, (sha256 as NSString).utf8String, -1, nil)
if sqlite3_step(statement) != SQLITE_DONE {
print("Error inserting frame_record: \(nodeId)")
}
}
sqlite3_finalize(statement)
}
private func insertToVideoMetadata(videoId: String, videoName: String, fileSize: Int, fileType: String) {
let insertQuery = """
INSERT INTO video_metadata (video_id, video_name, total_frames)
VALUES (?, ?, ?);
"""
var statement: OpaquePointer?
if sqlite3_prepare_v2(markBaseFSDB, insertQuery, -1, &statement, nil) == SQLITE_OK {
sqlite3_bind_text(statement, 1, (videoId as NSString).utf8String, -1, nil)
sqlite3_bind_text(statement, 2, (videoName as NSString).utf8String, -1, nil)
sqlite3_bind_int(statement, 3, 1) // total_frames = 1
sqlite3_step(statement)
}
sqlite3_finalize(statement)
}
private func updateFrameLocation(fileUuid: String, location: String) {
let updateQuery = """
UPDATE frame_records SET frame_file = ? WHERE frame_id = ?;
"""
var statement: OpaquePointer?
if sqlite3_prepare_v2(markBaseFSDB, updateQuery, -1, &statement, nil) == SQLITE_OK {
sqlite3_bind_text(statement, 1, (location as NSString).utf8String, -1, nil)
sqlite3_bind_text(statement, 2, (fileUuid as NSString).utf8String, -1, nil)
sqlite3_step(statement)
}
sqlite3_finalize(statement)
}
// MARK: - Report
private func reportImportResults() {
print("\n=== Import Results ===")
print(" - Total nodes imported: \(importedNodes)")
print(" - Folders imported: \(importedFolders)")
print(" - Files imported: \(importedFiles)")
print(" - Success rate: \(String(format: "%.1f", Double(importedNodes) / Double(importedNodes + importedFiles) * 100))%")
print("\n=== Import Complete ===")
}
// MARK: - Test
public func testImport() {
print("\n=== FileTreeImporter Test ===")
// Test 1: Check MarkBase database
print("Test 1: Check MarkBase database")
if openMarkBaseDB() {
let countQuery = "SELECT COUNT(*) FROM file_nodes;"
var statement: OpaquePointer?
if sqlite3_prepare_v2(markBaseDB, countQuery, -1, &statement, nil) == SQLITE_OK {
if sqlite3_step(statement) == SQLITE_ROW {
let count = sqlite3_column_int(statement, 0)
print(" - file_nodes count: \(count)")
print(" - Result: ✅ SUCCESS")
}
}
sqlite3_finalize(statement)
closeMarkBaseDB()
}
// Test 2: Import test
print("\nTest 2: Import test")
let testDBPath = "/tmp/test_import.sqlite"
// Create test database
if sqlite3_open(testDBPath, &markBaseFSDB) == SQLITE_OK {
// Create tables
let createTableQuery = """
CREATE TABLE IF NOT EXISTS frame_records (
frame_id TEXT PRIMARY KEY,
video_id TEXT,
frame_index INTEGER,
frame_file TEXT,
frame_offset INTEGER,
frame_size INTEGER,
frame_checksum TEXT
);
"""
sqlite3_exec(markBaseFSDB, createTableQuery, nil, nil, nil)
print(" - Test database created")
print(" - Result: ✅ SUCCESS")
sqlite3_close(markBaseFSDB)
markBaseFSDB = nil
}
print("\n=== FileTreeImporter Test Complete ===")
}
}