예제 #1
0
 /**
  * Updates the worker and block metadata for blocks removed from a worker.
  *
  * @param workerInfo The worker metadata object
  * @param removedBlockIds A list of block ids removed from the worker
  */
 @GuardedBy("workerInfo")
 private void processWorkerRemovedBlocks(
     MasterWorkerInfo workerInfo, Collection<Long> removedBlockIds) {
   for (long removedBlockId : removedBlockIds) {
     MasterBlockInfo block = mBlocks.get(removedBlockId);
     // TODO(calvin): Investigate if this branching logic can be simplified.
     if (block == null) {
       // LOG.warn("Worker {} informs the removed block {}, but block metadata does not exist"
       //    + " on Master!", workerInfo.getId(), removedBlockId);
       // TODO(pfxuan): [ALLUXIO-1804] should find a better way to handle the removed blocks.
       // Ideally, the delete/free I/O flow should never reach this point. Because Master may
       // update the block metadata only after receiving the acknowledgement from Workers.
       workerInfo.removeBlock(removedBlockId);
       // Continue to remove the remaining blocks.
       continue;
     }
     synchronized (block) {
       LOG.info("Block {} is removed on worker {}.", removedBlockId, workerInfo.getId());
       workerInfo.removeBlock(block.getBlockId());
       block.removeWorker(workerInfo.getId());
       if (block.getNumLocations() == 0) {
         mLostBlocks.add(removedBlockId);
       }
     }
   }
 }
예제 #2
0
 /**
  * @param blockId the block id to get information for
  * @return the {@link BlockInfo} for the given block id
  * @throws BlockInfoException if the block info is not found
  */
 public BlockInfo getBlockInfo(long blockId) throws BlockInfoException {
   MasterBlockInfo block = mBlocks.get(blockId);
   if (block == null) {
     throw new BlockInfoException(ExceptionMessage.BLOCK_META_NOT_FOUND, blockId);
   }
   synchronized (block) {
     return generateBlockInfo(block);
   }
 }
예제 #3
0
  /**
   * Marks a block as committed, but without a worker location. This means the block is only in ufs.
   *
   * @param blockId the id of the block to commit
   * @param length the length of the block
   */
  public void commitBlockInUFS(long blockId, long length) {
    LOG.debug("Commit block in ufs. blockId: {}, length: {}", blockId, length);
    if (mBlocks.get(blockId) != null) {
      // Block metadata already exists, so do not need to create a new one.
      return;
    }

    // The block has not been committed previously, so add the metadata to commit the block.
    MasterBlockInfo block = new MasterBlockInfo(blockId, length);
    long counter = AsyncJournalWriter.INVALID_FLUSH_COUNTER;
    synchronized (block) {
      if (mBlocks.putIfAbsent(blockId, block) == null) {
        // Successfully added the new block metadata. Append a journal entry for the new metadata.
        BlockInfoEntry blockInfo =
            BlockInfoEntry.newBuilder().setBlockId(blockId).setLength(length).build();
        counter = appendJournalEntry(JournalEntry.newBuilder().setBlockInfo(blockInfo).build());
      }
    }
    waitForJournalFlush(counter);
  }
예제 #4
0
 @Override
 public void streamToJournalCheckpoint(JournalOutputStream outputStream) throws IOException {
   outputStream.writeEntry(getContainerIdJournalEntry());
   for (MasterBlockInfo blockInfo : mBlocks.values()) {
     BlockInfoEntry blockInfoEntry =
         BlockInfoEntry.newBuilder()
             .setBlockId(blockInfo.getBlockId())
             .setLength(blockInfo.getLength())
             .build();
     outputStream.writeEntry(JournalEntry.newBuilder().setBlockInfo(blockInfoEntry).build());
   }
 }
예제 #5
0
 /**
  * Retrieves information for the given list of block ids.
  *
  * @param blockIds A list of block ids to retrieve the information for
  * @return A list of {@link BlockInfo} objects corresponding to the input list of block ids. The
  *     list is in the same order as the input list
  */
 public List<BlockInfo> getBlockInfoList(List<Long> blockIds) {
   List<BlockInfo> ret = new ArrayList<>(blockIds.size());
   for (long blockId : blockIds) {
     MasterBlockInfo block = mBlocks.get(blockId);
     if (block == null) {
       continue;
     }
     synchronized (block) {
       ret.add(generateBlockInfo(block));
     }
   }
   return ret;
 }
예제 #6
0
 @Override
 public void processJournalEntry(JournalEntry entry) throws IOException {
   Message innerEntry = JournalProtoUtils.unwrap(entry);
   // TODO(gene): A better way to process entries besides a huge switch?
   if (innerEntry instanceof BlockContainerIdGeneratorEntry) {
     mJournaledNextContainerId =
         ((BlockContainerIdGeneratorEntry) innerEntry).getNextContainerId();
     mBlockContainerIdGenerator.setNextContainerId((mJournaledNextContainerId));
   } else if (innerEntry instanceof BlockInfoEntry) {
     BlockInfoEntry blockInfoEntry = (BlockInfoEntry) innerEntry;
     if (mBlocks.containsKey(blockInfoEntry.getBlockId())) {
       // Update the existing block info.
       MasterBlockInfo blockInfo = mBlocks.get(blockInfoEntry.getBlockId());
       blockInfo.updateLength(blockInfoEntry.getLength());
     } else {
       mBlocks.put(
           blockInfoEntry.getBlockId(),
           new MasterBlockInfo(blockInfoEntry.getBlockId(), blockInfoEntry.getLength()));
     }
   } else {
     throw new IOException(ExceptionMessage.UNEXPECTED_JOURNAL_ENTRY.getMessage(entry));
   }
 }
