def store(self, oid, serial, data, version, transaction): if transaction is not self._transaction: raise POSException.StorageTransactionError(self, transaction) assert not version self._lock_acquire() try: if oid in self._index: oserial = self._index[oid] if serial != oserial: newdata = self.tryToResolveConflict( oid, oserial, serial, data) if not newdata: raise POSException.ConflictError( oid=oid, serials=(oserial, serial), data=data) else: data = newdata else: oserial = serial newserial = self._tid self._tmp.append((oid, data)) return serial == oserial and newserial or ResolvedSerial finally: self._lock_release()
def tpc_begin(self, txn, tid=None, status=' '): """Storage API: begin a transaction.""" if self._is_read_only: raise POSException.ReadOnlyError() try: tbuf = txn.data(self) except AttributeError: # Gaaaa. This is a recovery transaction. Work around this # until we can think of something better. XXX tb = {} txn.data = tb.__getitem__ txn.set_data = tb.__setitem__ except KeyError: pass else: if tbuf is not None: raise POSException.StorageTransactionError( "Duplicate tpc_begin calls for same transaction") txn.set_data(self, TransactionBuffer(self._connection_generation)) # XXX we'd like to allow multiple transactions at a time at some point, # but for now, due to server limitations, TCBOO. self._commit_lock.acquire() self._tbuf = txn.data(self) try: self._async('tpc_begin', id(txn), txn.user, txn.description, txn.extension, tid, status) except ClientDisconnected: self.tpc_end(txn) raise
def store(self, oid, serial, data, version, transaction): if transaction is not self._transaction: raise POSException.StorageTransactionError(self, transaction) if version: # we allow a version to be in use although we don't # support versions in the storage. LOG.debug('versions in use with TemporaryStorage although Temporary ' 'Storage doesnt support versions') self._lock_acquire() try: if self._index.has_key(oid): oserial=self._index[oid] if serial != oserial: newdata = self.tryToResolveConflict( oid, oserial, serial, data) if not newdata: raise POSException.ConflictError( oid=oid, serials=(oserial, serial), data=data) else: data = newdata else: oserial = serial newserial=self._tid self._tmp.append((oid, data)) return serial == oserial and newserial or ResolvedSerial finally: self._lock_release()
def _check_trans(self, trans): """Internal helper to check a transaction argument for sanity.""" if self._is_read_only: raise POSException.ReadOnlyError() if self._transaction is not trans: raise POSException.StorageTransactionError(self._transaction, trans)
def store(self, oid, serial, 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: if oid in self._index: oserial = self._index[oid][:8] if serial != oserial: rdata = self.tryToResolveConflict(oid, oserial, serial, data) if rdata is None: raise POSException.ConflictError(oid=oid, serials=(oserial, serial), data=data) else: data = rdata self._tindex[oid] = self._tid + data finally: self._lock_release() return self._tid
def commitVersion(self, src, dest, transaction): if transaction is not self._transaction: raise POSException.StorageTransactionError(self, transaction) if not src: raise POSException.VersionCommitError("Invalid source version") if src == dest: raise POSException.VersionCommitError( "Can't commit to same version: %s" % repr(src)) self._lock_acquire() try: v = self._vindex.get(src) if v is None: return newserial = self._tid tindex = self._tindex oids = [] for r in v.values(): oid, pre, vdata, p, tid = r assert vdata is not None oids.append(oid) if dest: new_vdata = dest, vdata[1] else: new_vdata = None tindex.append([oid, r, new_vdata, p, self._tid]) return self._tid, oids finally: self._lock_release()
def abortVersion(self, src, transaction): if transaction is not self._transaction: raise POSException.StorageTransactionError(self, transaction) if not src: raise POSException.VersionCommitError("Invalid version") self._lock_acquire() try: v = self._vindex.get(src, None) if not v: return oids = [] for r in v.values(): oid, pre, (version, nv), p, tid = r oids.append(oid) if nv: oid, pre, vdata, p, tid = nv self._tindex.append([oid, r, None, p, self._tid]) else: # effectively, delete the thing self._tindex.append([oid, r, None, None, self._tid]) return self._tid, oids finally: self._lock_release()
def checkCurrentSerialInTransaction(self, oid, serial, transaction): if transaction is not self._transaction: raise POSException.StorageTransactionError(self, transaction) committed_tid = self.getTid(oid) if committed_tid != serial: raise POSException.ReadConflictError( oid=oid, serials=(committed_tid, serial))
def tpc_vote(self, transaction): self._lock_acquire() try: if transaction is not self._transaction: raise POSException.StorageTransactionError( "tpc_vote called with wrong transaction") self._vote() finally: self._lock_release()
def store(self, oid, serial, data, v, txn): if txn is not self._transaction: raise POSException.StorageTransactionError(self, txn) assert not v if self._cur.get(oid) != serial: if not (serial is None or self._cur.get(oid) in [None, z64]): raise POSException.ConflictError( oid=oid, serials=(self._cur.get(oid), serial), data=data) self._txn.store(oid, data) return self._tid
def store(self, oid, serial, data, version, transaction): if transaction is not self._transaction: raise POSException.StorageTransactionError(self, transaction) self._lock_acquire() try: old = self._index.get(oid, None) if old is None: # Hm, nothing here, check the base version: if self._base: try: p, tid = self._base.load(oid, '') except KeyError: pass else: old = oid, None, None, p, tid nv=None if old: oid, pre, vdata, p, tid = old if vdata: if vdata[0] != version: raise POSException.VersionLockError(oid) nv=vdata[1] else: nv=old if serial != tid: raise POSException.ConflictError( oid=oid, serials=(tid, serial), data=data) r = [oid, old, version and (version, nv) or None, data, self._tid] self._tindex.append(r) s=self._tsize s=s+72+(data and (16+len(data)) or 4) if version: s=s+32+len(version) if self._quota is not None and s > self._quota: raise POSException.StorageError( '''<b>Quota Exceeded</b><br> The maximum quota for this demonstration storage has been exceeded.<br>Have a nice day.''') finally: self._lock_release() return self._tid
def _check_trans(self, trans, meth): """Internal helper to check a transaction argument for sanity.""" if self._is_read_only: raise POSException.ReadOnlyError() try: buf = trans.data(self) except KeyError: buf = None if buf is None: raise POSException.StorageTransactionError( "Transaction not committing", meth, trans) if buf.connection_generation != self._connection_generation: # We were disconnected, so this one is poisoned raise ClientDisconnected(meth, 'on a disconnected transaction') return buf
def store(self, oid, serial, data, version, transaction): if transaction is not self._transaction: raise POSException.StorageTransactionError(self, transaction) assert not version with self._lock: if oid in self._index: oserial = self._index[oid] if serial != oserial: newdata = self.tryToResolveConflict( oid, oserial, serial, data) if not newdata: raise POSException.ConflictError(oid=oid, serials=(oserial, serial), data=data) else: data = newdata else: oserial = serial self._tmp.append((oid, data))
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 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 commitVersion(self, src, dest, transaction): if transaction is not self._transaction: raise POSException.StorageTransactionError(self, transaction) return self._tid, []
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