private void handleLogRequest ( VoltMessage message ) { Iv2RepairLogRequestMessage req = ( Iv2RepairLogRequestMessage ) message ; // It is possible for a dead host to queue messages after a repair request is processed // so make sure this can't happen by re-queuing this message after we know the dead host is gone // Since we are not checking validateForeignHostId on the PicoNetwork thread, it is possible for // the PicoNetwork thread to validateForeignHostId and queue a message behind this repair message. // Further, we loose visibility to the ForeignHost as soon as HostMessenger marks the host invalid // even though the PicoNetwork thread could still be alive so we will skeptically int deadHostId = req . getDeadHostId ( ) ; if ( deadHostId != Integer . MAX_VALUE ) { if ( m_messenger . canCompleteRepair ( deadHostId ) ) { // Make sure we are the last in the task queue when we know the ForeignHost is gone req . disableDeadHostCheck ( ) ; deliver ( message ) ; } else { if ( req . getRepairRetryCount ( ) > 100 && req . getRepairRetryCount ( ) % 100 == 0 ) { hostLog . warn ( "Repair Request for dead host " + deadHostId + " has not been processed yet because connection has not closed" ) ; } Runnable retryRepair = new Runnable ( ) { @ Override public void run ( ) { InitiatorMailbox . this . deliver ( message ) ; } } ; VoltDB . instance ( ) . scheduleWork ( retryRepair , 10 , - 1 , TimeUnit . MILLISECONDS ) ; // the repair message will be resubmitted shortly when the ForeignHosts to the dead host have been removed } return ; } List < Iv2RepairLogResponseMessage > logs = m_repairLog . contents ( req . getRequestId ( ) , req . isMPIRequest ( ) ) ; if ( req . isMPIRequest ( ) ) { m_scheduler . cleanupTransactionBacklogOnRepair ( ) ; } for ( Iv2RepairLogResponseMessage log : logs ) { send ( message . m_sourceHSId , log ) ; } }
Produce the repair log . This is idempotent .