public Long safeToRecover ( ) { boolean safe = true ; for ( LastInitiatorData data : m_initiatorData . values ( ) ) { final long lastSeenTxnId = data . m_lastSeenTxnId ; if ( lastSeenTxnId == DtxnConstants . DUMMY_LAST_SEEN_TXN_ID ) { safe = false ; } } if ( ! safe ) { return null ; } OrderableTransaction next = peek ( ) ; if ( next == null ) { // no work - have heard from all initiators. use a heartbeat if ( m_state == QueueState . BLOCKED_EMPTY ) { return m_newestCandidateTransaction ; } // waiting for some txn to be 2pc to this site. else if ( m_state == QueueState . BLOCKED_SAFETY ) { return null ; } else if ( m_state == QueueState . BLOCKED_ORDERING ) { return null ; } m_recoveryLog . error ( "Unexpected RPQ state " + m_state + " when attempting to start recovery at " + " the source site. Consider killing the recovering node and trying again" ) ; return null ; // unreachable } else { // bingo - have a real transaction to return as the recovery point return next . txnId ; } }
Determine if it is safe to recover and if it is what txnid it is safe to recover at . Recovery is initiated by the recovering source partition . It can t be initiated until the recovering partition has heard from every initiator . This is because it is not possible to pick a point in the global txn ordering for the recovery to start at where all subsequent procedure invocations that need to be applied after recovery are available unless every initiator has been heard from .