Search in sources :

Example 1 with Block

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);
    }
}
Also used : JSONRPC2SessionException(com.thetransactioncompany.jsonrpc2.client.JSONRPC2SessionException) ArrayList(java.util.ArrayList) Block(org.starcoin.bean.Block)

Example 2 with Block

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;
}
Also used : HashMap(java.util.HashMap) JSONRPC2SessionException(com.thetransactioncompany.jsonrpc2.client.JSONRPC2SessionException) ArrayList(java.util.ArrayList) Block(org.starcoin.bean.Block) BlockHeader(org.starcoin.bean.BlockHeader)

Example 3 with Block

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;
}
Also used : GetRequest(org.elasticsearch.action.get.GetRequest) UncleBlock(org.starcoin.bean.UncleBlock) Block(org.starcoin.bean.Block) GetResponse(org.elasticsearch.action.get.GetResponse)

Example 4 with 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;
}
Also used : SearchRequest(org.elasticsearch.action.search.SearchRequest) UncleBlock(org.starcoin.bean.UncleBlock) Block(org.starcoin.bean.Block) TermQueryBuilder(org.elasticsearch.index.query.TermQueryBuilder) IOException(java.io.IOException) SearchSourceBuilder(org.elasticsearch.search.builder.SearchSourceBuilder) SearchResponse(org.elasticsearch.action.search.SearchResponse)

Example 5 with Block

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);
    }
}
Also used : JSONRPC2SessionException(com.thetransactioncompany.jsonrpc2.client.JSONRPC2SessionException) ArrayList(java.util.ArrayList) BlockOffset(org.starcoin.bean.BlockOffset) Block(org.starcoin.bean.Block) BlockHeader(org.starcoin.bean.BlockHeader)

Aggregations

Block (org.starcoin.bean.Block)8 JSONRPC2SessionException (com.thetransactioncompany.jsonrpc2.client.JSONRPC2SessionException)5 ArrayList (java.util.ArrayList)3 UncleBlock (org.starcoin.bean.UncleBlock)3 IOException (java.io.IOException)2 SearchRequest (org.elasticsearch.action.search.SearchRequest)2 SearchResponse (org.elasticsearch.action.search.SearchResponse)2 TermQueryBuilder (org.elasticsearch.index.query.TermQueryBuilder)2 SearchSourceBuilder (org.elasticsearch.search.builder.SearchSourceBuilder)2 BlockHeader (org.starcoin.bean.BlockHeader)2 BlockOffset (org.starcoin.bean.BlockOffset)2 HashMap (java.util.HashMap)1 PostConstruct (javax.annotation.PostConstruct)1 GetRequest (org.elasticsearch.action.get.GetRequest)1 GetResponse (org.elasticsearch.action.get.GetResponse)1