예제 #7
0
  /**
   * Removes blocks from workers.
   *
   * @param blockIds a list of block ids to remove from Alluxio space
   * @param delete whether to delete blocks' metadata in Master
   */
  public void removeBlocks(List<Long> blockIds, boolean delete) {
    for (long blockId : blockIds) {
      MasterBlockInfo block = mBlocks.get(blockId);
      if (block == null) {
        continue;
      }
      HashSet<Long> workerIds = new HashSet<>();
      synchronized (block) {
        // Technically, 'block' should be confirmed to still be in the data structure. A
        // concurrent removeBlock call can remove it. However, we are intentionally ignoring this
        // race, since deleting the same block again is a noop.
        workerIds.addAll(block.getWorkers());
        // Two cases here:
        // 1) For delete: delete the block metadata.
        // 2) For free: keep the block metadata. mLostBlocks will be changed in
        // processWorkerRemovedBlocks
        if (delete) {
          // Make sure blockId is removed from mLostBlocks when the block metadata is deleted.
          // Otherwise blockId in mLostBlock can be dangling index if the metadata is gone.
          mLostBlocks.remove(blockId);
          mBlocks.remove(blockId);
        }
      }

      // Outside of locking the block. This does not have to be synchronized with the block
      // metadata, since it is essentially an asynchronous signal to the worker to remove the block.
      for (long workerId : workerIds) {
        MasterWorkerInfo worker = mWorkers.getFirstByField(ID_INDEX, workerId);
        if (worker != null) {
          synchronized (worker) {
            worker.updateToRemovedBlock(true, blockId);
          }
        }
      }
    }
  }
예제 #8
0
 /**
  * Updates the worker and block metadata for blocks added to a worker.
  *
  * @param workerInfo The worker metadata object
  * @param addedBlockIds A mapping from storage tier alias to a list of block ids added
  */
 @GuardedBy("workerInfo")
 private void processWorkerAddedBlocks(
     MasterWorkerInfo workerInfo, Map<String, List<Long>> addedBlockIds) {
   for (Map.Entry<String, List<Long>> entry : addedBlockIds.entrySet()) {
     for (long blockId : entry.getValue()) {
       MasterBlockInfo block = mBlocks.get(blockId);
       if (block != null) {
         synchronized (block) {
           workerInfo.addBlock(blockId);
           block.addWorker(workerInfo.getId(), entry.getKey());
           mLostBlocks.remove(blockId);
         }
       } else {
         LOG.warn("Failed to register workerId: {} to blockId: {}", workerInfo.getId(), blockId);
       }
     }
   }
 }
예제 #9
0
  // TODO(binfan): check the logic is correct or not when commitBlock is a retry
  public void commitBlock(
      long workerId, long usedBytesOnTier, String tierAlias, long blockId, long length)
      throws NoWorkerException {
    LOG.debug(
        "Commit block from workerId: {}, usedBytesOnTier: {}, blockId: {}, length: {}",
        workerId,
        usedBytesOnTier,
        blockId,
        length);

    long counter = AsyncJournalWriter.INVALID_FLUSH_COUNTER;

    MasterWorkerInfo worker = mWorkers.getFirstByField(ID_INDEX, workerId);
    // TODO(peis): Check lost workers as well.
    if (worker == null) {
      throw new NoWorkerException(ExceptionMessage.NO_WORKER_FOUND.getMessage(workerId));
    }

    // Lock the worker metadata first.
    synchronized (worker) {
      // Loop until block metadata is successfully locked.
      for (; ; ) {
        boolean newBlock = false;
        MasterBlockInfo block = mBlocks.get(blockId);
        if (block == null) {
          // The block metadata doesn't exist yet.
          block = new MasterBlockInfo(blockId, length);
          newBlock = true;
        }

        // Lock the block metadata.
        synchronized (block) {
          boolean writeJournal = false;
          if (newBlock) {
            if (mBlocks.putIfAbsent(blockId, block) != null) {
              // Another thread already inserted the metadata for this block, so start loop over.
              continue;
            }
            // Successfully added the new block metadata. Append a journal entry for the new
            // metadata.
            writeJournal = true;
          } else if (block.getLength() != length && block.getLength() == Constants.UNKNOWN_SIZE) {
            // The block size was previously unknown. Update the block size with the committed
            // size, and append a journal entry.
            block.updateLength(length);
            writeJournal = true;
          }
          if (writeJournal) {
            BlockInfoEntry blockInfo =
                BlockInfoEntry.newBuilder().setBlockId(blockId).setLength(length).build();
            counter = appendJournalEntry(JournalEntry.newBuilder().setBlockInfo(blockInfo).build());
          }
          // At this point, both the worker and the block metadata are locked.

          // Update the block metadata with the new worker location.
          block.addWorker(workerId, tierAlias);
          // This worker has this block, so it is no longer lost.
          mLostBlocks.remove(blockId);

          // Update the worker information for this new block.
          // TODO(binfan): when retry commitBlock on master is expected, make sure metrics are not
          // double counted.
          worker.addBlock(blockId);
          worker.updateUsedBytes(tierAlias, usedBytesOnTier);
          worker.updateLastUpdatedTimeMs();
        }
        break;
      }
    }

    waitForJournalFlush(counter);
  }
예제 #10
0
 @Override
 public void processJournalCheckpoint(JournalInputStream inputStream) throws IOException {
   // clear state before processing checkpoint.
   mBlocks.clear();
   super.processJournalCheckpoint(inputStream);
 }