Skip to content

Commit

Permalink
de-djangofication.
Browse files Browse the repository at this point in the history
  • Loading branch information
mmalone committed Aug 10, 2010
1 parent f71c2cc commit 951a036
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 37 deletions.
22 changes: 11 additions & 11 deletions django_kvstore/__init__.py
Expand Up @@ -13,8 +13,7 @@
Brad Choate""" Brad Choate"""


from cgi import parse_qsl from cgi import parse_qsl
from django.conf import settings from goldengate import settings
from django.core import signals


# Names for use in settings file --> name of module in "backends" directory. # Names for use in settings file --> name of module in "backends" directory.
# Any backend scheeme that is not in this dictionary is treated as a Python # Any backend scheeme that is not in this dictionary is treated as a Python
Expand All @@ -29,7 +28,14 @@
'redis': 'redisdj', 'redis': 'redisdj',
} }


class InvalidKeyValueStoreBackend(Exception): pass
class InvalidKeyValueStoreBackend(Exception):
pass


class ImproperlyConfigured(Exception):
pass



def get_kvstore(backend_uri): def get_kvstore(backend_uri):
if backend_uri.find(':') == -1: if backend_uri.find(':') == -1:
Expand All @@ -49,16 +55,10 @@ def get_kvstore(backend_uri):
host = host[:-1] host = host[:-1]


if scheme in BACKENDS: if scheme in BACKENDS:
module = __import__('django_kvstore.backends.%s' % BACKENDS[scheme], {}, {}, ['']) module = __import__('kvstore.backends.%s' % BACKENDS[scheme], {}, {}, [''])
else: else:
module = __import__(scheme, {}, {}, ['']) module = __import__(scheme, {}, {}, [''])
return getattr(module, 'StorageClass')(host, params) return getattr(module, 'StorageClass')(host, params)


kvstore = get_kvstore(settings.KEY_VALUE_STORE_BACKEND) kvstore = get_kvstore(settings.STORAGE_BACKEND)
"""A handle to the configured key-value store."""


# Some kv store backends need to do a cleanup at the end of
# a request cycle. If the cache provides a close() method, wire
# it up here.
if hasattr(kvstore, 'close'):
signals.request_finished.connect(kvstore.close)
2 changes: 1 addition & 1 deletion django_kvstore/backends/base.py
@@ -1,6 +1,6 @@
"Base key-value store abstract class." "Base key-value store abstract class."


from django.core.exceptions import ImproperlyConfigured from kvstore import ImproperlyConfigured


class InvalidKeyValueStoreBackendError(ImproperlyConfigured): class InvalidKeyValueStoreBackendError(ImproperlyConfigured):
pass pass
Expand Down
2 changes: 1 addition & 1 deletion django_kvstore/backends/db.py
Expand Up @@ -15,7 +15,7 @@
""" """


import base64 import base64
from django_kvstore.backends.base import BaseStorage from kvstore.backends.base import BaseStorage
from django.db import connection, transaction, DatabaseError from django.db import connection, transaction, DatabaseError
try: try:
import cPickle as pickle import cPickle as pickle
Expand Down
87 changes: 85 additions & 2 deletions django_kvstore/backends/locmem.py
Expand Up @@ -13,9 +13,7 @@
import cPickle as pickle import cPickle as pickle
except ImportError: except ImportError:
import pickle import pickle

from base import BaseStorage from base import BaseStorage
from django.utils.synch import RWLock


class StorageClass(BaseStorage): class StorageClass(BaseStorage):
def __init__(self, _, params): def __init__(self, _, params):
Expand Down Expand Up @@ -58,3 +56,88 @@ def has_key(self, key):
return key in self._db return key in self._db
finally: finally:
self._lcok.reader_leaves() self._lcok.reader_leaves()


"""
Synchronization primitives:
- reader-writer lock (preference to writers)
(Contributed to Django by eugene@lazutkin.com)
(Borrowed from Django for use in Golden Gate by mike@simplegeo.com)
"""
import threading

class RWLock:
"""
Classic implementation of reader-writer lock with preference to writers.
Readers can access a resource simultaneously.
Writers get an exclusive access.
API is self-descriptive:
reader_enters()
reader_leaves()
writer_enters()
writer_leaves()
"""
def __init__(self):
self.mutex = threading.RLock()
self.can_read = threading.Semaphore(0)
self.can_write = threading.Semaphore(0)
self.active_readers = 0
self.active_writers = 0
self.waiting_readers = 0
self.waiting_writers = 0

