use of org.aion.zero.impl.sync.msg.ReqBlocksBodies in project aion by aionnetwork.
the class TaskGetBodies method run.
@Override
public void run() {
while (run.get()) {
HeadersWrapper hw;
try {
hw = headersImported.take();
} catch (InterruptedException e) {
continue;
}
int idHash = hw.getNodeIdHash();
List<A0BlockHeader> headers = hw.getHeaders();
if (headers.isEmpty()) {
continue;
}
HeadersWrapper hwPrevious = headersSent.get(idHash);
if (hwPrevious == null || (System.currentTimeMillis() - hwPrevious.getTimestamp()) > SENT_HEADERS_TIMEOUT) {
this.headersSent.put(idHash, hw);
if (log.isDebugEnabled()) {
log.debug("<get-bodies from-num={} to-num={} node={}>", headers.get(0).getNumber(), headers.get(headers.size() - 1).getNumber(), hw.getDisplayId());
}
this.p2p.send(idHash, new ReqBlocksBodies(headers.stream().map(k -> k.getHash()).collect(Collectors.toList())));
}
}
}
use of org.aion.zero.impl.sync.msg.ReqBlocksBodies in project aion by aionnetwork.
the class SyncMgr method requestBodies.
/**
* Requests the bodies associated to the given block headers.
*/
void requestBodies(int nodeId, String displayId) {
Thread.currentThread().setName("sync-gb-" + Thread.currentThread().getId());
long startTime = System.nanoTime();
List<List<BlockHeader>> forRequests = syncHeaderRequestManager.getHeadersForBodiesRequests(nodeId);
for (List<BlockHeader> requestHeaders : forRequests) {
// Filter headers again in case the blockchain has advanced while this task was waiting to be executed.
List<BlockHeader> filtered = requestHeaders.stream().filter(h -> !importedBlockHashes.containsKey(ByteArrayWrapper.wrap(h.getHash()))).collect(Collectors.toList());
// Check the peer state and discard blocks that are under the current best (in case the hashes already dropped from the above map).
// This check is only applicable for SyncMode.NORMAL because the other sync modes deal with side chains.
long currentBest = chain.getBestBlock() == null ? 0L : chain.getBestBlock().getNumber();
long firstInBatch = requestHeaders.get(0).getNumber();
if (syncHeaderRequestManager.getSyncMode(nodeId) == SyncMode.NORMAL && firstInBatch <= currentBest) {
// remove all blocks in the batch that are under the current best
for (Iterator<BlockHeader> it = filtered.iterator(); it.hasNext(); ) {
if (it.next().getNumber() <= currentBest) {
it.remove();
}
}
}
if (filtered.size() == requestHeaders.size()) {
// Log bodies request before sending the request.
log.debug("<get-bodies from-num={} to-num={} node={}>", firstInBatch, requestHeaders.get(requestHeaders.size() - 1).getNumber(), displayId);
p2pMgr.send(nodeId, displayId, new ReqBlocksBodies(requestHeaders.stream().map(k -> k.getHash()).collect(Collectors.toList())));
stats.updateTotalRequestsToPeer(displayId, RequestType.BODIES);
stats.updateRequestTime(displayId, System.nanoTime(), RequestType.BODIES);
} else {
// Drop the headers that are already known.
syncHeaderRequestManager.dropHeaders(nodeId, requestHeaders);
if (!filtered.isEmpty()) {
// Store the subset that is still useful.
syncHeaderRequestManager.storeHeaders(nodeId, filtered);
}
}
}
long duration = System.nanoTime() - startTime;
survey_log.debug("TaskGetBodies: make request, duration = {} ns.", duration);
}
use of org.aion.zero.impl.sync.msg.ReqBlocksBodies in project aion by aionnetwork.
the class ReqBlocksBodiesHandler method receive.
@Override
public void receive(int _nodeIdHashcode, String _displayId, final byte[] _msgBytes) {
if (isSyncOnlyNode)
return;
ReqBlocksBodies reqBlocks = ReqBlocksBodies.decode(_msgBytes);
if (reqBlocks != null) {
// limit number of blocks
List<byte[]> hashes = reqBlocks.getBlocksHashes();
hashes = hashes.size() > MAX_NUM_OF_BLOCKS ? hashes.subList(0, MAX_NUM_OF_BLOCKS) : hashes;
// results
List<byte[]> blockBodies = new ArrayList<>();
// read from cache, then block store
int out = 0;
for (byte[] hash : hashes) {
// ref for add.
byte[] blockBytesForadd;
byte[] blockBytes = cache.get(ByteArrayWrapper.wrap(hash));
// if cached , add.
if (blockBytes != null) {
blockBytesForadd = blockBytes;
} else {
Block block = blockchain.getBlockByHash(hash);
if (block != null) {
blockBytesForadd = block.getEncodedBody();
cache.put(ByteArrayWrapper.wrap(hash), block.getEncodedBody());
} else {
// not found
break;
}
}
if ((out += blockBytesForadd.length) > P2pConstant.MAX_BODY_SIZE) {
log.debug("<req-blocks-bodies-max-size-reach size={}/{}>", out, P2pConstant.MAX_BODY_SIZE);
break;
}
blockBodies.add(blockBytesForadd);
}
this.p2pMgr.send(_nodeIdHashcode, _displayId, new ResBlocksBodies(blockBodies.toArray()));
this.syncMgr.getSyncStats().updateTotalBlockRequestsByPeer(_displayId, blockBodies.size());
if (log.isDebugEnabled()) {
this.log.debug("<req-bodies req-size={} res-size={} node={}>", reqBlocks.getBlocksHashes().size(), blockBodies.size(), _displayId);
}
} else {
this.log.error("<req-bodies decode-error, unable to decode bodies from {}, len: {}>", _displayId, _msgBytes.length);
if (this.log.isTraceEnabled()) {
this.log.trace("req-bodies dump: {}", ByteUtil.toHexString(_msgBytes));
}
}
}
Aggregations