diff options
-rw-r--r-- | client/src/leap/soledad/client/__init__.py | 1 | ||||
-rw-r--r-- | client/src/leap/soledad/client/dbwrapper.py | 183 |
2 files changed, 0 insertions, 184 deletions
diff --git a/client/src/leap/soledad/client/__init__.py b/client/src/leap/soledad/client/__init__.py index fc8219fa..a3b26689 100644 --- a/client/src/leap/soledad/client/__init__.py +++ b/client/src/leap/soledad/client/__init__.py @@ -84,7 +84,6 @@ except ImportError: from leap.soledad.common import soledad_assert, soledad_assert_type from leap.soledad.common.document import SoledadDocument from leap.soledad.client.crypto import SoledadCrypto -from leap.soledad.client.dbwrapper import SQLCipherWrapper from leap.soledad.client.shared_db import SoledadSharedDatabase from leap.soledad.client.sqlcipher import open as sqlcipher_open from leap.soledad.client.sqlcipher import SQLCipherDatabase diff --git a/client/src/leap/soledad/client/dbwrapper.py b/client/src/leap/soledad/client/dbwrapper.py deleted file mode 100644 index a27a933e..00000000 --- a/client/src/leap/soledad/client/dbwrapper.py +++ /dev/null @@ -1,183 +0,0 @@ -# -*- coding: utf-8 -*- -# dbwrapper.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -""" -Thread-safe wrapper for sqlite/pysqlcipher. - -*TODO* -At some point we surely will want to switch to a twisted way of dealing -with this, using defers and proper callbacks. But I had this tested for -some time so postponing that refactor. -""" -import logging -import threading -import Queue -import time - -import exceptions - -from functools import partial - -from leap.soledad.client import sqlcipher - -logger = logging.getLogger(__name__) - - -class SQLCipherWrapper(threading.Thread): - - def __init__(self, *args, **kwargs): - """ - Initializes a wrapper that proxies method and attribute - access to an underlying SQLCipher instance. We instantiate sqlcipher - in a thread, and all method accesses communicate with it using a - Queue. - - :param *args: position arguments to pass to pysqlcipher initialization - :type args: tuple - - :param **kwargs: keyword arguments to pass to pysqlcipher - initialization - :type kwargs: dict - """ - threading.Thread.__init__(self) - self._db = None - self._wrargs = args, kwargs - - self._queue = Queue.Queue() - self._stopped = threading.Event() - - self.start() - - def _init_db(self): - """ - Initializes sqlcipher database. - - This is called on a separate thread. - """ - # instantiate u1db - args, kwargs = self._wrargs - self._db = sqlcipher.open(*args, **kwargs) - - def run(self): - """ - Main loop for the sqlcipher thread. - """ - logger.debug("SQLCipherWrapper thread started.") - logger.debug("Initializing sqlcipher") - end_mths = ("__end_thread", "_SQLCipherWrapper__end_thread") - - self._init_db() - self._lock = threading.Lock() - - ct = 0 - started = False - - while True: - if self._db is None: - if started: - break - if ct > 10: - break # XXX DEBUG - logger.debug('db not ready yet, waiting...') - time.sleep(1) - ct += 1 - - started = True - - with self._lock: - try: - mth, q, wrargs = self._queue.get() - except: - logger.error("exception getting args from queue") - - res = None - attr = getattr(self._db, mth, None) - if not attr: - if mth not in end_mths: - logger.error('method %s does not exist' % (mth,)) - res = AttributeError( - "_db instance has no attribute %s" % mth) - - elif callable(attr): - # invoke the method with the passed args - args = wrargs.get('args', []) - kwargs = wrargs.get('kwargs', {}) - try: - res = attr(*args, **kwargs) - except Exception as e: - logger.error( - "Error on proxied method %s: '%r'." % ( - attr, e)) - res = e - else: - # non-callable attribute - res = attr - logger.debug('returning proxied db call...') - q.put(res) - - if mth in end_mths: - logger.debug('ending thread') - break - - logger.debug("SQLCipherWrapper thread terminated.") - self._stopped.set() - - def close(self): - """ - Closes the sqlcipher database and finishes the thread. This method - should always be called explicitely. - """ - self.__getattr__('close')() - self.__end_thread() - - def __getattr__(self, attr): - """ - Returns _db proxied attributes. - """ - - def __proxied_mth(method, *args, **kwargs): - if not self._stopped.isSet(): - wrargs = {'args': args, 'kwargs': kwargs} - q = Queue.Queue() - self._queue.put((method, q, wrargs)) - res = q.get() - q.task_done() - - if isinstance(res, exceptions.BaseException): - # XXX should get the original bt - raise res - return res - else: - logger.warning("tried to call proxied meth " - "but stopped is set: %s" % - (method,)) - - rgetattr = object.__getattribute__ - - if attr != "_db": - proxied = partial(__proxied_mth, attr) - return proxied - - # fallback to regular behavior - return rgetattr(self, attr) - - def __del__(self): - """ - Do not trust this get called. No guarantees given. Because of a funny - dance with the refs and the way the gc works, we should be calling the - close method explicitely. - """ - self.close() |