/** * Updates metadata when a worker periodically heartbeats with the master. * * @param workerId the worker id * @param usedBytesOnTiers a mapping from tier alias to the used bytes * @param removedBlockIds a list of block ids removed from this worker * @param addedBlocksOnTiers a mapping from tier alias to the added blocks * @return an optional command for the worker to execute */ public Command workerHeartbeat( long workerId, Map<String, Long> usedBytesOnTiers, List<Long> removedBlockIds, Map<String, List<Long>> addedBlocksOnTiers) { MasterWorkerInfo worker = mWorkers.getFirstByField(ID_INDEX, workerId); if (worker == null) { LOG.warn("Could not find worker id: {} for heartbeat.", workerId); return new Command(CommandType.Register, new ArrayList<Long>()); } synchronized (worker) { // Technically, 'worker' should be confirmed to still be in the data structure. Lost worker // detection can remove it. However, we are intentionally ignoring this race, since the worker // will just re-register regardless. processWorkerRemovedBlocks(worker, removedBlockIds); processWorkerAddedBlocks(worker, addedBlocksOnTiers); worker.updateUsedBytes(usedBytesOnTiers); worker.updateLastUpdatedTimeMs(); List<Long> toRemoveBlocks = worker.getToRemoveBlocks(); if (toRemoveBlocks.isEmpty()) { return new Command(CommandType.Nothing, new ArrayList<Long>()); } return new Command(CommandType.Free, toRemoveBlocks); } }