use of org.starcoin.bean.Block in project starcoin-search by starcoinorg.
the class RepairHandle method repair.
public void repair(long blockNumber) {
try {
// get block from chain
Block blockOnChain = blockRPCClient.getBlockByHeight(blockNumber);
if (blockOnChain == null) {
logger.warn("block not exist on chain: {}", blockNumber);
return;
}
// get block from es
Block blockOnEs = elasticSearchHandler.getBlockId(blockNumber);
if (blockOnEs != null) {
if (!blockOnChain.getHeader().getBlockHash().equals(blockOnEs.getHeader().getBlockHash())) {
// update block
List<Block> blockList = new ArrayList<>();
ServiceUtils.addBlockToList(transactionRPCClient, blockList, blockOnChain);
elasticSearchHandler.updateBlock(blockList);
logger.info("repair ok: {}", blockNumber);
} else {
logger.info("not repair");
}
} else {
logger.warn("es not exist block:{}", blockNumber);
}
} catch (JSONRPC2SessionException e) {
logger.error("repair error:", e);
}
}
use of org.starcoin.bean.Block in project starcoin-search by starcoinorg.
the class RepairHandle method autoRepair.
public boolean autoRepair(long startNumber, int count) {
// read current master height
try {
BlockHeader chainHeader = blockRPCClient.getChainHeader();
long currentMasterNumber = chainHeader.getHeight();
if (startNumber > currentMasterNumber - 200) {
logger.info("repair too fast: {}", startNumber);
return false;
}
} catch (JSONRPC2SessionException e) {
logger.error("get master error: ", e);
return false;
}
List<Block> blocksOnChain;
try {
blocksOnChain = blockRPCClient.getBlockListFromHeight(startNumber, count);
} catch (JSONRPC2SessionException e) {
logger.error("get blocks on chain error:", e);
return false;
}
if (blocksOnChain.isEmpty()) {
logger.warn("blocks on chain is empty!");
return false;
}
Result<Block> blockResult = elasticSearchHandler.getBlockIds(startNumber - count, count);
if (blockResult == null || blockResult.getContents().isEmpty()) {
logger.warn("blocks on es is empty!");
return false;
}
Map<Long, Block> blockHashMap = new HashMap<>();
for (Block block : blockResult.getContents()) {
blockHashMap.put(block.getHeader().getHeight(), block);
}
List<Block> blockList = new ArrayList<>();
long newStartNumber = startNumber;
for (Block block : blocksOnChain) {
Block esBlock = blockHashMap.get(block.getHeader().getHeight());
if (esBlock == null) {
logger.warn("es block not exist: {}", block.getHeader().getHeight());
try {
ServiceUtils.addBlockToList(transactionRPCClient, blockList, block);
} catch (JSONRPC2SessionException e) {
logger.error("add block err:", e);
}
continue;
}
if (!block.getHeader().getBlockHash().equals(esBlock.getHeader().getBlockHash())) {
// fork block
try {
ServiceUtils.addBlockToList(transactionRPCClient, blockList, block);
} catch (JSONRPC2SessionException e) {
logger.error("add fix block err:", e);
}
} else {
logger.info("normal block: {}", block.getHeader().getHeight());
}
newStartNumber = block.getHeader().getHeight();
}
if (!blockList.isEmpty()) {
elasticSearchHandler.updateBlock(blockList);
logger.info("repair ok: {}", newStartNumber);
} else {
logger.info("not repair:{}", startNumber);
}
return true;
}
use of org.starcoin.bean.Block in project starcoin-search by starcoinorg.
the class BlockService method getBlock.
public Block getBlock(String network, String id) throws IOException {
GetRequest getRequest = new GetRequest(getIndex(network, Constant.BLOCK_CONTENT_INDEX), id);
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
Block block = new Block();
if (getResponse.isExists()) {
String sourceAsString = getResponse.getSourceAsString();
block = JSON.parseObject(sourceAsString, Block.class);
} else {
logger.error("not found block by id: {}", id);
}
return block;
}
use of org.starcoin.bean.Block in project starcoin-search by starcoinorg.
the class BlockService method getBlockByHeight.
public Block getBlockByHeight(String network, long height) {
SearchRequest searchRequest = new SearchRequest(getIndex(network, Constant.BLOCK_IDS_INDEX));
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("header.number", height);
searchSourceBuilder.query(termQueryBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse;
try {
searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
logger.error("get block by height error:", e);
return null;
}
Result<Block> result = ServiceUtils.getSearchResult(searchResponse, Block.class);
List<Block> blocks = result.getContents();
if (blocks.size() == 1) {
return getBlockByHash(network, blocks.get(0).getHeader().getBlockHash());
} else {
logger.warn("get block by height is null, network: {}, : {}", network, height);
}
return null;
}
use of org.starcoin.bean.Block in project starcoin-search by starcoinorg.
the class IndexerHandle method executeInternal.
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) {
// read current offset
if (localBlockOffset == null || currentHandleHeader == null) {
// logger.warn("local offset error, reset it: {}, {}", localOffset, currentHandleHeader);
initOffset();
}
BlockOffset remoteBlockOffset = elasticSearchHandler.getRemoteOffset();
logger.info("current remote offset: {}", remoteBlockOffset);
if (remoteBlockOffset == null) {
logger.warn("offset must not null, please check blocks.mapping!!");
return;
}
if (remoteBlockOffset.getBlockHeight() > localBlockOffset.getBlockHeight()) {
logger.info("indexer equalize chain blocks.");
return;
}
// read head
try {
BlockHeader chainHeader = blockRPCClient.getChainHeader();
// calculate bulk size
long headHeight = chainHeader.getHeight();
long bulkNumber = Math.min(headHeight - localBlockOffset.getBlockHeight(), bulkSize);
int index = 1;
List<Block> blockList = new ArrayList<>();
while (index <= bulkNumber) {
long readNumber = localBlockOffset.getBlockHeight() + index;
Block block = blockRPCClient.getBlockByHeight(readNumber);
if (!block.getHeader().getParentHash().equals(currentHandleHeader.getBlockHash())) {
// fork handle until reach forked point block
logger.warn("Fork detected, roll back: {}, {}, {}", readNumber, block.getHeader().getParentHash(), currentHandleHeader.getBlockHash());
Block lastForkBlock, lastMasterBlock;
BlockHeader forkHeader = currentHandleHeader;
long lastMasterNumber = readNumber - 1;
String forkHeaderParentHash = null;
do {
// 获取分叉的block
if (forkHeaderParentHash == null) {
// 第一次先回滚当前最高的分叉块
forkHeaderParentHash = forkHeader.getBlockHash();
} else {
forkHeaderParentHash = forkHeader.getParentHash();
}
lastForkBlock = elasticSearchHandler.getBlockContent(forkHeaderParentHash);
if (lastForkBlock == null) {
logger.warn("get fork block null: {}", forkHeaderParentHash);
// read from node
lastForkBlock = blockRPCClient.getBlockByHash(forkHeaderParentHash);
}
if (lastForkBlock != null) {
elasticSearchHandler.bulkForkedUpdate(lastForkBlock);
logger.info("rollback forked block ok: {}, {}", lastForkBlock.getHeader().getHeight(), forkHeaderParentHash);
} else {
// 如果块取不到,先退出当前任务,下一个轮询周期再执行
logger.warn("get forked block is null: {}", forkHeaderParentHash);
return;
}
// 获取上一个高度主块
lastMasterBlock = blockRPCClient.getBlockByHeight(lastMasterNumber);
if (lastMasterBlock != null) {
long forkNumber = forkHeader.getHeight();
logger.info("fork number: {}", forkNumber);
forkHeader = lastForkBlock.getHeader();
// reset offset to handled fork block
currentHandleHeader = forkHeader;
localBlockOffset.setBlockHeight(currentHandleHeader.getHeight());
localBlockOffset.setBlockHash(currentHandleHeader.getBlockHash());
elasticSearchHandler.setRemoteOffset(localBlockOffset);
if (lastMasterNumber == forkNumber && lastMasterBlock.getHeader().getBlockHash().equals(forkHeaderParentHash)) {
// find fork point
logger.info("find fork height: {}", lastMasterNumber);
break;
}
// 继续找下一个分叉
lastMasterNumber--;
logger.info("continue last forked block: {}", lastMasterNumber);
} else {
logger.warn("get last master Block null: {}", lastMasterNumber);
}
} while (true);
logger.info("rollback handle ok: {}", localBlockOffset);
// 退出当前任务,重新添加从分叉点之后的block
return;
}
// set event
ServiceUtils.addBlockToList(transactionRPCClient, blockList, block);
// update current header
currentHandleHeader = block.getHeader();
index++;
logger.debug("add block: {}", block.getHeader());
}
// bulk execute
elasticSearchHandler.bulk(blockList);
// update offset
localBlockOffset.setBlockHeight(currentHandleHeader.getHeight());
localBlockOffset.setBlockHash(currentHandleHeader.getBlockHash());
elasticSearchHandler.setRemoteOffset(localBlockOffset);
logger.info("indexer update success: {}", localBlockOffset);
} catch (JSONRPC2SessionException e) {
logger.error("chain header error:", e);
}
}
Aggregations