def reader_enters(self):
self.mutex.acquire()
try:
if self.active_writers == 0 and self.waiting_writers == 0:
self.active_readers += 1
self.can_read.release()
else:
self.waiting_readers += 1
finally:
self.mutex.release()
self.can_read.acquire()

def reader_leaves(self):
self.mutex.acquire()
try:
self.active_readers -= 1
if self.active_readers == 0 and self.waiting_writers != 0:
self.active_writers += 1
self.waiting_writers -= 1
self.can_write.release()
finally:
self.mutex.release()

def writer_enters(self):
self.mutex.acquire()
try:
if self.active_writers == 0 and self.waiting_writers == 0 and self.active_readers == 0:
self.active_writers += 1
self.can_write.release()
else:
self.waiting_writers += 1
finally:
self.mutex.release()
self.can_write.acquire()

def writer_leaves(self):
self.mutex.acquire()
try:
self.active_writers -= 1
if self.waiting_writers != 0:
self.active_writers += 1
self.waiting_writers -= 1
self.can_write.release()
elif self.waiting_readers != 0:
t = self.waiting_readers
self.waiting_readers = 0
self.active_readers += t
while t > 0:
self.can_read.release()
t -= 1
finally:
self.mutex.release()
17 changes: 12 additions & 5 deletions django_kvstore/backends/memcached.py
Expand Up @@ -10,7 +10,6 @@
""" """


from base import BaseStorage, InvalidKeyValueStoreBackendError from base import BaseStorage, InvalidKeyValueStoreBackendError
from django.utils.encoding import smart_unicode, smart_str


try: try:
import cmemcache as memcache import cmemcache as memcache
Expand All @@ -20,6 +19,14 @@
except: except:
raise InvalidKeyValueStoreBackendError("Memcached key-value store backend requires either the 'memcache' or 'cmemcache' library") raise InvalidKeyValueStoreBackendError("Memcached key-value store backend requires either the 'memcache' or 'cmemcache' library")



def _utf8_str(s):
if isinstance(s, unicode):
return s.encode('utf-8')
else:
return str(s)


class StorageClass(BaseStorage): class StorageClass(BaseStorage):
def __init__(self, server, params): def __init__(self, server, params):
BaseStorage.__init__(self, params) BaseStorage.__init__(self, params)
Expand All @@ -28,17 +35,17 @@ def __init__(self, server, params):
def set(self, key, value): def set(self, key, value):
if isinstance(value, unicode): if isinstance(value, unicode):
value = value.encode('utf-8') value = value.encode('utf-8')
self._db.set(smart_str(key), value, 0) self._db.set(_utf8_str(key), value, 0)


def get(self, key): def get(self, key):
val = self._db.get(smart_str(key)) val = self._db.get(_utf8_str(key))
if isinstance(val, basestring): if isinstance(val, basestring):
return smart_unicode(val) return val.decode('utf-8')
else: else:
return val return val


def delete(self, key): def delete(self, key):
self._db.delete(smart_str(key)) self._db.delete(_utf8_str(key))


def close(self, **kwargs): def close(self, **kwargs):
self._db.disconnect_all() self._db.disconnect_all()
13 changes: 9 additions & 4 deletions django_kvstore/backends/redisdj.py
Expand Up @@ -10,7 +10,6 @@
""" """
import base64 import base64
from base import BaseStorage, InvalidKeyValueStoreBackendError from base import BaseStorage, InvalidKeyValueStoreBackendError
from django.utils.encoding import smart_unicode, smart_str


try: try:
import redis import redis
Expand All @@ -22,6 +21,12 @@
except ImportError: except ImportError:
import pickle import pickle


def _utf8_str(s):
if isinstance(s, unicode):
return s.encode('utf-8')
else:
return str(s)

class StorageClass(BaseStorage): class StorageClass(BaseStorage):


def __init__(self, server, params): def __init__(self, server, params):
Expand All @@ -36,16 +41,16 @@ def __init__(self, server, params):


def set(self, key, value): def set(self, key, value):
encoded = base64.encodestring(pickle.dumps(value, 2)).strip() encoded = base64.encodestring(pickle.dumps(value, 2)).strip()
self._db.set(smart_str(key), encoded) self._db.set(_utf8_str(key), encoded)


def get(self, key): def get(self, key):
val = self._db.get(smart_str(key)) val = self._db.get(_utf8_str(key))
if val is None: if val is None:
return None return None
return pickle.loads(base64.decodestring(val)) return pickle.loads(base64.decodestring(val))


