[tor-commits] [nyx/master] Move cache to its own module

atagar at torproject.org atagar at torproject.org
Sun Sep 3 01:24:13 UTC 2017


commit 70fe1215a01020a87c9cdee139f4188b1424d006
Author: Damian Johnson <atagar at torproject.org>
Date:   Thu Aug 31 10:41:22 2017 -0700

    Move cache to its own module
    
    Not yet even close to what I'm planning, but moving this out of the base module
    is a good first step.
---
 nyx/__init__.py | 53 +-------------------------------------
 nyx/cache.py    | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 test/cache.py   | 26 +++++++++----------
 3 files changed, 93 insertions(+), 65 deletions(-)

diff --git a/nyx/__init__.py b/nyx/__init__.py
index 8c3d396..c2032bc 100644
--- a/nyx/__init__.py
+++ b/nyx/__init__.py
@@ -31,10 +31,8 @@ Tor curses monitoring application.
     +- halt - stops daemon panels
 """
 
-import contextlib
 import distutils.spawn
 import os
-import sqlite3
 import sys
 import threading
 import time
@@ -55,6 +53,7 @@ __license__ = 'GPLv3'
 
 __all__ = [
   'arguments',
+  'cache',
   'controller',
   'curses',
   'log',
@@ -86,17 +85,6 @@ CONFIG = stem.util.conf.config_dict('nyx', {
 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,
-
-  'CREATE TABLE relays(fingerprint TEXT PRIMARY KEY, address TEXT, or_port NUMBER, nickname TEXT)',
-)
-
 
 # technically can change but we use this query a *lot* so needs to be cached
 
@@ -263,45 +251,6 @@ def data_directory(filename, config):
   return os.path.join(data_dir, filename)
 
 
- at contextlib.contextmanager
-def cache():
-  """
-  Provides the sqlite cache for application data.
-
-  :returns: **sqlite3.Connection** for our applicaion cache
-  """
-
-  global CACHE
-
-  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)
-
-    yield CACHE
-
-
 @uses_settings
 def expand_path(path, config):
   """
diff --git a/nyx/cache.py b/nyx/cache.py
new file mode 100644
index 0000000..b989f20
--- /dev/null
+++ b/nyx/cache.py
@@ -0,0 +1,79 @@
+"""
+Cache for frequently needed information. This persists to disk if we can, and
+otherwise is an in-memory cache.
+"""
+
+import contextlib
+import os
+import sqlite3
+import threading
+
+import stem.util.log
+
+import nyx
+
+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,
+
+  'CREATE TABLE relays(fingerprint TEXT PRIMARY KEY, address TEXT, or_port NUMBER, nickname TEXT)',
+)
+
+
+ at contextlib.contextmanager
+def cache():
+  """
+  Provides the sqlite cache for application data.
+
+  :returns: :class:`~nyx.cache.Cache` for our applicaion
+  """
+
+  global CACHE
+
+  with CACHE_LOCK:
+    if CACHE is None:
+      CACHE = Cache()
+
+    yield CACHE
+
+
+class Cache(object):
+  """
+  Cache for frequently used information.
+  """
+
+  def __init__(self):
+    cache_path = nyx.data_directory('cache.sqlite')
+
+    if cache_path:
+      try:
+        self._conn = sqlite3.connect(cache_path)
+        schema = self._conn.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))
+
+        self._conn.close()
+        os.remove(cache_path)
+        self._conn = sqlite3.connect(cache_path)
+
+        for cmd in SCHEMA:
+          self._conn.execute(cmd)
+    else:
+      self._conn = sqlite3.connect(':memory:')
+
+      for cmd in SCHEMA:
+        self._conn.execute(cmd)
+
+  def query(self, query, *param):
+    """
+    Performs a query on our cache.
+    """
+
+    return self._conn.execute(query, param)
diff --git a/test/cache.py b/test/cache.py
index 01f99af..733fbca 100644
--- a/test/cache.py
+++ b/test/cache.py
@@ -5,7 +5,7 @@ Unit tests for nyx.cache.
 import tempfile
 import unittest
 
-import nyx
+import nyx.cache
 
 from mock import Mock, patch
 
@@ -17,7 +17,7 @@ NICKNAME = 'caersidi'
 
 class TestCache(unittest.TestCase):
   def setUp(self):
-    nyx.CACHE = None  # drop cached database reference
+    nyx.cache.CACHE = None  # drop cached database reference
 
   @patch('nyx.data_directory', Mock(return_value = None))
   def test_memory_cache(self):
@@ -25,10 +25,10 @@ class TestCache(unittest.TestCase):
     Create a cache in memory.
     """
 
-    with nyx.cache() as cache:
-      self.assertEqual((0, 'main', ''), cache.execute("PRAGMA database_list").fetchone())
-      cache.execute('INSERT INTO relays(fingerprint, address, or_port, nickname) VALUES (?,?,?,?)', (FINGERPRINT, ADDRESS, PORT, NICKNAME))
-      self.assertEqual(NICKNAME, cache.execute('SELECT nickname FROM relays WHERE fingerprint=?', (FINGERPRINT,)).fetchone()[0])
+    with nyx.cache.cache() as cache:
+      self.assertEqual((0, 'main', ''), cache.query('PRAGMA database_list').fetchone())
+      cache.query('INSERT INTO relays(fingerprint, address, or_port, nickname) VALUES (?,?,?,?)', FINGERPRINT, ADDRESS, PORT, NICKNAME)
+      self.assertEqual(NICKNAME, cache.query('SELECT nickname FROM relays WHERE fingerprint=?', FINGERPRINT).fetchone()[0])
 
   def test_file_cache(self):
     """
@@ -37,12 +37,12 @@ class TestCache(unittest.TestCase):
 
     with tempfile.NamedTemporaryFile(suffix = '.sqlite') as tmp:
       with patch('nyx.data_directory', Mock(return_value = tmp.name)):
-        with nyx.cache() as cache:
-          self.assertEqual((0, 'main', tmp.name), cache.execute("PRAGMA database_list").fetchone())
-          cache.execute('INSERT INTO relays(fingerprint, address, or_port, nickname) VALUES (?,?,?,?)', (FINGERPRINT, ADDRESS, PORT, NICKNAME))
-          cache.commit()
+        with nyx.cache.cache() as cache:
+          self.assertEqual((0, 'main', tmp.name), cache.query('PRAGMA database_list').fetchone())
+          cache.query('INSERT INTO relays(fingerprint, address, or_port, nickname) VALUES (?,?,?,?)', FINGERPRINT, ADDRESS, PORT, NICKNAME)
+          cache._conn.commit()
 
-        nyx.CACHE = None
+        nyx.cache.CACHE = None
 
-        with nyx.cache() as cache:
-          self.assertEqual(NICKNAME, cache.execute('SELECT nickname FROM relays WHERE fingerprint=?', (FINGERPRINT,)).fetchone()[0])
+        with nyx.cache.cache() as cache:
+          self.assertEqual(NICKNAME, cache.query('SELECT nickname FROM relays WHERE fingerprint=?', FINGERPRINT).fetchone()[0])





More information about the tor-commits mailing list