github.com/okex/exchain@v1.8.0/libs/tendermint/state/execution_async_db.go (about) 1 package state 2 3 import ( 4 "sync" 5 "time" 6 ) 7 8 type asyncDBContext struct { 9 // switch to turn on async save abciResponse and state 10 isAsyncSaveDB bool 11 // channel to write abciResponse async 12 abciResponseQueue chan abciResponse 13 /// channel to write state async 14 stateQueue chan State 15 // channel to feed back height of saved abci response and stat response 16 asyncFeedbackQueue chan int64 17 // flag to avoid waiting async state result for the first block 18 isWaitingLastBlock bool 19 //flag to avoid stop twice 20 isAsyncQueueStop bool 21 //wait group for quiting 22 wg sync.WaitGroup 23 } 24 25 const ( 26 MAXCHAN_LEN = 2 27 FEEDBACK_LEN = 2 28 QUIT_SIG = -99 29 MAX_WAIT_TIME_SECONDS = 30 30 ) 31 32 type abciResponse struct { 33 height int64 34 responses *ABCIResponses 35 } 36 37 func (blockExec *BlockExecutor) initAsyncDBContext() { 38 blockExec.abciResponseQueue = make(chan abciResponse, MAXCHAN_LEN) 39 blockExec.stateQueue = make(chan State, MAXCHAN_LEN) 40 blockExec.asyncFeedbackQueue = make(chan int64, FEEDBACK_LEN) 41 42 blockExec.wg.Add(3) 43 go blockExec.asyncSaveStateRoutine() 44 go blockExec.asyncSaveABCIRespRoutine() 45 go blockExec.fireEventsRountine() 46 } 47 48 func (blockExec *BlockExecutor) stopAsyncDBContext() { 49 if blockExec.isAsyncQueueStop { 50 return 51 } 52 53 blockExec.abciResponseQueue <- abciResponse{height: QUIT_SIG} 54 blockExec.stateQueue <- State{LastBlockHeight: QUIT_SIG} 55 blockExec.eventsChan <- event{} 56 57 blockExec.wg.Wait() 58 59 blockExec.isAsyncQueueStop = true 60 } 61 62 func (blockExec *BlockExecutor) SaveABCIResponsesAsync(height int64, responses *ABCIResponses) { 63 blockExec.abciResponseQueue <- abciResponse{height, responses} 64 } 65 66 func (blockExec *BlockExecutor) SaveStateAsync(state State) { 67 blockExec.stateQueue <- state 68 } 69 70 // asyncSaveRoutine handle writing state work 71 func (blockExec *BlockExecutor) asyncSaveStateRoutine() { 72 for stateMsg := range blockExec.stateQueue { 73 if stateMsg.LastBlockHeight == QUIT_SIG { 74 break 75 } 76 77 SaveState(blockExec.db, stateMsg) 78 blockExec.asyncFeedbackQueue <- stateMsg.LastBlockHeight 79 } 80 81 blockExec.wg.Done() 82 } 83 84 // asyncSaveRoutine handle writing abciResponse work 85 func (blockExec *BlockExecutor) asyncSaveABCIRespRoutine() { 86 for abciMsg := range blockExec.abciResponseQueue { 87 if abciMsg.height == QUIT_SIG { 88 break 89 } 90 SaveABCIResponses(blockExec.db, abciMsg.height, abciMsg.responses) 91 blockExec.asyncFeedbackQueue <- abciMsg.height 92 } 93 blockExec.wg.Done() 94 } 95 96 // SetIsAsyncSaveDB switches to open async write db feature 97 func (blockExec *BlockExecutor) SetIsAsyncSaveDB(isAsyncSaveDB bool) { 98 blockExec.isAsyncSaveDB = isAsyncSaveDB 99 } 100 101 // wait for the last sate and abciResponse to be saved 102 func (blockExec *BlockExecutor) tryWaitLastBlockSave(lastHeight int64) { 103 timeoutCh := time.After(MAX_WAIT_TIME_SECONDS * time.Second) 104 if blockExec.isAsyncSaveDB && blockExec.isWaitingLastBlock { 105 i := 0 106 for { 107 select { 108 case r := <-blockExec.asyncFeedbackQueue: 109 if r != lastHeight { 110 panic("Incorrect synced aysnc feed Height") 111 } 112 if i++; i == FEEDBACK_LEN { 113 return 114 } 115 case <-timeoutCh: 116 // It shouldn't be timeout. something must be wrong here 117 panic("Can't get last block aysnc result") 118 } 119 } 120 } 121 } 122 123 // try to save the abciReponse async 124 func (blockExec *BlockExecutor) trySaveABCIResponsesAsync(height int64, abciResponses *ABCIResponses) { 125 if blockExec.isAsyncSaveDB { 126 blockExec.isWaitingLastBlock = true 127 blockExec.SaveABCIResponsesAsync(height, abciResponses) 128 } else { 129 SaveABCIResponses(blockExec.db, height, abciResponses) 130 } 131 } 132 133 // try to save the state async 134 func (blockExec *BlockExecutor) trySaveStateAsync(state State) { 135 if blockExec.isAsyncSaveDB { 136 blockExec.SaveStateAsync(state) 137 } else { 138 //Async save state 139 SaveState(blockExec.db, state) 140 } 141 }