Commit f419f974 authored by Julien Muchembled's avatar Julien Muchembled

storage: define interface for backends and check they implement it

parent c6b80f7b
#
# Copyright (C) 2015 Nexedi SA
#
# 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 2
# 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/>.
import inspect
from functools import wraps
def implements(obj, ignore=()):
tobj = type(obj)
ignore = set(ignore)
not_implemented = []
for name in dir(obj):
method = getattr(obj if issubclass(tobj, type) or name in obj.__dict__
else tobj, name)
if inspect.ismethod(method):
try:
method.__abstract__
ignore.remove(name)
except KeyError:
not_implemented.append(name)
except AttributeError:
not_implemented.extend(func.__name__
for func in getattr(method, "__requires__", ())
if not hasattr(obj, func.__name__))
assert not ignore, ignore
assert not not_implemented, not_implemented
return obj
def _set_code(func):
args, varargs, varkw, _ = inspect.getargspec(func)
if varargs:
args.append("*" + varargs)
if varkw:
args.append("**" + varkw)
exec "def %s(%s): raise NotImplementedError\nf = %s" % (
func.__name__, ",".join(args), func.__name__)
func.func_code = f.func_code
def abstract(func):
_set_code(func)
func.__abstract__ = 1
return func
def requires(*args):
for func in args:
_set_code(func)
def decorator(func):
func.__requires__ = args
return func
return decorator
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
LOG_QUERIES = False LOG_QUERIES = False
from neo.lib.exception import DatabaseFailure from neo.lib.exception import DatabaseFailure
from .manager import DatabaseManager
DATABASE_MANAGER_DICT = { DATABASE_MANAGER_DICT = {
'Importer': 'importer.ImporterDatabaseManager', 'Importer': 'importer.ImporterDatabaseManager',
......
...@@ -23,10 +23,13 @@ from ConfigParser import SafeConfigParser ...@@ -23,10 +23,13 @@ from ConfigParser import SafeConfigParser
from ZODB.config import storageFromString from ZODB.config import storageFromString
from ZODB.POSException import POSKeyError from ZODB.POSException import POSKeyError
from . import buildDatabaseManager, DatabaseManager from . import buildDatabaseManager
from .manager import DatabaseManager
from neo.lib import logging, patch, util from neo.lib import logging, patch, util
from neo.lib.exception import DatabaseFailure from neo.lib.exception import DatabaseFailure
from neo.lib.protocol import CellStates, ZERO_OID, ZERO_TID, ZERO_HASH, MAX_TID from neo.lib.interfaces import implements
from neo.lib.protocol import BackendNotImplemented, CellStates, \
MAX_TID, ZERO_HASH, ZERO_OID, ZERO_TID
patch.speedupFileStorageTxnLookup() patch.speedupFileStorageTxnLookup()
...@@ -280,6 +283,9 @@ class ImporterDatabaseManager(DatabaseManager): ...@@ -280,6 +283,9 @@ class ImporterDatabaseManager(DatabaseManager):
def __init__(self, *args, **kw): def __init__(self, *args, **kw):
super(ImporterDatabaseManager, self).__init__(*args, **kw) super(ImporterDatabaseManager, self).__init__(*args, **kw)
self.db._connect() self.db._connect()
implements(self, """_getNextTID checkSerialRange checkTIDRange
deleteObject deleteTransaction dropPartitions getLastTID
getReplicationObjectList getTIDList nonempty""".split())
_uncommitted_data = property( _uncommitted_data = property(
lambda self: self.db._uncommitted_data, lambda self: self.db._uncommitted_data,
...@@ -549,3 +555,8 @@ class ImporterDatabaseManager(DatabaseManager): ...@@ -549,3 +555,8 @@ class ImporterDatabaseManager(DatabaseManager):
length, partition) length, partition)
return r return r
def getObjectHistory(self, *args, **kw):
raise BackendNotImplemented(self.getObjectHistory)
def pack(self, *args, **kw):
raise BackendNotImplemented(self.pack)
This diff is collapsed.
...@@ -28,10 +28,11 @@ import string ...@@ -28,10 +28,11 @@ import string
import struct import struct
import time import time
from . import DatabaseManager, LOG_QUERIES from . import LOG_QUERIES
from .manager import CreationUndone, splitOIDField from .manager import CreationUndone, DatabaseManager, splitOIDField
from neo.lib import logging, util from neo.lib import logging, util
from neo.lib.exception import DatabaseFailure from neo.lib.exception import DatabaseFailure
from neo.lib.interfaces import implements
from neo.lib.protocol import CellStates, ZERO_OID, ZERO_TID, ZERO_HASH from neo.lib.protocol import CellStates, ZERO_OID, ZERO_TID, ZERO_HASH
...@@ -40,6 +41,7 @@ def getPrintableQuery(query, max=70): ...@@ -40,6 +41,7 @@ def getPrintableQuery(query, max=70):
else '\\x%02x' % ord(c) for c in query) else '\\x%02x' % ord(c) for c in query)
@implements
class MySQLDatabaseManager(DatabaseManager): class MySQLDatabaseManager(DatabaseManager):
"""This class manages a database on MySQL.""" """This class manages a database on MySQL."""
......
...@@ -20,10 +20,11 @@ from hashlib import sha1 ...@@ -20,10 +20,11 @@ from hashlib import sha1
import string import string
import traceback import traceback
from . import DatabaseManager, LOG_QUERIES from . import LOG_QUERIES
from .manager import CreationUndone, splitOIDField from .manager import CreationUndone, DatabaseManager, splitOIDField
from neo.lib import logging, util from neo.lib import logging, util
from neo.lib.exception import DatabaseFailure from neo.lib.exception import DatabaseFailure
from neo.lib.interfaces import implements
from neo.lib.protocol import CellStates, ZERO_OID, ZERO_TID, ZERO_HASH from neo.lib.protocol import CellStates, ZERO_OID, ZERO_TID, ZERO_HASH
def unique_constraint_message(table, *columns): def unique_constraint_message(table, *columns):
...@@ -57,6 +58,7 @@ def retry_if_locked(f, *args): ...@@ -57,6 +58,7 @@ def retry_if_locked(f, *args):
raise raise
@implements
class SQLiteDatabaseManager(DatabaseManager): class SQLiteDatabaseManager(DatabaseManager):
"""This class manages a database on SQLite. """This class manages a database on SQLite.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment