BUG-5280: fix transaction seal atomicity
AbstractProxyTransaction.seal() indicates that the user is done
with the transaction. This transition needs to be atomically
propagated to successors on reconnect, such that the user will
always observe sealed proxies. More importantly this state
is propagated to parent ProxyHistory, where it drives the state
machine in ClientProxyHistory -- and failing to mark the successor
as sealed will wreck that.
Unfortunately an AbstractProxyTransaction does not forward all
of the state on seal(), but rather when the resulting commit
cohort initiates commit -- which means we have to perform three-way
synchronization between seal()/(can|direct)Commit/finishReconnect,
to ensure we flush state towards the backend exactly once.
To do that, we guard the methods involved with locking for split
them into fast/slow paths and add an explicit flushState() method
by which subclasses forward their current unsent state to their
successor. This solution is correct but a bit heavy-handed, so it
will be further optimized in a follow-up patch.
Change-Id: Id5f156dc18faef5b9184c3e2e3d24f7af1b18841
Signed-off-by: Robert Varga <rovarga@cisco.com>