# HG changeset patch # User sam # Date 1712418510 -25200 # Node ID 0c02ca5de8e634795353e2e707749260eef649d0 # Parent 4e487f06378b45f6cea1436a50dddf66143609ad do: intermediate save before doing shit from scratch diff -r 4e487f06378b -r 0c02ca5de8e6 semicongine/storage.nim --- a/semicongine/storage.nim Sat Apr 06 21:26:31 2024 +0700 +++ b/semicongine/storage.nim Sat Apr 06 22:48:30 2024 +0700 @@ -8,8 +8,6 @@ import ./core const STORAGE_NAME = Path("storage.db") -const KEY_VALUE_TABLE_NAME = "shelf" -const KILL_SIGNAL_KEY = "__semicongine__kill_worker" type StorageType* = enum @@ -22,9 +20,9 @@ KillWorker Storage*[T] = object storageType: StorageType - keyChannel: Channel[(StorageOperation, string)] # false is read, true is write - dataChannel: Channel[T] - thread: Thread[(ptr Channel[string], ptr Channel[T])] + keyChannel: ptr Channel[(StorageOperation, string)] # false is read, true is write + dataChannel: ptr Channel[T] + thread: Thread[tuple[storageType: StorageType, keyChannel: ptr Channel[(StorageOperation, string)], dataChannel: ptr Channel[T]]] proc path(storageType: StorageType): Path = case storageType: @@ -34,19 +32,22 @@ Path(getDataDir()) / Path(AppName()) / STORAGE_NAME proc openDb(storageType: StorageType): DbConn = + const KEY_VALUE_TABLE_NAME = "shelf" result = open(string(storageType.path), "", "", "") result.exec(sql(&"""CREATE TABLE IF NOT EXISTS {KEY_VALUE_TABLE_NAME} ( key TEXT NOT NULL UNIQUE, - value TEXT NOT NULL, + value TEXT NOT NULL )""")) proc store[T](db: DbConn, key: string, value: T) = - db.exec(sql(f"""INSERT INTO {KEY_VALUE_TABLE_NAME} VALUES(?, ?) + const KEY_VALUE_TABLE_NAME = "shelf" + db.exec(sql(&"""INSERT INTO {KEY_VALUE_TABLE_NAME} VALUES(?, ?) ON CONFLICT(key) DO UPDATE SET value=excluded.value """), key, $$value) proc load[T](db: DbConn, key: string, default = default(T)): T = - let dbResult = db.getValue(sql(f"""SELECT value FROM {KEY_VALUE_TABLE_NAME} WHERE key = ? """), key) + const KEY_VALUE_TABLE_NAME = "shelf" + let dbResult = db.getValue(sql(&"""SELECT value FROM {KEY_VALUE_TABLE_NAME} WHERE key = ? """), key) if dbResult == "": return default return to[T](dbResult) @@ -54,35 +55,40 @@ proc storageWorker[T](params: tuple[storageType: StorageType, keyChannel: ptr Channel[(StorageOperation, string)], dataChannel: ptr Channel[T]]) = var db = params.storageType.openDb() defer: db.close() - var key: (string, bool) - while key[0] != KILL_SIGNAL_KEY: + var key: (StorageOperation, string) + while true: key = params.keyChannel[].recv() - case key: - of Read: params.dataChannel[].send(db.load(key)) - of Write: db.store(key, params.dataChannel[].recv()) + case key[0]: + of Read: params.dataChannel[].send(load[T](db, key[1])) + of Write: store(db, key[1], params.dataChannel[].recv()) of KillWorker: break proc openStorage*[T](storageType: StorageType): Storage[T] = - result.keyChannel = cast[ptr Channel[(string, bool)]](allocShared0(sizeof(Channel[(string, bool)]))) + result.keyChannel = cast[ptr Channel[(StorageOperation, string)]](allocShared0(sizeof(Channel[(StorageOperation, string)]))) result.keyChannel[].open() result.dataChannel = cast[ptr Channel[T]](allocShared0(sizeof(Channel[T]))) result.dataChannel[].open() - createThread(result.thread, storageWorker, (storageType, result.keyChannel, result.dataChannel)) + createThread(result.thread, storageWorker[T], (storageType, result.keyChannel, result.dataChannel)) -proc get[T](storage: Storage[T], key: string): Channel[T] = +proc get*[T](storage: Storage[T], key: string): Channel[T] = storage.keyChannel.send((Read, key)) return storage.dataChannel[] -proc set[T](storage: Storage[T], key: string, value: T) = +proc set*[T](storage: Storage[T], key: string, value: T) = storage.keyChannel.send((Write, key)) storage.dataChannel.send(value) +proc purge*[T](storage: var Storage[T]) = + storage.closeStorage() + storage.path().string.removeFile() + + proc closeStorage*[T](storage: var Storage[T]) = storage.keyChannel[].send((KillWorker, "")) storage.thread.joinThread() storage.keyChannel[].close() - storage.deallocShared(storage.keyChannel) + deallocShared(storage.keyChannel) storage.dataChannel[].close() - storage.deallocShared(storage.dataChannel) + deallocShared(storage.dataChannel)