[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [nyx/master] Schema versioning and cache thread safety
commit 3b9786e3d22b938e7c25fc5a40179208707fd68b
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Wed Aug 30 10:32:44 2017 -0700
Schema versioning and cache thread safety
Versioning nyx's cache schema and ensure use of the cache is done in a thread
safe fashion.
---
nyx/__init__.py | 40 ++++++++++++++++++++++++++++++++++++----
test/cache.py | 31 ++++++++++++++++---------------
2 files changed, 52 insertions(+), 19 deletions(-)
diff --git a/nyx/__init__.py b/nyx/__init__.py
index c7db0cb..ee146a6 100644
--- a/nyx/__init__.py
+++ b/nyx/__init__.py
@@ -31,6 +31,7 @@ Tor curses monitoring application.
+- halt - stops daemon panels
"""
+import contextlib
import distutils.spawn
import os
import sqlite3
@@ -86,6 +87,14 @@ NYX_INTERFACE = None
TOR_CONTROLLER = None
BASE_DIR = os.path.sep.join(__file__.split(os.path.sep)[:-1])
CACHE = None
+CACHE_LOCK = threading.RLock()
+
+SCHEMA_VERSION = 1 # version of our scheme, bump this if you change the following
+SCHEMA = (
+ 'CREATE TABLE schema(version NUMBER)',
+ 'INSERT INTO schema(version) VALUES (%i)' % SCHEMA_VERSION,
+)
+
# technically can change but we use this query a *lot* so needs to be cached
@@ -252,6 +261,7 @@ def data_directory(filename, config):
return os.path.join(data_dir, filename)
+@contextlib.contextmanager
def cache():
"""
Provides the sqlite cache for application data.
@@ -261,11 +271,33 @@ def cache():
global CACHE
- if CACHE is None:
- cache_path = data_directory('cache.sqlite')
- CACHE = sqlite3.connect(cache_path if cache_path else ':memory:')
+ with CACHE_LOCK:
+ if CACHE is None:
+ cache_path = data_directory('cache.sqlite')
+
+ if cache_path:
+ try:
+ CACHE = sqlite3.connect(cache_path)
+ schema = CACHE.execute('SELECT version FROM schema').fetchone()[0]
+ except:
+ schema = 'no schema'
+
+ if schema != SCHEMA_VERSION:
+ stem.util.log.info('Cache schema of %s is out of date (has %s but current version is %s). Clearing the cache.' % (cache_path, schema, SCHEMA_VERSION))
+
+ CACHE.close()
+ os.remove(cache_path)
+ CACHE = sqlite3.connect(cache_path)
+
+ for cmd in SCHEMA:
+ CACHE.execute(cmd)
+ else:
+ CACHE = sqlite3.connect(':memory:')
+
+ for cmd in SCHEMA:
+ CACHE.execute(cmd)
- return CACHE
+ yield CACHE
@uses_settings
diff --git a/test/cache.py b/test/cache.py
index dc1fa40..1c30f40 100644
--- a/test/cache.py
+++ b/test/cache.py
@@ -16,25 +16,26 @@ class TestCache(unittest.TestCase):
@patch('nyx.data_directory', Mock(return_value = None))
def test_memory_cache(self):
- cache = nyx.cache()
- self.assertEqual((0, 'main', ''), cache.execute("PRAGMA database_list").fetchone())
+ with nyx.cache() as cache:
+ self.assertEqual((0, 'main', ''), cache.execute("PRAGMA database_list").fetchone())
- cache.execute('CREATE TABLE aliases(alias TEXT, command TEXT)')
- cache.execute('INSERT INTO aliases(alias, command) VALUES (?,?)', ('l', 'ls -xF --color=auto'))
- cache.execute('INSERT INTO aliases(alias, command) VALUES (?,?)', ('ll', 'ls -hlA --color=auto'))
- self.assertEqual('ls -hlA --color=auto', cache.execute('SELECT command FROM aliases WHERE alias=?', ('ll',)).fetchone()[0])
+ cache.execute('CREATE TABLE aliases(alias TEXT, command TEXT)')
+ cache.execute('INSERT INTO aliases(alias, command) VALUES (?,?)', ('l', 'ls -xF --color=auto'))
+ cache.execute('INSERT INTO aliases(alias, command) VALUES (?,?)', ('ll', 'ls -hlA --color=auto'))
+ self.assertEqual('ls -hlA --color=auto', cache.execute('SELECT command FROM aliases WHERE alias=?', ('ll',)).fetchone()[0])
def test_file_cache(self):
with tempfile.NamedTemporaryFile(suffix = '.sqlite') as tmp:
with patch('nyx.data_directory', Mock(return_value = tmp.name)):
- cache = nyx.cache()
- self.assertEqual((0, 'main', tmp.name), cache.execute("PRAGMA database_list").fetchone())
-
- cache.execute('CREATE TABLE aliases(alias TEXT, command TEXT)')
- cache.execute('INSERT INTO aliases(alias, command) VALUES (?,?)', ('l', 'ls -xF --color=auto'))
- cache.execute('INSERT INTO aliases(alias, command) VALUES (?,?)', ('ll', 'ls -hlA --color=auto'))
- cache.commit()
- cache.close()
+ with nyx.cache() as cache:
+ self.assertEqual((0, 'main', tmp.name), cache.execute("PRAGMA database_list").fetchone())
+
+ cache.execute('CREATE TABLE aliases(alias TEXT, command TEXT)')
+ cache.execute('INSERT INTO aliases(alias, command) VALUES (?,?)', ('l', 'ls -xF --color=auto'))
+ cache.execute('INSERT INTO aliases(alias, command) VALUES (?,?)', ('ll', 'ls -hlA --color=auto'))
+ cache.commit()
+
nyx.CACHE = None
- self.assertEqual('ls -hlA --color=auto', nyx.cache().execute('SELECT command FROM aliases WHERE alias=?', ('ll',)).fetchone()[0])
+ with nyx.cache() as cache:
+ self.assertEqual('ls -hlA --color=auto', cache.execute('SELECT command FROM aliases WHERE alias=?', ('ll',)).fetchone()[0])
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits