class ClientOperationHandler(EventHandler): def askTransactionInformation(self, conn, tid): t = self.app.dm.getTransaction(tid) if t is None: p = Errors.TidNotFound('%s does not exist' % dump(tid)) else: p = Packets.AnswerTransactionInformation(tid, t[1], t[2], t[3], t[4], t[0]) conn.answer(p) def askObject(self, conn, oid, serial, tid): app = self.app if app.tm.loadLocked(oid): # Delay the response. app.queueEvent(self.askObject, conn, (oid, serial, tid)) return o = app.dm.getObject(oid, serial, tid) try: serial, next_serial, compression, checksum, data, data_serial = o except TypeError: p = (Errors.OidDoesNotExist if o is None else Errors.OidNotFound)(dump(oid)) else: if checksum is None: checksum = ZERO_HASH data = '' p = Packets.AnswerObject(oid, serial, next_serial, compression, checksum, data, data_serial) conn.answer(p) def connectionLost(self, conn, new_state): uuid = conn.getUUID() node = self.app.nm.getByUUID(uuid) if self.app.listening_conn: # if running assert node is not None, conn self.app.nm.remove(node) def abortTransaction(self, conn, ttid): self.app.tm.abort(ttid) def askStoreTransaction(self, conn, ttid, *txn_info): self.app.tm.register(conn.getUUID(), ttid) self.app.tm.vote(ttid, txn_info) conn.answer(Packets.AnswerStoreTransaction()) def askVoteTransaction(self, conn, ttid): self.app.tm.vote(ttid) conn.answer(Packets.AnswerVoteTransaction()) def _askStoreObject(self, conn, oid, serial, compression, checksum, data, data_serial, ttid, unlock, request_time): try: self.app.tm.storeObject(ttid, serial, oid, compression, checksum, data, data_serial, unlock) except ConflictError, err: # resolvable or not conn.answer(Packets.AnswerStoreObject(1, oid, err.getTID())) except DelayedError: # locked by a previous transaction, retry later # If we are unlocking, we want queueEvent to raise # AlreadyPendingError, to avoid making lcient wait for an unneeded # response. try: self.app.queueEvent(self._askStoreObject, conn, (oid, serial, compression, checksum, data, data_serial, ttid, unlock, request_time), key=(oid, ttid), raise_on_duplicate=unlock) except AlreadyPendingError: conn.answer(Errors.AlreadyPending(dump(oid)))
self._askCheckCurrentSerial(conn, ttid, serial, oid, time.time()) def _askCheckCurrentSerial(self, conn, ttid, serial, oid, request_time): try: self.app.tm.checkCurrentSerial(ttid, serial, oid) except ConflictError, err: # resolvable or not conn.answer(Packets.AnswerCheckCurrentSerial(1, oid, err.getTID())) except DelayedError: # locked by a previous transaction, retry later try: self.app.queueEvent(self._askCheckCurrentSerial, conn, (ttid, serial, oid, request_time), key=(oid, ttid)) except AlreadyPendingError: conn.answer(Errors.AlreadyPending(dump(oid))) except NotRegisteredError: # transaction was aborted, cancel this event logging.info('Forget serial check of %s:%s by %s delayed by %s', dump(oid), dump(serial), dump(ttid), dump(self.app.tm.getLockingTID(oid))) # send an answer as the client side is waiting for it conn.answer(Packets.AnswerCheckCurrentSerial(0, oid, serial)) else: if SLOW_STORE is not None: duration = time.time() - request_time if duration > SLOW_STORE: logging.info('CheckCurrentSerial delay: %.02fs', duration) conn.answer(Packets.AnswerCheckCurrentSerial(0, oid, serial))