CodernityDB / CodernityDB / database_super_thread_safe.py

codernity 0647083 


codernity 4d65fca 
codernity 0647083 

























codernity 10699da 

codernity 0647083 








codernity 10699da 
codernity 0647083 
codernity 10699da 


codernity 0647083 











codernity a472a6c 
codernity 0647083 









codernity 10699da 





codernity 0647083 
codernity a472a6c 



codernity 10699da 






























#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2011-2013 Codernity (http://codernity.com)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


from threading import RLock

from CodernityDB.env import cdb_environment

cdb_environment['mode'] = "threads"
cdb_environment['rlock_obj'] = RLock

from database import Database

from functools import wraps
from types import FunctionType, MethodType

from CodernityDB.database_safe_shared import th_safe_gen


class SuperLock(type):

    @staticmethod
    def wrapper(f):
        @wraps(f)
        def _inner(*args, **kwargs):
            db = args[0]
            with db.super_lock:
#                print '=>', f.__name__, repr(args[1:])
                res = f(*args, **kwargs)
#                if db.opened:
#                    db.flush()
#                print '<=', f.__name__, repr(args[1:])
                return res
        return _inner

    def __new__(cls, classname, bases, attr):
        new_attr = {}
        for base in bases:
            for b_attr in dir(base):
                a = getattr(base, b_attr, None)
                if isinstance(a, MethodType) and not b_attr.startswith('_'):
                    if b_attr == 'flush' or b_attr == 'flush_indexes':
                        pass
                    else:
                        # setattr(base, b_attr, SuperLock.wrapper(a))
                        new_attr[b_attr] = SuperLock.wrapper(a)
        for attr_name, attr_value in attr.iteritems():
            if isinstance(attr_value, FunctionType) and not attr_name.startswith('_'):
                attr_value = SuperLock.wrapper(attr_value)
            new_attr[attr_name] = attr_value
        new_attr['super_lock'] = RLock()
        return type.__new__(cls, classname, bases, new_attr)


class SuperThreadSafeDatabase(Database):
    """
    Thread safe version that always allows single thread to use db.
    It adds the same lock for all methods, so only one operation can be
    performed in given time. Completely different implementation
    than ThreadSafe version (without super word)
    """

    __metaclass__ = SuperLock

    def __init__(self, *args, **kwargs):
        super(SuperThreadSafeDatabase, self).__init__(*args, **kwargs)

    def __patch_index_gens(self, name):
        ind = self.indexes_names[name]
        for c in ('all', 'get_many'):
            m = getattr(ind, c)
            if getattr(ind, c + "_orig", None):
                return
            m_fixed = th_safe_gen.wrapper(m, name, c, self.super_lock)
            setattr(ind, c, m_fixed)
            setattr(ind, c + '_orig', m)

    def open(self, *args, **kwargs):
        res = super(SuperThreadSafeDatabase, self).open(*args, **kwargs)
        for name in self.indexes_names.iterkeys():
            self.__patch_index_gens(name)
        return res

    def create(self, *args, **kwargs):
        res = super(SuperThreadSafeDatabase, self).create(*args, **kwargs)
        for name in self.indexes_names.iterkeys():
            self.__patch_index_gens(name)
            return res

    def add_index(self, *args, **kwargs):
        res = super(SuperThreadSafeDatabase, self).add_index(*args, **kwargs)
        self.__patch_index_gens(res)
        return res

    def edit_index(self, *args, **kwargs):
        res = super(SuperThreadSafeDatabase, self).edit_index(*args, **kwargs)
        self.__patch_index_gens(res)
        return res
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.