def delete(self, key): def delete(self, key):
self._db.delete(smart_str(key)) self._db.delete(_utf8_str(key))


def close(self, **kwargs): def close(self, **kwargs):
pass pass
22 changes: 16 additions & 6 deletions django_kvstore/backends/sdb.py
Expand Up @@ -9,15 +9,25 @@




from base import BaseStorage, InvalidKeyValueStoreBackendError from base import BaseStorage, InvalidKeyValueStoreBackendError
from django.core.exceptions import ImproperlyConfigured from kvstore import ImproperlyConfigured
from django.utils.encoding import smart_unicode, smart_str try:
from django.utils import simplejson import simplejson as json
except ImportError:
import json


try: try:
import simpledb import simpledb
except ImportError: except ImportError:
raise InvalidKeyValueStoreBackendError("SipmleDB key-value store backend requires the 'python-simpledb' library") raise InvalidKeyValueStoreBackendError("SipmleDB key-value store backend requires the 'python-simpledb' library")



def _utf8_str(s):
if isinstance(s, unicode):
return s.encode('utf-8')
else:
return str(s)


class StorageClass(BaseStorage): class StorageClass(BaseStorage):
def __init__(self, domain, params): def __init__(self, domain, params):
BaseStorage.__init__(self, params) BaseStorage.__init__(self, params)
Expand All @@ -33,17 +43,17 @@ def __init__(self, domain, params):
def set(self, key, value): def set(self, key, value):
if isinstance(value, unicode): if isinstance(value, unicode):
value = value.encode('utf-8') value = value.encode('utf-8')
self._domain[smart_str(key)] = {'value': simplejson.dumps(value)} self._domain[_utf8_str(key)] = {'value': simplejson.dumps(value)}


def get(self, key): def get(self, key):
val = self._domain[smart_str(key)].get('value', None) val = self._domain[_utf8_str(key)].get('value', None)
if isinstance(val, basestring): if isinstance(val, basestring):
return simplejson.loads(val) return simplejson.loads(val)
else: else:
return val return val


def delete(self, key): def delete(self, key):
del self._domain[smart_str(key)] del self._domain[_utf8_str(key)]


def close(self, **kwargs): def close(self, **kwargs):
pass pass
22 changes: 16 additions & 6 deletions django_kvstore/backends/tokyotyrant.py
Expand Up @@ -10,15 +10,25 @@
""" """


from base import BaseStorage, InvalidKeyValueStoreBackendError from base import BaseStorage, InvalidKeyValueStoreBackendError
from django.core.exceptions import ImproperlyConfigured from kvstore import ImproperlyConfigured
from django.utils.encoding import smart_unicode, smart_str try:
from django.utils import simplejson import simplejson as json
except ImportError:
import json


try: try:
import pytyrant import pytyrant
except ImportError: except ImportError:
raise InvalidKeyValueStoreBackendError("Tokyotyrant key-value store backend requires the 'pytyrant' library") raise InvalidKeyValueStoreBackendError("Tokyotyrant key-value store backend requires the 'pytyrant' library")



def _utf8_str(s):
if isinstance(s, unicode):
return s.encode('utf-8')
else:
return str(s)


class StorageClass(BaseStorage): class StorageClass(BaseStorage):
def __init__(self, server, params): def __init__(self, server, params):
BaseStorage.__init__(self, params) BaseStorage.__init__(self, params)
Expand All @@ -32,17 +42,17 @@ def __init__(self, server, params):
def set(self, key, value): def set(self, key, value):
if isinstance(value, unicode): if isinstance(value, unicode):
value = value.encode('utf-8') value = value.encode('utf-8')
self._db[smart_str(key)] = simplejson.dumps(value) self._db[_utf8_str(key)] = simplejson.dumps(value)


def get(self, key): def get(self, key):
val = self._db.get(smart_str(key)) val = self._db.get(_utf8_str(key))
if isinstance(val, basestring): if isinstance(val, basestring):
return simplejson.loads(val) return simplejson.loads(val)
else: else:
return val return val


def delete(self, key): def delete(self, key):
del self._db[smart_str(key)] del self._db[_utf8_str(key)]


def close(self, **kwargs): def close(self, **kwargs):
pass pass
Expand Down
2 changes: 1 addition & 1 deletion django_kvstore/models.py
@@ -1,4 +1,4 @@
from django_kvstore import kvstore from kvstore import kvstore




class FieldError(Exception): pass class FieldError(Exception): pass
Expand Down

0 comments on commit 951a036

Please sign in to comment.