github.com/klaytn/klaytn@v1.12.1/datasync/dbsyncer/dbsync_multi.go (about) 1 // Copyright 2019 The klaytn Authors 2 // This file is part of the klaytn library. 3 // 4 // The klaytn library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The klaytn library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>. 16 17 package dbsyncer 18 19 import ( 20 "errors" 21 "strings" 22 "time" 23 24 "github.com/klaytn/klaytn/blockchain/types" 25 ) 26 27 func (ds *DBSyncer) HandleChainEventParallel(block *types.Block) error { 28 logger.Info("dbsyncer(multi) HandleChainEvent", "number", block.Number(), "txs", block.Transactions().Len()) 29 30 bulkInsertQuerys := []*BulkInsertQuery{} 31 32 startblock := time.Now() 33 bulkInsertQuerys, err := ds.parallelSyncBlockHeader(block) 34 if err != nil { 35 logger.Error("fail to sync block", "block", block.Number(), "err", err) 36 return err 37 } 38 blocktime := time.Since(startblock) 39 40 starttx := time.Now() 41 receipttime := time.Duration(0) 42 if block.Transactions().Len() > 0 { 43 44 startrceipt := time.Now() 45 receipts := ds.blockchain.GetReceiptsByBlockHash(block.Hash()) 46 receipttime = time.Since(startrceipt) 47 48 bulkInsertQuerys, err = ds.parallelSyncTransactions(block, receipts, bulkInsertQuerys) 49 if err != nil { 50 logger.Error("fail to sync transaction", "block", block.Number(), "err", err) 51 return err 52 } 53 } 54 txtime := time.Since(starttx) 55 56 startInsert := time.Now() 57 queryResult := make(chan *BulkInsertResult, len(bulkInsertQuerys)) 58 ds.queryEngine.executeBulkInsert(bulkInsertQuerys, queryResult) 59 60 totalResult := 0 61 defer close(queryResult) 62 63 RESULT: 64 for result := range queryResult { 65 if result.err != nil { 66 return result.err 67 } 68 69 totalResult++ 70 if totalResult == len(bulkInsertQuerys) { 71 break RESULT 72 } 73 } 74 insertTime := time.Since(startInsert) 75 76 totalTime := time.Since(startblock) 77 if ds.logMode { 78 logger.Info("dbsyncer(multi) time", "number", block.Number(), "block", blocktime, "txs", txtime, "receipts", receipttime, "insert", insertTime, "total", totalTime) 79 } 80 81 return nil 82 } 83 84 func (ds *DBSyncer) parallelSyncBlockHeader(block *types.Block) ([]*BulkInsertQuery, error) { 85 blockStr := ds.blockInsertQuery + "," 86 vals := []interface{}{} 87 88 bulkInsertQuerys := []*BulkInsertQuery{} 89 90 proposerAddr, committeeAddrs, err := getProposerAndValidatorsFromBlock(block) 91 if err != nil { 92 return nil, err 93 } 94 95 totalTx := block.Transactions().Len() 96 committee := strings.ToLower(committeeAddrs) 97 gasUsed := block.Header().GasUsed 98 gasPrice := ds.blockchain.Config().UnitPrice 99 hash := block.Header().Hash().Hex() 100 number := block.Header().Number.Uint64() 101 parentHash := block.Header().ParentHash.Hex() 102 proposer := strings.ToLower(proposerAddr) 103 reward := block.Header().Rewardbase.Hex() 104 size := block.Size() 105 timestamp := block.Header().Time.String() 106 timestampFos := block.Header().TimeFoS 107 108 vals = append(vals, totalTx, committee, gasUsed, gasPrice, hash, 109 number, parentHash, proposer, reward, size, timestamp, timestampFos) 110 111 bulkInsertQuerys = append(bulkInsertQuerys, &BulkInsertQuery{blockStr, vals, block.NumberU64(), 1}) 112 113 return bulkInsertQuerys, nil 114 } 115 116 func (ds *DBSyncer) parallelSyncTransactions(block *types.Block, receipts types.Receipts, bulkInsertQuerys []*BulkInsertQuery) ([]*BulkInsertQuery, error) { 117 txStr, vals, insertCount := ds.resetTxParameter() 118 summaryStr, summaryVals, summaryInsertCount := ds.resetSummaryParameter() 119 txMapStr, txMapVals, txMapInsertCount := ds.resetTxMapParameter() 120 121 txLen := block.Transactions().Len() 122 result := make(chan *MakeQueryResult, txLen) 123 124 if txLen != receipts.Len() { 125 logger.Error("transactions is not matched receipts", "txs", txLen, "receipts", receipts.Len()) 126 return nil, errors.New("transaction count is not matched receipts") 127 } 128 129 ds.queryEngine.insertTransactions(block, block.Transactions(), receipts, result) 130 totalTxs := 0 131 132 defer close(result) 133 134 QUERY: 135 for record := range result { 136 137 if record.err != nil { 138 return nil, record.err 139 } 140 141 txStr += record.cols + "," 142 vals = append(vals, record.val...) 143 insertCount++ 144 145 if insertCount >= ds.bulkInsertSize { 146 bulkInsertQuerys = append(bulkInsertQuerys, &BulkInsertQuery{txStr, vals, block.NumberU64(), insertCount}) 147 148 txStr, vals, insertCount = ds.resetTxParameter() 149 } 150 151 if record.count == 1 { 152 summaryStr += record.scols + "," 153 summaryVals = append(summaryVals, record.sval...) 154 summaryInsertCount++ 155 } 156 157 if summaryInsertCount >= ds.bulkInsertSize { 158 bulkInsertQuerys = append(bulkInsertQuerys, &BulkInsertQuery{summaryStr, summaryVals, block.NumberU64(), summaryInsertCount}) 159 160 summaryStr, summaryVals, summaryInsertCount = ds.resetTxParameter() 161 } 162 163 if record.tcount == 1 { 164 txMapStr += record.tcols + "," 165 txMapVals = append(txMapVals, record.tval...) 166 txMapInsertCount++ 167 } 168 169 if txMapInsertCount >= ds.bulkInsertSize { 170 bulkInsertQuerys = append(bulkInsertQuerys, &BulkInsertQuery{txMapStr, txMapVals, block.NumberU64(), txMapInsertCount}) 171 172 txMapStr, txMapVals, txMapInsertCount = ds.resetTxMapParameter() 173 } 174 175 totalTxs++ 176 if totalTxs == block.Transactions().Len() { 177 break QUERY 178 } 179 } 180 181 if insertCount > 0 { 182 bulkInsertQuerys = append(bulkInsertQuerys, &BulkInsertQuery{txStr, vals, block.NumberU64(), insertCount}) 183 } 184 185 if summaryInsertCount > 0 { 186 bulkInsertQuerys = append(bulkInsertQuerys, &BulkInsertQuery{summaryStr, summaryVals, block.NumberU64(), summaryInsertCount}) 187 } 188 189 if txMapInsertCount > 0 { 190 bulkInsertQuerys = append(bulkInsertQuerys, &BulkInsertQuery{txMapStr, txMapVals, block.NumberU64(), txMapInsertCount}) 191 } 192 193 return bulkInsertQuerys, nil 194 }