manager.py 10.6 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
from neo import util
19
from neo.exception import DatabaseFailure
20

21 22 23
class DatabaseManager(object):
    """This class only describes an interface for database managers."""

24
    def __init__(self):
25 26 27 28 29
        """
            Initialize the object.
        """
        self._under_transaction = False

30 31 32
    def isUnderTransaction(self):
        return self._under_transaction

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
    def begin(self):
        """
            Begin a transaction
        """
        if self._under_transaction:
            raise DatabaseFailure('A transaction as already began')
        self._begin()
        self._under_transaction = True

    def commit(self):
        """
            Commit the current transaction
        """
        if not self._under_transaction:
            raise DatabaseFailure('The transaction as not began')
        self._commit()
        self._under_transaction = False

    def rollback(self):
        """
            Rollback the current transaction
        """
        self._rollback()
        self._under_transaction = False
57 58 59 60

    def setup(self, reset = 0):
        """Set up a database. If reset is true, existing data must be
        discarded."""
61
        raise NotImplementedError
62 63 64 65

    def _begin(self):
        raise NotImplementedError

66 67 68 69 70 71
    def _commit(self):
        raise NotImplementedError

    def _rollback(self):
        raise NotImplementedError

72 73 74 75
    def getConfiguration(self, key):
        """
            Return a configuration value, returns None if not found or not set
        """
76
        raise NotImplementedError
77

78 79 80 81
    def setConfiguration(self, key, value):
        """
            Set a configuration value
        """
82 83 84 85 86 87 88 89 90 91 92 93
        if self._under_transaction:
            self._setConfiguration(key, value)
        else:
            self.begin()
            try:
                self._setConfiguration(key, value)
            except:
                self.rollback()
                raise
            self.commit()

    def _setConfiguration(self, key, value):
94
        raise NotImplementedError
95

96 97 98 99 100 101 102 103 104 105 106 107
    def getUUID(self):
        """
            Load an UUID from a database.
        """
        return util.bin(self.getConfiguration('uuid'))

    def setUUID(self, uuid):
        """
            Store an UUID into a database.
        """
        self.setConfiguration('uuid', util.dump(uuid))

108
    def getNumPartitions(self):
109 110 111 112 113 114
        """
            Load the number of partitions from a database.
        """
        n = self.getConfiguration('partitions')
        if n is not None:
            return int(n)
115 116

    def setNumPartitions(self, num_partitions):
117 118 119 120
        """
            Store the number of partitions into a database.
        """
        self.setConfiguration('partitions', num_partitions)
121

122
    def getNumReplicas(self):
123 124 125 126 127 128 129 130 131 132 133 134
        """
            Load the number of replicas from a database.
        """
        n = self.getConfiguration('replicas')
        if n is not None:
            return int(n)

    def setNumReplicas(self, num_replicas):
        """
            Store the number of replicas into a database.
        """
        self.setConfiguration('replicas', num_replicas)
135

136
    def getName(self):
137 138 139 140
        """
            Load a name from a database.
        """
        return self.getConfiguration('name')
141 142

    def setName(self, name):
143 144 145 146
        """
            Store a name into a database.
        """
        self.setConfiguration('name', name)
147 148

    def getPTID(self):
149 150 151 152
        """
            Load a Partition Table ID from a database.
        """
        return util.bin(self.getConfiguration('ptid'))
153 154

    def setPTID(self, ptid):
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
        """
            Store a Partition Table ID into a database.
        """
        self.setConfiguration('ptid', util.dump(ptid))

    def getLastOID(self):
        """
            Returns the last OID used
        """
        return util.bin(self.getConfiguration('loid'))

    def setLastOID(self, loid):
        """
            Set the last OID used
        """
        self.setConfiguration('loid', util.dump(loid))
171 172 173 174 175

    def getPartitionTable(self):
        """Return a whole partition table as a tuple of rows. Each row
        is again a tuple of an offset (row ID), an UUID of a storage
        node, and a cell state."""
176
        raise NotImplementedError
177 178 179 180 181

    def getLastTID(self, all = True):
        """Return the last TID in a database. If all is true,
        unfinished transactions must be taken account into. If there
        is no TID in the database, return None."""
182
        raise NotImplementedError
183 184 185

    def getUnfinishedTIDList(self):
        """Return a list of unfinished transaction's IDs."""
186
        raise NotImplementedError
187 188 189 190 191

    def objectPresent(self, oid, tid, all = True):
        """Return true iff an object specified by a given pair of an
        object ID and a transaction ID is present in a database.
        Otherwise, return false. If all is true, the object must be
192
        searched from unfinished transactions as well."""
193
        raise NotImplementedError
