def load(self, oid, version=''): pos = self.index.get(oid) if pos is None: return self._storage.load(oid) self._file.seek(pos) h = self._file.read(8) oidlen = u64(h) read_oid = self._file.read(oidlen) if read_oid != oid: raise POSException.StorageSystemError('Bad temporary storage') h = self._file.read(16) size = u64(h[8:]) serial = h[:8] return self._file.read(size), serial
def tpc_begin(self, transaction, tid=None, status=' '): if self._is_read_only: raise POSException.ReadOnlyError() self._lock_acquire() try: if self._transaction is transaction: raise POSException.StorageTransactionError( "Duplicate tpc_begin calls for same transaction") self._lock_release() self._commit_lock_acquire() self._lock_acquire() self._transaction = transaction self._clear_temp() user = transaction.user desc = transaction.description ext = transaction._extension if ext: ext = cPickle.dumps(ext, 1) else: ext = "" self._ude = user, desc, ext if tid is None: now = time.time() t = TimeStamp(*(time.gmtime(now)[:5] + (now % 60,))) self._ts = t = t.laterThan(self._ts) self._tid = repr(t) else: self._ts = TimeStamp(tid) self._tid = tid self._tstatus = status self._begin(self._tid, user, desc, ext) finally: self._lock_release()
def __init__(self, name='Demo Storage', base=None, quota=None): BaseStorage.__init__(self, name, base) # We use a BTree because the items are sorted! self._data = OOBTree.OOBTree() self._index = {} self._vindex = {} self._base = base self._size = 0 self._quota = quota self._ltid = None self._clear_temp() if base is not None and base.versions(): raise POSException.StorageError( "Demo base storage has version data")
def loadSerial(self, oid, serial, marker=[]): """ this is only useful to make conflict resolution work. It does not actually implement all the semantics that a revisioning storage needs! """ self._lock_acquire() try: data = self._conflict_cache.get((oid, serial), marker) if data is marker: # XXX Need 2 serialnos to pass them to ConflictError-- # the old and the new raise POSException.ConflictError(oid=oid) else: return data[0] # data here is actually (data, t) finally: self._lock_release()
def new_oid(self): if self._is_read_only: raise POSException.ReadOnlyError() self._lock_acquire() try: last = self._oid d = ord(last[-1]) if d < 255: # fast path for the usual case last = last[:-1] + chr(d + 1) else: # there's a carry out of the last byte last_as_long, = _structunpack(">Q", last) last = _structpack(">Q", last_as_long + 1) self._oid = last return last finally: self._lock_release()
def load(self, oid, version=''): with self._lock: try: s = self._index[oid] p = self._opickle[oid] return p, s # pickle, serial except KeyError: # this oid was probably garbage collected while a thread held # on to an object that had a reference to it; we can probably # force the loader to sync their connection by raising a # ConflictError (at least if Zope is the loader, because it # will resync its connection on a retry). This isn't # perfect because the length of the recently gc'ed oids list # is finite and could be overrun through a mass gc, but it # should be adequate in common-case usage. if oid in self._recently_gc_oids: raise POSException.ConflictError(oid=oid) else: raise
def tpc_finish(self, transaction, f=None): # It's important that the storage calls the function we pass # while it still has its lock. We don't want another thread # to be able to read any updated data until we've had a chance # to send an invalidation message to all of the other # connections! self._lock_acquire() try: if transaction is not self._transaction: raise POSException.StorageTransactionError( "tpc_finish called with wrong transaction") try: if f is not None: f(self._tid) u, d, e = self._ude self._finish(self._tid, u, d, e) self._clear_temp() finally: self._ude = None self._transaction = None self._commit_lock_release() finally: self._lock_release()
def load(self, oid, version=''): result = self.loadBefore(oid, utils.maxtid) if result is None: raise POSException.POSKeyError(oid) return result[:2]
def loadSerial(self, oid, serial): raise POSException.Unsupported( "Retrieval of historical revisions is not supported")
def pack(self, t, referencesf): if self._is_read_only: raise POSException.ReadOnlyError()
def undo(self, transaction_id, txn): if self._is_read_only: raise POSException.ReadOnlyError() raise POSException.UndoError('non-undoable transaction')
def loadEx(self, oid, version): try: data, serial, _ = self.app.load(oid) except NEOStorageNotFoundError: raise POSException.POSKeyError(oid) return data, serial, ''
def commitVersion(self, src, dest, transaction): if transaction is not self._transaction: raise POSException.StorageTransactionError(self, transaction) return self._tid, []
def history(self, oid, *args, **kw): try: return self.app.history(oid, *args, **kw) except NEOStorageNotFoundError: raise POSException.POSKeyError(oid)
def loadSerial(self, oid, serial): try: return self.app.load(oid, serial)[0] except NEOStorageNotFoundError: raise POSException.POSKeyError(oid)
def raiseReadOnlyError(*args, **kw): raise POSException.ReadOnlyError()
def store(self, oid, h64, data, version, transaction): if transaction is not self._transaction: raise POSException.StorageTransactionError(self, transaction) if version: raise POSException.Unsupported, "Versions aren't supported" self._lock_acquire() try: self.conf_resource.access(self) # Update configuration # First detect conflicts. # The "h64" argument, if its value is not 0, # was previously generated by hash64(). if h64 == HASH0: # Writing a new object. is_new = True else: # Overwriting an old object. Use the hash to verify # that the new data was derived from the old data. is_new = False event, old_c, old_state, old_hash = self._gwio.load(oid) old_h64 = self.hash64(old_hash) if h64 != old_h64: h = None if self.debug_conflicts: h = self._loaded_hashes.get(oid) if h is None: h = h64 old_hash = old_h64 error = ("Storing %s based on old data. %s != %s." % (repr(oid), repr(h), repr(old_hash))) if self.debug_conflicts: # Expose the error for debugging.. raise RuntimeError(error) else: # Use normal ZODB conflict errors. raise POSException.ConflictError(error) # Now unpickle and store the data. file = StringIO(data) u = Unpickler(file) classification = u.load() state = u.load() event, new_hash = self._gwio.store(oid, classification, state, is_new) new_h64 = self.hash64(new_hash) if self.debug_conflicts: self._loaded_hashes[oid] = new_hash # Remember that this OID changed (for scanning) tid = self.getTransactionId() t = self.changed.get(tid) if t is None: t = {} self.changed[tid] = t t[oid] = 1 finally: self._lock_release() return new_h64