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

460 lines
16 KiB
Swift

import Foundation
public class FileLevelStorage {
// File Level Storage for MarkBaseFS
// No DriverKit Entitlement required
// Uses FileManager API for all storage operations
private let frameIndexTable: FrameIndexTable
private let fileManager = FileManager.default
// Multi-tier storage paths
private var nvmeTierPath: String = "/Volumes/MarkBaseFS_Test" // vdisk for POC
private var hddTierPath: String = "/Volumes/HDD_RAID"
private var objectStorageEndpoint: String = "http://localhost:9000"
// Object Storage Client
private var objectStorageClient: ObjectStorageClient?
// Performance tracking
private var writeSpeedMBps: Double = 0
private var readSpeedMBps: Double = 0
public init(frameIndexTable: FrameIndexTable) {
self.frameIndexTable = frameIndexTable
print("FileLevelStorage initializing...")
print(" - NVMe Tier (vdisk): \(nvmeTierPath)")
print(" - HDD Tier: \(hddTierPath)")
print(" - Object Storage: \(objectStorageEndpoint)")
// Initialize Object Storage Client
initializeObjectStorageClient()
}
private func initializeObjectStorageClient() {
let config = ObjectStorageConfig.minIODefault()
objectStorageClient = ObjectStorageClient(
endpoint: config.endpoint,
accessKey: config.accessKey,
secretKey: config.secretKey
)
print(" - Object Storage Client initialized")
}
// MARK: - vdisk Access Test
public func testVDiskAccess() {
print("\n=== FileLevelStorage: Multi-tier Storage Test ===")
// Test NVMe tier (vdisk)
testNVMeTier()
// Test HDD tier
testHDDTier()
// Test Object Storage tier
testObjectStorageTier()
// Test Multi-tier integration
testMultiTierIntegration()
print("\n=== Multi-tier Storage Test Complete ===")
}
private func testNVMeTier() {
print("\nTest: NVMe Tier (vdisk)")
testVDiskMount()
testFileOperations()
testFrameStorage()
testPerformance()
}
private func testHDDTier() {
print("\nTest: HDD Tier")
print(" - Checking HDD tier mount point: \(hddTierPath)")
if fileManager.fileExists(atPath: hddTierPath) {
print(" Result: ✅ SUCCESS - HDD tier mounted")
do {
let attributes = try fileManager.attributesOfFileSystem(forPath: hddTierPath)
if let totalSize = attributes[.systemSize] as? UInt64 {
let sizeGB = Double(totalSize) / (1024 * 1024 * 1024)
print(" Total Size: \(String(format: "%.2f", sizeGB)) GB")
}
} catch {
print(" ⚠️ Warning: Could not get file system attributes: \(error)")
}
} else {
print(" Result: ⚠️ WARNING - HDD tier not mounted")
print(" Note: HDD tier not available for POC testing")
}
}
private func testObjectStorageTier() {
print("\nTest: Object Storage Tier")
if let client = objectStorageClient {
client.testObjectOperations()
} else {
print(" Result: ⚠️ WARNING - Object Storage Client not initialized")
}
}
private func checkObjectStorageAvailable() -> Bool {
guard let client = objectStorageClient else {
return false
}
return client.testConnection()
}
private func testMultiTierIntegration() {
print("\nTest: Multi-tier Integration")
// Test tier selection logic
print(" - Testing tier selection logic...")
let videoId = "test_video_multi_tier"
let frameNumber: UInt64 = 0
// NVMe tier: hot frames (recently accessed)
print(" Tier for hot frame: \(getStorageTier(for: videoId, frameNumber: frameNumber, accessPattern: .hot))")
// HDD tier: cold frames (infrequently accessed)
print(" Tier for cold frame: \(getStorageTier(for: videoId, frameNumber: frameNumber, accessPattern: .cold))")
// Object Storage tier: archive frames (long-term storage)
print(" Tier for archive frame: \(getStorageTier(for: videoId, frameNumber: frameNumber, accessPattern: .archive))")
print(" - Multi-tier integration: ✅ SUCCESS")
}
private func testVDiskMount() {
print("Test 1: vdisk Mount Verification")
print(" - Checking vdisk mount point: \(nvmeTierPath)")
if fileManager.fileExists(atPath: nvmeTierPath) {
print(" Result: ✅ SUCCESS - vdisk mounted")
do {
let attributes = try fileManager.attributesOfFileSystem(forPath: nvmeTierPath)
if let totalSize = attributes[.systemSize] as? UInt64 {
let sizeGB = Double(totalSize) / (1024 * 1024 * 1024)
print(" Total Size: \(String(format: "%.2f", sizeGB)) GB")
}
if let freeSize = attributes[.systemFreeSize] as? UInt64 {
let freeGB = Double(freeSize) / (1024 * 1024 * 1024)
print(" Free Size: \(String(format: "%.2f", freeGB)) GB")
}
} catch {
print(" ⚠️ Warning: Could not get file system attributes: \(error)")
}
} else {
print(" Result: ❌ FAILED - vdisk not mounted")
}
}
private func testFileOperations() {
print("Test 2: File Operations")
let testFilePath = nvmeTierPath + "/markbase_test.txt"
let testContent = "MarkBaseFS File Level Storage Test\n".data(using: .utf8)!
// Write test
print(" - Write test")
do {
fileManager.createFile(atPath: testFilePath, contents: testContent, attributes: nil)
print(" Result: ✅ SUCCESS - File created")
} catch {
print(" Result: ❌ FAILED - \(error)")
}
// Read test
print(" - Read test")
do {
let readContent = fileManager.contents(atPath: testFilePath)
if readContent == testContent {
print(" Result: ✅ SUCCESS - File read correctly")
} else {
print(" Result: ❌ FAILED - Content mismatch")
}
} catch {
print(" Result: ❌ FAILED - \(error)")
}
// Delete test
print(" - Delete test")
do {
try fileManager.removeItem(atPath: testFilePath)
print(" Result: ✅ SUCCESS - File deleted")
} catch {
print(" Result: ❌ FAILED - \(error)")
}
}
private func testFrameStorage() {
print("Test 3: Frame Storage Integration")
// Create test frames
let testFrames = createTestFrames(count: 10)
print(" - Created \(testFrames.count) test frames")
// Insert frames to Frame Index Table
print(" - Inserting frames to Frame Index Table...")
for (index, frame) in testFrames.enumerated() {
let videoId = "test_video_\(index)"
let frameIndex = index
let frameFile = nvmeTierPath + "/frame_\(index).bin"
let frameOffset: Int = 0
let frameSize: Int = 1024
let frameChecksum = "test_checksum_\(index)"
frameIndexTable.insertFrame(
frameId: UUID().uuidString,
videoId: videoId,
frameIndex: frameIndex,
frameFile: frameFile,
frameOffset: frameOffset,
frameSize: frameSize,
frameChecksum: frameChecksum
)
print(" Inserted frame \(index): \(frameFile)")
}
// Verify frames
print(" - Verifying frames in Frame Index Table...")
let retrievedFrames = frameIndexTable.getFramesForVideo(videoId: "test_video_0")
if retrievedFrames.count == 10 {
print(" Result: ✅ SUCCESS - All frames retrieved")
} else {
print(" Result: ❌ FAILED - Expected 10 frames, got \(retrievedFrames.count)")
}
}
private func testPerformance() {
print("Test 4: Performance Test")
let performanceFilePath = nvmeTierPath + "/performance_test.bin"
// Write performance test
print(" - Write performance test")
let writeData = Data(count: 1024 * 1024 * 100) // 100 MB
let writeStart = Date()
do {
fileManager.createFile(atPath: performanceFilePath, contents: writeData, attributes: nil)
let writeEnd = Date()
let writeDuration = writeEnd.timeIntervalSince(writeStart)
writeSpeedMBps = 100.0 / writeDuration
print(" Write Speed: \(String(format: "%.2f", writeSpeedMBps)) MB/s")
print(" Result: ✅ SUCCESS")
} catch {
print(" Result: ❌ FAILED - \(error)")
}
// Read performance test
print(" - Read performance test")
let readStart = Date()
do {
let readData = fileManager.contents(atPath: performanceFilePath)
let readEnd = Date()
let readDuration = readEnd.timeIntervalSince(readStart)
let dataSizeMB = Double(readData?.count ?? 0) / (1024 * 1024)
readSpeedMBps = dataSizeMB / readDuration
print(" Read Speed: \(String(format: "%.2f", readSpeedMBps)) MB/s")
print(" Result: ✅ SUCCESS")
} catch {
print(" Result: ❌ FAILED - \(error)")
}
// Cleanup
do {
try fileManager.removeItem(atPath: performanceFilePath)
} catch {
print(" ⚠️ Warning: Could not cleanup performance test file")
}
// Performance summary
print(" Performance Summary:")
print(" Write Speed: \(String(format: "%.2f", writeSpeedMBps)) MB/s")
print(" Read Speed: \(String(format: "%.2f", readSpeedMBps)) MB/s")
if writeSpeedMBps > 100 && readSpeedMBps > 100 {
print(" ✅ Performance meets POC requirements")
} else {
print(" ⚠️ Performance below POC requirements")
}
}
// MARK: - Frame Operations
public func storeFrame(videoId: String, frameNumber: UInt64, data: Data) -> Bool {
let filePath = nvmeTierPath + "/videos/\(videoId)/frame_\(frameNumber).bin"
// Create directory if needed
let dirPath = nvmeTierPath + "/videos/\(videoId)"
do {
try fileManager.createDirectory(atPath: dirPath, withIntermediateDirectories: true)
} catch {
print("Error creating directory: \(error)")
return false
}
// Write frame data
do {
fileManager.createFile(atPath: filePath, contents: data, attributes: nil)
// Insert to Frame Index Table
frameIndexTable.insertFrame(
frameId: UUID().uuidString,
videoId: videoId,
frameIndex: Int(frameNumber),
frameFile: filePath,
frameOffset: 0,
frameSize: data.count,
frameChecksum: "stored_checksum"
)
return true
} catch {
print("Error storing frame: \(error)")
return false
}
}
public func retrieveFrame(videoId: String, frameNumber: UInt64) -> Data? {
// Get frame from Frame Index Table
let frames = frameIndexTable.getFramesForVideo(videoId: videoId)
for frame in frames {
if let frameIndex = frame["frame_index"] as? Int, frameIndex == Int(frameNumber) {
// Read frame data from file
if let frameFile = frame["frame_file"] as? String {
do {
let data = fileManager.contents(atPath: frameFile)
return data
} catch {
print("Error retrieving frame: \(error)")
return nil
}
}
}
}
return nil
}
public func deleteFrame(videoId: String, frameNumber: UInt64) -> Bool {
// Get frame from Frame Index Table
let frames = frameIndexTable.getFramesForVideo(videoId: videoId)
for frame in frames {
if let frameIndex = frame["frame_index"] as? Int, frameIndex == Int(frameNumber) {
// Delete frame file
if let frameFile = frame["frame_file"] as? String, let frameId = frame["frame_id"] as? String {
do {
try fileManager.removeItem(atPath: frameFile)
// Delete from Frame Index Table
frameIndexTable.deleteFrame(frameId: frameId)
return true
} catch {
print("Error deleting frame: \(error)")
return false
}
}
}
}
return false
}
// MARK: - Multi-tier Storage
public enum AccessPattern {
case hot // Recently accessed, high performance required
case cold // Infrequently accessed, moderate performance
case archive // Long-term storage, low performance acceptable
}
public func getStorageTier(for videoId: String, frameNumber: UInt64, accessPattern: AccessPattern = .hot) -> StorageTier {
// Determine storage tier based on access pattern
switch accessPattern {
case .hot:
return .nvme // NVMe tier for hot frames
case .cold:
return .hdd // HDD tier for cold frames
case .archive:
return .objectStorage // Object Storage tier for archive frames
}
}
public func getStorageTier(for videoId: String) -> StorageTier {
// Legacy function for compatibility
return getStorageTier(for: videoId, frameNumber: 0, accessPattern: .hot)
}
public func migrateToTier(videoId: String, targetTier: StorageTier) -> Bool {
// Migrate video data to target tier
// For POC, migration is not implemented
print("Migration to \(targetTier) not implemented for POC")
return false
}
// MARK: - Helper Functions
private func createTestFrames(count: Int) -> [Data] {
var frames: [Data] = []
for i in 0..<count {
let frameData = Data(count: 1024) // 1 KB test frame
frames.append(frameData)
}
return frames
}
public func getStorageStats() -> StorageStats {
let objectStorageAvailable = checkObjectStorageAvailable()
return StorageStats(
writeSpeedMBps: writeSpeedMBps,
readSpeedMBps: readSpeedMBps,
nvmeTierAvailable: fileManager.fileExists(atPath: nvmeTierPath),
hddTierAvailable: fileManager.fileExists(atPath: hddTierPath),
objectStorageAvailable: objectStorageAvailable
)
}
}
// MARK: - Supporting Types
public enum StorageTier {
case nvme
case hdd
case objectStorage
}
public struct StorageStats {
let writeSpeedMBps: Double
let readSpeedMBps: Double
let nvmeTierAvailable: Bool
let hddTierAvailable: Bool
let objectStorageAvailable: Bool
}