194

195
    def getObject(self, oid, tid = None, before_tid = None):
196
        """Return a tuple of a serial, next serial, a compression
197 198 199 200 201
        specification, a checksum, and object data, if a given object
        ID is present. Otherwise, return None. If tid is None and
        before_tid is None, the latest revision is taken. If tid is
        specified, the given revision is taken. If tid is not specified,
        but before_tid is specified, the latest revision before the
202 203
        given revision is taken. The next serial is a serial right after
        before_tid, if specified. Otherwise, it is None."""
204
        raise NotImplementedError
205

206 207 208 209 210
    def changePartitionTable(self, ptid, cell_list):
        """Change a part of a partition table. The list of cells is
        a tuple of tuples, each of which consists of an offset (row ID),
        an UUID of a storage node, and a cell state. The Partition
        Table ID must be stored as well."""
211
        raise NotImplementedError
212 213 214 215 216

    def setPartitionTable(self, ptid, cell_list):
        """Set a whole partition table. The semantics is the same as
        changePartitionTable, except that existing data must be
        thrown away."""
217
        raise NotImplementedError
218

219 220
    def dropPartitions(self, num_partitions, offset_list):
        """ Drop any data of non-assigned partitions for a given UUID """
221 222
        raise NotImplementedError('this method must be overriden')

223 224
    def dropUnfinishedData(self):
        """Drop any unfinished data from a database."""
225
        raise NotImplementedError
226

227 228 229 230 231 232
    def storeTransaction(self, tid, object_list, transaction, temporary = True):
        """Store a transaction temporarily, if temporary is true. Note
        that this transaction is not finished yet. The list of objects
        contains tuples, each of which consists of an object ID,
        a compression specification, a checksum and object data.
        The transaction is either None or a tuple of the list of OIDs,
233 234
        user information, a description, extension information and transaction
        pack state (True for packed)."""
235
        raise NotImplementedError
236

237 238 239 240 241 242 243 244 245 246
    def getTransactionUndoData(self, tid, undone_tid,
            getObjectFromTransaction):
        """Undo transaction with "undone_tid" tid. "tid" is the tid of the
        transaction in which the undo happens.
        getObjectFromTransaction is a callback allowing to find object data
        stored to this storage in the same transaction (it is useful for
        example when undoing twice in the same transaction).
        """
        raise NotImplementedError

Grégory Wisniewski's avatar
Grégory Wisniewski committed
247
    def finishTransaction(self, tid):
248 249
        """Finish a transaction specified by a given ID, by moving
        temporarily data to a finished area."""
250
        raise NotImplementedError
251 252 253 254 255

    def deleteTransaction(self, tid, all = False):
        """Delete a transaction specified by a given ID from a temporarily
        area. If all is true, it must be deleted even from a finished
        area."""
256
        raise NotImplementedError
257 258 259 260 261 262 263

    def getTransaction(self, tid, all = False):
        """Return a tuple of the list of OIDs, user information,
        a description, and extension information, for a given transaction
        ID. If there is no such transaction ID in a database, return None.
        If all is true, the transaction must be searched from a temporary
        area as well."""
264
        raise NotImplementedError
265 266 267 268 269

    def getOIDList(self, offset, length, num_partitions, partition_list):
        """Return a list of OIDs in descending order from an offset,
        at most the specified length. The list of partitions are passed
        to filter out non-applicable TIDs."""
270
        raise NotImplementedError
271

272
    def getObjectHistory(self, oid, offset = 0, length = 1):
273
        """Return a list of serials and sizes for a given object ID.
274 275 276
        The length specifies the maximum size of such a list. Result starts
        with latest serial, and the list must be sorted in descending order.
        If there is no such object ID in a database, return None."""
277
        raise NotImplementedError
278 279

    def getTIDList(self, offset, length, num_partitions, partition_list):
280 281 282 283 284 285 286
        """Return a list of TIDs in ascending order from an offset,
        at most the specified length. The list of partitions are passed
        to filter out non-applicable TIDs."""
        raise NotImplementedError

    def getReplicationTIDList(self, offset, length, num_partitions,
        partition_list):
287 288 289
        """Return a list of TIDs in descending order from an offset,
        at most the specified length. The list of partitions are passed
        to filter out non-applicable TIDs."""
290
        raise NotImplementedError
291 292 293 294

    def getTIDListPresent(self, tid_list):
        """Return a list of TIDs which are present in a database among
        the given list."""
295
        raise NotImplementedError
296 297 298 299

    def getSerialListPresent(self, oid, serial_list):
        """Return a list of serials which are present in a database among
        the given list."""
300
        raise NotImplementedError
301