Commit f2f0e7be authored by Grégory Wisniewski's avatar Grégory Wisniewski

Implement support of a new transaction with a TID supplied by the client.


git-svn-id: https://svn.erp5.org/repos/neo/branches/prototype3@1010 71dcc9de-d417-0410-9af5-da40c76e7ee4
parent 8c830924
...@@ -659,14 +659,13 @@ class Application(object): ...@@ -659,14 +659,13 @@ class Application(object):
if self.local_var.txn is transaction: if self.local_var.txn is transaction:
# We already begin the same transaction # We already begin the same transaction
return return
# Get a new transaction id if necessary # ask the primary master to start a transaction, if no tid is supplied,
if tid is None: # the master will supply us one. Otherwise the requested tid will be
self.local_var.tid = None # used if possible.
self._askPrimary(protocol.askBeginTransaction()) self.local_var.tid = None
if self.local_var.tid is None: self._askPrimary(protocol.askBeginTransaction(tid))
raise NEOStorageError('tpc_begin failed') if self.local_var.tid is None:
else: raise NEOStorageError('tpc_begin failed')
self.local_var.tid = tid
self.local_var.txn = transaction self.local_var.txn = transaction
......
...@@ -236,7 +236,7 @@ class EventHandler(object): ...@@ -236,7 +236,7 @@ class EventHandler(object):
def handleCommitTransaction(self, conn, packet, tid): def handleCommitTransaction(self, conn, packet, tid):
raise UnexpectedPacketError raise UnexpectedPacketError
def handleAskBeginTransaction(self, conn, packet): def handleAskBeginTransaction(self, conn, packet, tid):
raise UnexpectedPacketError raise UnexpectedPacketError
def handleAnswerBeginTransaction(self, conn, packet, tid): def handleAnswerBeginTransaction(self, conn, packet, tid):
......
...@@ -80,7 +80,7 @@ class MasterHandler(EventHandler): ...@@ -80,7 +80,7 @@ class MasterHandler(EventHandler):
def handleOidNotFound(self, conn, packet, message): def handleOidNotFound(self, conn, packet, message):
logging.error('ignoring OID Not Found in %s' % self.__class__.__name__) logging.error('ignoring OID Not Found in %s' % self.__class__.__name__)
def handleAskBeginTransaction(self, conn, packet): def handleAskBeginTransaction(self, conn, packet, tid):
logging.error('ignoring Ask New TID in %s' % self.__class__.__name__) logging.error('ignoring Ask New TID in %s' % self.__class__.__name__)
def handleAskNewOIDs(self, conn, packet, num_oids): def handleAskNewOIDs(self, conn, packet, num_oids):
......
...@@ -94,9 +94,15 @@ class ClientServiceHandler(BaseServiceHandler): ...@@ -94,9 +94,15 @@ class ClientServiceHandler(BaseServiceHandler):
except KeyError: except KeyError:
logging.warn('aborting transaction %s does not exist', dump(tid)) logging.warn('aborting transaction %s does not exist', dump(tid))
def handleAskBeginTransaction(self, conn, packet): def handleAskBeginTransaction(self, conn, packet, tid):
app = self.app app = self.app
tid = app.getNextTID() if tid is not None and tid < app.ltid:
# supplied TID is in the past
raise protocol.ProtocolError('invalid TID requested')
if tid is None:
# give a new transaction ID
tid = app.getNextTID()
app.ltid = tid
app.finishing_transaction_dict[tid] = FinishingTransaction(conn) app.finishing_transaction_dict[tid] = FinishingTransaction(conn)
conn.answer(protocol.answerBeginTransaction(tid), packet) conn.answer(protocol.answerBeginTransaction(tid), packet)
......
...@@ -36,7 +36,7 @@ class ShutdownHandler(BaseServiceHandler): ...@@ -36,7 +36,7 @@ class ShutdownHandler(BaseServiceHandler):
@decorators.identification_required @decorators.identification_required
@decorators.restrict_node_types(CLIENT_NODE_TYPE) @decorators.restrict_node_types(CLIENT_NODE_TYPE)
def handleAskBeginTransaction(self, conn, packet): def handleAskBeginTransaction(self, conn, packet, tid):
logging.error('reject any new demand for new tid') logging.error('reject any new demand for new tid')
raise protocol.ProtocolError('cluster is shutting down') raise protocol.ProtocolError('cluster is shutting down')
......
...@@ -172,10 +172,10 @@ packet_types = Enum({ ...@@ -172,10 +172,10 @@ packet_types = Enum({
# Commit a transaction. PM -> S. # Commit a transaction. PM -> S.
'COMMIT_TRANSACTION': 0x0011, 'COMMIT_TRANSACTION': 0x0011,
# Ask a new transaction ID. C -> PM. # Ask to begin a new transaction. C -> PM.
'ASK_BEGIN_TRANSACTION': 0x0012, 'ASK_BEGIN_TRANSACTION': 0x0012,
# Answer a new transaction ID. PM -> C. # Answer when a transaction begin, give a TID if necessary. PM -> C.
'ANSWER_BEGIN_TRANSACTION': 0x8012, 'ANSWER_BEGIN_TRANSACTION': 0x8012,
# Finish a transaction. C -> PM. # Finish a transaction. C -> PM.
...@@ -531,6 +531,16 @@ def _encodePTID(ptid): ...@@ -531,6 +531,16 @@ def _encodePTID(ptid):
return INVALID_PTID return INVALID_PTID
return ptid return ptid
def _decodeTID(tid):
if tid == INVALID_TID:
return None
return tid
def _encodeTID(tid):
if tid is None:
return INVALID_TID
return tid
def _readString(buf, name, offset=0): def _readString(buf, name, offset=0):
buf = buf[offset:] buf = buf[offset:]
(size, ) = unpack('!L', buf[:4]) (size, ) = unpack('!L', buf[:4])
...@@ -752,12 +762,15 @@ decode_table[COMMIT_TRANSACTION] = _decodeCommitTransaction ...@@ -752,12 +762,15 @@ decode_table[COMMIT_TRANSACTION] = _decodeCommitTransaction
@handle_errors @handle_errors
def _decodeAskBeginTransaction(body): def _decodeAskBeginTransaction(body):
pass (tid, ) = unpack('8s', body)
tid = _decodeTID(tid)
return (tid, )
decode_table[ASK_BEGIN_TRANSACTION] = _decodeAskBeginTransaction decode_table[ASK_BEGIN_TRANSACTION] = _decodeAskBeginTransaction
@handle_errors @handle_errors
def _decodeAnswerBeginTransaction(body): def _decodeAnswerBeginTransaction(body):
(tid, ) = unpack('8s', body) (tid, ) = unpack('8s', body)
tid = _decodeTID(tid)
return (tid, ) return (tid, )
decode_table[ANSWER_BEGIN_TRANSACTION] = _decodeAnswerBeginTransaction decode_table[ANSWER_BEGIN_TRANSACTION] = _decodeAnswerBeginTransaction
...@@ -870,8 +883,7 @@ def _decodeAskObject(body): ...@@ -870,8 +883,7 @@ def _decodeAskObject(body):
(oid, serial, tid) = unpack('8s8s8s', body) (oid, serial, tid) = unpack('8s8s8s', body)
if serial == INVALID_TID: if serial == INVALID_TID:
serial = None serial = None
if tid == INVALID_TID: tid = _decodeTID(tid)
tid = None
return (oid, serial, tid) return (oid, serial, tid)
decode_table[ASK_OBJECT] = _decodeAskObject decode_table[ASK_OBJECT] = _decodeAskObject
...@@ -1156,8 +1168,7 @@ def answerLastIDs(loid, ltid, lptid): ...@@ -1156,8 +1168,7 @@ def answerLastIDs(loid, ltid, lptid):
# packet when no last IDs are known # packet when no last IDs are known
if loid is None: if loid is None:
loid = INVALID_OID loid = INVALID_OID
if ltid is None: ltid = _encodeTID(ltid)
ltid = INVALID_TID
lptid = _encodePTID(lptid) lptid = _encodePTID(lptid)
return Packet(ANSWER_LAST_IDS, loid + ltid + lptid) return Packet(ANSWER_LAST_IDS, loid + ltid + lptid)
...@@ -1226,10 +1237,12 @@ def deleteTransaction(tid): ...@@ -1226,10 +1237,12 @@ def deleteTransaction(tid):
def commitTransaction(tid): def commitTransaction(tid):
return Packet(COMMIT_TRANSACTION, tid) return Packet(COMMIT_TRANSACTION, tid)
def askBeginTransaction(): def askBeginTransaction(tid):
return Packet(ASK_BEGIN_TRANSACTION) tid = _encodeTID(tid)
return Packet(ASK_BEGIN_TRANSACTION, tid)
def answerBeginTransaction(tid): def answerBeginTransaction(tid):
tid = _encodeTID(tid)
return Packet(ANSWER_BEGIN_TRANSACTION, tid) return Packet(ANSWER_BEGIN_TRANSACTION, tid)
def askNewOIDs(num_oids): def askNewOIDs(num_oids):
...@@ -1297,11 +1310,8 @@ def answerStoreObject(conflicting, oid, serial): ...@@ -1297,11 +1310,8 @@ def answerStoreObject(conflicting, oid, serial):
return Packet(ANSWER_STORE_OBJECT, body) return Packet(ANSWER_STORE_OBJECT, body)
def askObject(oid, serial, tid): def askObject(oid, serial, tid):
if tid is None: tid = _encodeTID(tid)
# tid can be unspecified serial = _encodeTID(serial) # serial is the previous TID
tid = INVALID_TID
if serial is None:
serial = INVALID_TID
return Packet(ASK_OBJECT, pack('!8s8s8s', oid, serial, tid)) return Packet(ASK_OBJECT, pack('!8s8s8s', oid, serial, tid))
def answerObject(oid, serial_start, serial_end, compression, def answerObject(oid, serial_start, serial_end, compression,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment