Commit 6c500078 authored by Vincent Pelletier's avatar Vincent Pelletier

Document an RC bug on tpc_finish.

Also, change the way TTIDs are generated in preparation for that bug's fix:
we will need TTID to be monotonous across master restarts and TID generator
provides this feature.
parent fb6ffb7b
...@@ -19,6 +19,13 @@ RC = Release Critical (for next release) ...@@ -19,6 +19,13 @@ RC = Release Critical (for next release)
RC - Review XXX in the code (CODE) RC - Review XXX in the code (CODE)
RC - Review TODO in the code (CODE) RC - Review TODO in the code (CODE)
RC - Review output of pylint (CODE) RC - Review output of pylint (CODE)
RC - tpc_finish might raise while transaction got successfully committed.
This can happen if it gets disconnected from primary master while waiting
for AnswerFinishTransaction after primary received it and hence will
commit transaction independently from client presence. Client could
legitimaltely think transaction is not committed, and might decide to
retry. To solve this, a TTID column must be added in storage nodes so
client can know if his TTID got successfuly committed.
- Keep-alive (HIGH AVAILABILITY) (implemented, to be reviewed and tested) - Keep-alive (HIGH AVAILABILITY) (implemented, to be reviewed and tested)
Consider the need to implement a keep-alive system (packets sent Consider the need to implement a keep-alive system (packets sent
automatically when there is no activity on the connection for a period automatically when there is no activity on the connection for a period
......
...@@ -219,7 +219,6 @@ class TransactionManager(object): ...@@ -219,7 +219,6 @@ class TransactionManager(object):
Manage current transactions Manage current transactions
""" """
_last_tid = ZERO_TID _last_tid = ZERO_TID
_next_ttid = 0
def __init__(self, on_commit): def __init__(self, on_commit):
# ttid -> transaction # ttid -> transaction
...@@ -270,18 +269,17 @@ class TransactionManager(object): ...@@ -270,18 +269,17 @@ class TransactionManager(object):
def getLastOID(self): def getLastOID(self):
return self._last_oid return self._last_oid
def _nextTID(self, ttid, divisor): def _nextTID(self, ttid=None, divisor=None):
""" """
Compute the next TID based on the current time and check collisions. Compute the next TID based on the current time and check collisions.
Also, adjust it so that Also, if ttid is not None, divisor is mandatory adjust it so that
tid % divisor == ttid % divisor tid % divisor == ttid % divisor
while preserving while preserving
min_tid < tid min_tid < tid
If ttid is None, divisor is ignored.
When constraints allow, prefer decreasing generated TID, to avoid When constraints allow, prefer decreasing generated TID, to avoid
fast-forwarding to future dates. fast-forwarding to future dates.
""" """
assert isinstance(ttid, basestring), repr(ttid)
assert isinstance(divisor, (int, long)), repr(divisor)
tm = time() tm = time()
gmt = gmtime(tm) gmt = gmtime(tm)
# See leap second handling in epoch: # See leap second handling in epoch:
...@@ -299,21 +297,24 @@ class TransactionManager(object): ...@@ -299,21 +297,24 @@ class TransactionManager(object):
try_decrease = False try_decrease = False
else: else:
try_decrease = True try_decrease = True
ref_remainder = u64(ttid) % divisor if ttid is not None:
remainder = u64(tid) % divisor assert isinstance(ttid, basestring), repr(ttid)
if ref_remainder != remainder: assert isinstance(divisor, (int, long)), repr(divisor)
if try_decrease: ref_remainder = u64(ttid) % divisor
new_tid = addTID(tid, ref_remainder - divisor - remainder) remainder = u64(tid) % divisor
assert u64(new_tid) % divisor == ref_remainder, (dump(new_tid), if ref_remainder != remainder:
ref_remainder) if try_decrease:
if new_tid <= min_tid: new_tid = addTID(tid, ref_remainder - divisor - remainder)
new_tid = addTID(new_tid, divisor) assert u64(new_tid) % divisor == ref_remainder, (dump(new_tid),
else: ref_remainder)
if ref_remainder > remainder: if new_tid <= min_tid:
ref_remainder += divisor new_tid = addTID(new_tid, divisor)
new_tid = addTID(tid, ref_remainder - remainder) else:
assert min_tid < new_tid, (dump(min_tid), dump(tid), dump(new_tid)) if ref_remainder > remainder:
tid = new_tid ref_remainder += divisor
new_tid = addTID(tid, ref_remainder - remainder)
assert min_tid < new_tid, (dump(min_tid), dump(tid), dump(new_tid))
tid = new_tid
self._last_tid = tid self._last_tid = tid
return self._last_tid return self._last_tid
...@@ -329,14 +330,6 @@ class TransactionManager(object): ...@@ -329,14 +330,6 @@ class TransactionManager(object):
""" """
self._last_tid = max(self._last_tid, tid) self._last_tid = max(self._last_tid, tid)
def getTTID(self):
"""
Generate a temporary TID, to be used only during a single node's
2PC.
"""
self._next_ttid += 1
return p64(self._next_ttid)
def reset(self): def reset(self):
""" """
Discard all manager content Discard all manager content
...@@ -367,7 +360,7 @@ class TransactionManager(object): ...@@ -367,7 +360,7 @@ class TransactionManager(object):
""" """
if tid is None: if tid is None:
# No TID requested, generate a temporary one # No TID requested, generate a temporary one
ttid = self.getTTID() ttid = self._nextTID()
else: else:
# Use of specific TID requested, queue it immediately and update # Use of specific TID requested, queue it immediately and update
# last TID. # last TID.
......
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