Storage.py 5.16 KB
Newer Older
Aurel's avatar
Aurel committed
1
#
Grégory Wisniewski's avatar
Grégory Wisniewski committed
2
# Copyright (C) 2006-2010  Nexedi SA
3
#
Aurel's avatar
Aurel committed
4 5 6 7
# 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.
8
#
Aurel's avatar
Aurel committed
9 10 11 12 13 14 15
# 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, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Aurel's avatar
Aurel committed
17

18 19
from ZODB import BaseStorage, ConflictResolution, POSException

20
from neo.client.app import Application
21
from neo.client.exception import NEOStorageNotFoundError
22

23 24 25 26 27 28 29
def check_read_only(func):
    def wrapped(self, *args, **kw):
        if self._is_read_only:
            raise POSException.ReadOnlyError()
        return func(self, *args, **kw)
    return wrapped

Aurel's avatar
Aurel committed
30 31
class Storage(BaseStorage.BaseStorage,
              ConflictResolution.ConflictResolvingStorage):
32
    """Wrapper class for neoclient."""
33

Aurel's avatar
Aurel committed
34 35
    __name__ = 'NEOStorage'

36 37
    def __init__(self, master_nodes, name, connector=None, read_only=False,
                 **kw):
38
        BaseStorage.BaseStorage.__init__(self, name)
39
        self._is_read_only = read_only
40
        self.app = Application(master_nodes, name, connector)
41 42

    def load(self, oid, version=None):
43
        try:
Aurel's avatar
Aurel committed
44
            return self.app.load(oid=oid)
45 46
        except NEOStorageNotFoundError:
            raise POSException.POSKeyError(oid)
47

48
    @check_read_only
49
    def new_oid(self):
Aurel's avatar
Aurel committed
50
        return self.app.new_oid()
51

52
    @check_read_only
53
    def tpc_begin(self, transaction, tid=None, status=' '):
54
        return self.app.tpc_begin(transaction=transaction, tid=tid,
55
                status=status)
56

57
    @check_read_only
58
    def tpc_vote(self, transaction):
59 60
        return self.app.tpc_vote(transaction=transaction,
            tryToResolveConflict=self.tryToResolveConflict)
61

62
    @check_read_only
63
    def tpc_abort(self, transaction):
64
        return self.app.tpc_abort(transaction=transaction)
65

66
    def tpc_finish(self, transaction, f=None):
67
        return self.app.tpc_finish(transaction=transaction, f=f)
68

69
    @check_read_only
70
    def store(self, oid, serial, data, version, transaction):
71 72 73
        return self.app.store(oid=oid, serial=serial,
            data=data, version=version, transaction=transaction,
            tryToResolveConflict=self.tryToResolveConflict)
74

75
    def getSerial(self, oid):
76
        try:
Aurel's avatar
Aurel committed
77
            return self.app.getSerial(oid = oid)
78 79
        except NEOStorageNotFoundError:
            raise POSException.POSKeyError(oid)
80

81 82
    # mutliple revisions
    def loadSerial(self, oid, serial):
83
        try:
Aurel's avatar
Aurel committed
84
            return self.app.loadSerial(oid=oid, serial=serial)
85 86
        except NEOStorageNotFoundError:
            raise POSException.POSKeyError (oid, serial)
87 88

    def loadBefore(self, oid, tid):
89
        try:
Aurel's avatar
Aurel committed
90
            return self.app.loadBefore(oid=oid, tid=tid)
91
        except NEOStorageNotFoundError:
92
            return None
93

94
    def iterator(self, start=None, stop=None):
95
        return self.app.iterator(start, stop)
96

97
    # undo
98
    @check_read_only
99
    def undo(self, transaction_id, txn):
100 101
        return self.app.undo(transaction_id=transaction_id, txn=txn,
            tryToResolveConflict=self.tryToResolveConflict)
102

103

104
    @check_read_only
105
    def undoLog(self, first, last, filter=None):
Aurel's avatar
Aurel committed
106
        return self.app.undoLog(first, last, filter)
107 108

    def supportsUndo(self):
109 110 111 112
        return True

    def supportsTransactionalUndo(self):
        return True
113

114
    @check_read_only
115
    def abortVersion(self, src, transaction):
116
        return self.app.abortVersion(src, transaction)
117

118
    @check_read_only
119
    def commitVersion(self, src, dest, transaction):
120
        return self.app.commitVersion(src, dest, transaction)
121

122
    def __len__(self):
123
        return self.app.getStorageSize()
124 125 126

    def registerDB(self, db, limit):
        self.app.registerDB(db, limit)
Aurel's avatar
Aurel committed
127

Grégory Wisniewski's avatar
Grégory Wisniewski committed
128 129
    def history(self, oid, version=None, size=1, filter=None):
        return self.app.history(oid, version, size, filter)
Aurel's avatar
Aurel committed
130

131 132
    def sync(self):
        self.app.sync()
Aurel's avatar
Aurel committed
133

134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
#    def restore(self, oid, serial, data, version, prev_txn, transaction):
#        raise NotImplementedError

    def pack(self, t, referencesf):
        raise NotImplementedError

    def lastSerial(self):
        # seems unused
        raise NotImplementedError

    def lastTransaction(self):
        # seems unused
        raise NotImplementedError

    def _clear_temp(self):
        raise NotImplementedError

    def set_max_oid(self, possible_new_max_oid):
        # seems used only by FileStorage
        raise NotImplementedError
154 155 156 157 158 159 160 161 162 163 164 165

    def cleanup(self):
        # Used in unit tests to remove local database files.
        # We have no such thing, so make this method a no-op.
        pass

    def close(self):
        # The purpose of this method is unclear, the NEO implementation may
        # stop the client node or ask the primary master to shutdown/freeze the
        # cluster. For now make this a no-op.
        pass