diff --git a/lib/db/sqlite/firo_cache.dart b/lib/db/sqlite/firo_cache.dart index 7197690a8..543b63557 100644 --- a/lib/db/sqlite/firo_cache.dart +++ b/lib/db/sqlite/firo_cache.dart @@ -15,8 +15,8 @@ import '../../utilities/stack_file_system.dart'; part 'firo_cache_coordinator.dart'; part 'firo_cache_reader.dart'; -part 'firo_cache_writer.dart'; part 'firo_cache_worker.dart'; +part 'firo_cache_writer.dart'; /// Temporary debugging log function for this file void _debugLog(Object? object) { @@ -29,44 +29,73 @@ void _debugLog(Object? object) { } abstract class _FiroCache { - static const String sqliteDbFileName = "firo_ex_cache.sqlite3"; + static const int _setCacheVersion = 1; + static const int _tagsCacheVersion = 1; + static const String sparkSetCacheFileName = + "spark_set_v$_setCacheVersion.sqlite3"; + static const String sparkUsedTagsCacheFileName = + "spark_tags_v$_tagsCacheVersion.sqlite3"; - static Database? _db; - static Database get db { - if (_db == null) { + static Database? _setCacheDB; + static Database? _usedTagsCacheDB; + static Database get setCacheDB { + if (_setCacheDB == null) { throw Exception( "FiroCache.init() must be called before accessing FiroCache.db!", ); } - return _db!; + return _setCacheDB!; + } + + static Database get usedTagsCacheDB { + if (_usedTagsCacheDB == null) { + throw Exception( + "FiroCache.init() must be called before accessing FiroCache.db!", + ); + } + return _usedTagsCacheDB!; } static Future? _initFuture; static Future init() => _initFuture ??= _init(); static Future _init() async { - final sqliteDir = await StackFileSystem.applicationSQLiteDirectory(); + final sqliteDir = + await StackFileSystem.applicationFiroCacheSQLiteDirectory(); - final file = File("${sqliteDir.path}/$sqliteDbFileName"); + final sparkSetCacheFile = File("${sqliteDir.path}/$sparkSetCacheFileName"); + final sparkUsedTagsCacheFile = + File("${sqliteDir.path}/$sparkUsedTagsCacheFileName"); - final exists = await file.exists(); - if (!exists) { - await _createDb(file.path); + if (!(await sparkSetCacheFile.exists())) { + await _createSparkSetCacheDb(sparkSetCacheFile.path); + } + if (!(await sparkUsedTagsCacheFile.exists())) { + await _createSparkUsedTagsCacheDb(sparkUsedTagsCacheFile.path); } - _db = sqlite3.open( - file.path, + _setCacheDB = sqlite3.open( + sparkSetCacheFile.path, + mode: OpenMode.readWrite, + ); + _usedTagsCacheDB = sqlite3.open( + sparkUsedTagsCacheFile.path, mode: OpenMode.readWrite, ); } static Future _deleteAllCache() async { final start = DateTime.now(); - db.execute( + setCacheDB.execute( """ DELETE FROM SparkSet; DELETE FROM SparkCoin; DELETE FROM SparkSetCoins; + VACUUM; + """, + ); + usedTagsCacheDB.execute( + """ DELETE FROM SparkUsedCoinTags; VACUUM; """, @@ -77,7 +106,7 @@ abstract class _FiroCache { ); } - static Future _createDb(String file) async { + static Future _createSparkSetCacheDb(String file) async { final db = sqlite3.open( file, mode: OpenMode.readWriteCreate, @@ -109,7 +138,20 @@ abstract class _FiroCache { FOREIGN KEY (setId) REFERENCES SparkSet(id), FOREIGN KEY (coinId) REFERENCES SparkCoin(id) ); - + """, + ); + + db.dispose(); + } + + static Future _createSparkUsedTagsCacheDb(String file) async { + final db = sqlite3.open( + file, + mode: OpenMode.readWriteCreate, + ); + + db.execute( + """ CREATE TABLE SparkUsedCoinTags ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, tag TEXT NOT NULL UNIQUE diff --git a/lib/db/sqlite/firo_cache_coordinator.dart b/lib/db/sqlite/firo_cache_coordinator.dart index d2e4796f6..610504d5f 100644 --- a/lib/db/sqlite/firo_cache_coordinator.dart +++ b/lib/db/sqlite/firo_cache_coordinator.dart @@ -20,14 +20,18 @@ abstract class FiroCacheCoordinator { } static Future getSparkCacheSize() async { - final dir = await StackFileSystem.applicationSQLiteDirectory(); - final cacheFile = File("${dir.path}/${_FiroCache.sqliteDbFileName}"); - final int bytes; - if (await cacheFile.exists()) { - bytes = await cacheFile.length(); - } else { - bytes = 0; - } + final dir = await StackFileSystem.applicationFiroCacheSQLiteDirectory(); + final setCacheFile = File( + "${dir.path}/${_FiroCache.sparkSetCacheFileName}", + ); + final usedTagsCacheFile = File( + "${dir.path}/${_FiroCache.sparkUsedTagsCacheFileName}", + ); + final int bytes = + ((await setCacheFile.exists()) ? await setCacheFile.length() : 0) + + ((await usedTagsCacheFile.exists()) + ? await usedTagsCacheFile.length() + : 0); if (bytes < 1024) { return '$bytes B'; @@ -88,7 +92,7 @@ abstract class FiroCacheCoordinator { static Future> getUsedCoinTags(int startNumber) async { final result = await _Reader._getSparkUsedCoinTags( startNumber, - db: _FiroCache.db, + db: _FiroCache.usedTagsCacheDB, ); return result.map((e) => e["tag"] as String).toSet(); } @@ -99,7 +103,7 @@ abstract class FiroCacheCoordinator { /// this table in practice. static Future getUsedCoinTagsLastAddedRowId() async { final result = await _Reader._getUsedCoinTagsLastAddedRowId( - db: _FiroCache.db, + db: _FiroCache.usedTagsCacheDB, ); if (result.isEmpty) { return 0; @@ -112,7 +116,7 @@ abstract class FiroCacheCoordinator { ) async { return await _Reader._checkTagIsUsed( tag, - db: _FiroCache.db, + db: _FiroCache.usedTagsCacheDB, ); } @@ -122,7 +126,7 @@ abstract class FiroCacheCoordinator { }) async { return await _Reader._getSetCoinsForGroupId( groupId, - db: _FiroCache.db, + db: _FiroCache.setCacheDB, newerThanTimeStamp: newerThanTimeStamp, ); } @@ -137,7 +141,7 @@ abstract class FiroCacheCoordinator { ) async { final result = await _Reader._getLatestSetInfoForGroupId( groupId, - db: _FiroCache.db, + db: _FiroCache.setCacheDB, ); if (result.isEmpty) { @@ -156,7 +160,7 @@ abstract class FiroCacheCoordinator { ) async { return await _Reader._checkSetInfoForGroupIdExists( groupId, - db: _FiroCache.db, + db: _FiroCache.setCacheDB, ); } } diff --git a/lib/db/sqlite/firo_cache_worker.dart b/lib/db/sqlite/firo_cache_worker.dart index d29018b8d..a611c54b9 100644 --- a/lib/db/sqlite/firo_cache_worker.dart +++ b/lib/db/sqlite/firo_cache_worker.dart @@ -26,8 +26,10 @@ class _FiroCacheWorker { } static Future<_FiroCacheWorker> spawn() async { - final sqliteDir = await StackFileSystem.applicationSQLiteDirectory(); - final dbFilePath = "${sqliteDir.path}/${_FiroCache.sqliteDbFileName}"; + final dir = await StackFileSystem.applicationFiroCacheSQLiteDirectory(); + final setCacheFilePath = "${dir.path}/${_FiroCache.sparkSetCacheFileName}"; + final usedTagsCacheFilePath = + "${dir.path}/${_FiroCache.sparkUsedTagsCacheFileName}"; final initPort = RawReceivePort(); final connection = Completer<(ReceivePort, SendPort)>.sync(); @@ -45,7 +47,7 @@ class _FiroCacheWorker { try { await Isolate.spawn( _startWorkerIsolate, - (initPort.sendPort, dbFilePath), + (initPort.sendPort, setCacheFilePath, usedTagsCacheFilePath), ); } catch (_) { initPort.close(); @@ -75,7 +77,8 @@ class _FiroCacheWorker { static void _handleCommandsToIsolate( ReceivePort receivePort, SendPort sendPort, - Database db, + Database setCacheDb, + Database usedTagsCacheDb, Mutex mutex, ) { receivePort.listen((message) { @@ -87,11 +90,18 @@ class _FiroCacheWorker { switch (task.func) { case FCFuncName._updateSparkAnonSetCoinsWith: final data = task.data as (int, Map); - result = _updateSparkAnonSetCoinsWith(db, data.$2, data.$1); + result = _updateSparkAnonSetCoinsWith( + setCacheDb, + data.$2, + data.$1, + ); break; case FCFuncName._updateSparkUsedTagsWith: - result = _updateSparkUsedTagsWith(db, task.data as List); + result = _updateSparkUsedTagsWith( + usedTagsCacheDb, + task.data as List, + ); break; } @@ -107,14 +117,24 @@ class _FiroCacheWorker { }); } - static void _startWorkerIsolate((SendPort, String) args) { + static void _startWorkerIsolate((SendPort, String, String) args) { final receivePort = ReceivePort(); args.$1.send(receivePort.sendPort); final mutex = Mutex(); - final db = sqlite3.open( + final setCacheDb = sqlite3.open( args.$2, mode: OpenMode.readWrite, ); - _handleCommandsToIsolate(receivePort, args.$1, db, mutex); + final usedTagsCacheDb = sqlite3.open( + args.$3, + mode: OpenMode.readWrite, + ); + _handleCommandsToIsolate( + receivePort, + args.$1, + setCacheDb, + usedTagsCacheDb, + mutex, + ); } } diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart index 022c0640a..cf47215d1 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart @@ -18,6 +18,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:isar/isar.dart'; +import '../../../db/sqlite/firo_cache.dart'; import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../models/isar/models/isar_models.dart'; import '../../../pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart'; @@ -282,6 +283,24 @@ class _DesktopWalletViewState extends ConsumerState { ), ], ), + if (wallet.isarTransactionVersion == 2 && + wallet is FiroWallet) + Row( + children: [ + const Text( + "sparkCache: ", + ), + const SizedBox( + width: 2, + ), + FutureBuilder( + future: FiroCacheCoordinator.getSparkCacheSize(), + builder: (_, snapshot) => Text( + snapshot.data ?? "", + ), + ), + ], + ), ], ), const Spacer(), diff --git a/lib/utilities/stack_file_system.dart b/lib/utilities/stack_file_system.dart index 281bd2a8f..da3d33cfe 100644 --- a/lib/utilities/stack_file_system.dart +++ b/lib/utilities/stack_file_system.dart @@ -91,10 +91,24 @@ abstract class StackFileSystem { } } - static Future applicationSQLiteDirectory() async { + // Not used in general now. See applicationFiroCacheSQLiteDirectory() + // static Future applicationSQLiteDirectory() async { + // final root = await applicationRootDirectory(); + // if (Util.isDesktop) { + // final dir = Directory("${root.path}/sqlite"); + // if (!dir.existsSync()) { + // await dir.create(); + // } + // return dir; + // } else { + // return root; + // } + // } + + static Future applicationTorDirectory() async { final root = await applicationRootDirectory(); if (Util.isDesktop) { - final dir = Directory("${root.path}/sqlite"); + final dir = Directory("${root.path}/tor"); if (!dir.existsSync()) { await dir.create(); } @@ -104,10 +118,10 @@ abstract class StackFileSystem { } } - static Future applicationTorDirectory() async { + static Future applicationFiroCacheSQLiteDirectory() async { final root = await applicationRootDirectory(); if (Util.isDesktop) { - final dir = Directory("${root.path}/tor"); + final dir = Directory("${root.path}/sqlite/firo_cache"); if (!dir.existsSync()) { await dir.create(); }