Esempio n. 1
0
  @Test
  public void reserveTest() throws Exception {
    // Reserve on top tier
    long blockId = 100;
    BlockStoreLocation tier0 = BlockStoreLocation.anyDirInTier(StorageLevelAlias.MEM.getValue());
    for (int i = 0; i < 3; i++) {
      TieredBlockStoreTestUtils.cache(SESSION_ID, blockId++, BLOCK_SIZE, mBlockStore, tier0);
    }
    CommonUtils.sleepMs(
        WorkerContext.getConf().getLong(Constants.WORKER_SPACE_RESERVER_INTERVAL_MS));
    BlockStoreMeta storeMeta = mBlockStore.getBlockStoreMeta();
    Assert.assertEquals(3 * BLOCK_SIZE, storeMeta.getUsedBytes());
    List<Long> usedBytesOnTiers = storeMeta.getUsedBytesOnTiers();
    Assert.assertEquals(
        2 * BLOCK_SIZE, (long) usedBytesOnTiers.get(StorageLevelAlias.MEM.getValue() - 1));
    Assert.assertEquals(
        BLOCK_SIZE, (long) usedBytesOnTiers.get(StorageLevelAlias.HDD.getValue() - 1));

    // Reserve on under tier
    for (int i = 0; i < 7; i++) {
      TieredBlockStoreTestUtils.cache(SESSION_ID, blockId++, BLOCK_SIZE, mBlockStore, tier0);
    }
    CommonUtils.sleepMs(
        WorkerContext.getConf().getLong(Constants.WORKER_SPACE_RESERVER_INTERVAL_MS));
    storeMeta = mBlockStore.getBlockStoreMeta();
    Assert.assertEquals(9 * BLOCK_SIZE, storeMeta.getUsedBytes());
    usedBytesOnTiers = storeMeta.getUsedBytesOnTiers();
    Assert.assertEquals(
        2 * BLOCK_SIZE, (long) usedBytesOnTiers.get(StorageLevelAlias.MEM.getValue() - 1));
    Assert.assertEquals(
        7 * BLOCK_SIZE, (long) usedBytesOnTiers.get(StorageLevelAlias.HDD.getValue() - 1));
  }
Esempio n. 2
0
  /** Reads into the block. */
  public void read() throws IOException {
    if (_state.get().isValid()) {
      return;
    }

    synchronized (this) {
      if (_state.get().isValid()) {
      } else if (_state.get().isDestroyed()) {
        throw new IllegalStateException(toString());
      } else if (_store.getBlockManager().copyDirtyBlock(this)) {
        // clearDirty();
        // toValid();
      } else {
        if (log.isLoggable(Level.ALL)) log.log(Level.ALL, "read db-block " + this);

        _isLoad = true;

        BlockReadWrite readWrite = _store.getReadWrite();

        clearDirty();

        readWrite.readBlock(
            _blockId & BlockStore.BLOCK_MASK, getBuffer(), 0, BlockStore.BLOCK_SIZE);

        toValid();
      }
    }
  }
Esempio n. 3
0
  private synchronized boolean add(Block block, boolean tryConnecting)
      throws BlockStoreException, VerificationException, ScriptException {
    if (System.currentTimeMillis() - statsLastTime > 1000) {
      // More than a second passed since last stats logging.
      log.info("{} blocks per second", statsBlocksAdded);
      statsLastTime = System.currentTimeMillis();
      statsBlocksAdded = 0;
    }
    // We check only the chain head for double adds here to avoid potentially expensive block chain
    // misses.
    if (block.equals(chainHead.getHeader())) {
      // Duplicate add of the block at the top of the chain, can be a natural artifact of the
      // download process.
      return true;
    }

    // Prove the block is internally valid: hash is lower than target, merkle root is correct and so
    // on.
    try {
      block.verify();
    } catch (VerificationException e) {
      log.error("Failed to verify block:", e);
      log.error(block.toString());
      throw e;
    }

    // Try linking it to a place in the currently known blocks.
    StoredBlock storedPrev = blockStore.get(block.getPrevBlockHash());

    if (storedPrev == null) {
      // We can't find the previous block. Probably we are still in the process of downloading the
      // chain and a
      // block was solved whilst we were doing it. We put it to one side and try to connect it later
      // when we
      // have more blocks.
      log.warn("Block does not connect: {}", block.getHashAsString());
      unconnectedBlocks.add(block);
      return false;
    } else {
      // It connects to somewhere on the chain. Not necessarily the top of the best known chain.
      //
      // Create a new StoredBlock from this block. It will throw away the transaction data so when
      // block goes
      // out of scope we will reclaim the used memory.
      StoredBlock newStoredBlock = storedPrev.build(block);
      checkDifficultyTransitions(storedPrev, newStoredBlock);
      blockStore.put(newStoredBlock);
      // block.transactions may be null here if we received only a header and not a full block. This
      // does not
      // happen currently but might in future if getheaders is implemented.
      connectBlock(newStoredBlock, storedPrev, block.transactions);
    }

    if (tryConnecting) tryConnectingUnconnected();

    statsBlocksAdded++;
    return true;
  }
Esempio n. 4
0
 public void flush() {
   Iterator<BlockPayload> iterator = dirty.values().iterator();
   while (iterator.hasNext()) {
     BlockPayload block = iterator.next();
     iterator.remove();
     store.write(block);
   }
   store.flush();
 }
Esempio n. 5
0
  public void validateIsIndex() {
    long blockIndex = BlockStore.blockIdToIndex(getBlockId());

    int allocCode = getStore().getAllocation(blockIndex);

    if (allocCode != BlockStore.ALLOC_INDEX) {
      RuntimeException exn;
      exn = new IllegalStateException(L.l("block {0} is not an index code={1}", this, allocCode));
      exn.fillInStackTrace();

      throw exn;
      /*
      if (_isValidation) {
        log.warning(exn.toString()));
      }
      else {
        log.log(Level.WARNING, exn.toString(), exn);

        ShutdownSystem.shutdownActive(ExitCode.HEALTH,
                                      L.l("Internal database issue: forcing restart {0}",
                                          exn.toString()));
      }
      */
    }
  }
Esempio n. 6
0
 /**
  * For each block in unconnectedBlocks, see if we can now fit it on top of the chain and if so, do
  * so.
  */
 private void tryConnectingUnconnected()
     throws VerificationException, ScriptException, BlockStoreException {
   // For each block in our unconnected list, try and fit it onto the head of the chain. If we
   // succeed remove it
   // from the list and keep going. If we changed the head of the list at the end of the round try
   // again until
   // we can't fit anything else on the top.
   int blocksConnectedThisRound;
   do {
     blocksConnectedThisRound = 0;
     Iterator<Block> iter = unconnectedBlocks.iterator();
     while (iter.hasNext()) {
       Block block = iter.next();
       // Look up the blocks previous.
       StoredBlock prev = blockStore.get(block.getPrevBlockHash());
       if (prev == null) {
         // This is still an unconnected/orphan block.
         continue;
       }
       // Otherwise we can connect it now.
       // False here ensures we don't recurse infinitely downwards when connecting huge chains.
       add(block, false);
       iter.remove();
       blocksConnectedThisRound++;
     }
     if (blocksConnectedThisRound > 0) {
       log.info("Connected {} floating blocks.", blocksConnectedThisRound);
     }
   } while (blocksConnectedThisRound > 0);
 }
Esempio n. 7
0
 private void setChainHead(StoredBlock chainHead) {
   this.chainHead = chainHead;
   try {
     blockStore.setChainHead(chainHead);
   } catch (BlockStoreException e) {
     throw new RuntimeException(e);
   }
 }
Esempio n. 8
0
  /**
   * Creates a BlockDataManager based on the configuration values.
   *
   * @param workerSource object for collecting the worker metrics
   * @param workerBlockMasterClient the block Tachyon master client for worker
   * @param workerFileSystemMasterClient the file system Tachyon master client for worker
   * @param blockStore the block store manager
   * @throws IOException if fail to connect to under filesystem
   */
  public BlockDataManager(
      WorkerSource workerSource,
      WorkerBlockMasterClient workerBlockMasterClient,
      WorkerFileSystemMasterClient workerFileSystemMasterClient,
      BlockStore blockStore)
      throws IOException {
    mHeartbeatReporter = new BlockHeartbeatReporter();
    mBlockStore = blockStore;
    mWorkerSource = workerSource;
    mMetricsReporter = new BlockMetricsReporter(mWorkerSource);

    mBlockMasterClient = workerBlockMasterClient;
    mFileSystemMasterClient = workerFileSystemMasterClient;

    // Register the heartbeat reporter so it can record block store changes
    mBlockStore.registerBlockStoreEventListener(mHeartbeatReporter);
    mBlockStore.registerBlockStoreEventListener(mMetricsReporter);
  }
Esempio n. 9
0
 private static void shutdown() {
   try {
     if (peers == null) return; // setup() never called so nothing to do.
     peers.stopAndWait();
     saveWallet(walletFile);
     store.close();
     wallet = null;
   } catch (BlockStoreException e) {
     throw new RuntimeException(e);
   }
 }
Esempio n. 10
0
  Block(BlockStore store, long blockId) {
    store.validateBlockId(blockId);

    _store = store;
    _blockId = blockId;

    // _lock = new Lock("block:" + store.getName() + ":" + Long.toHexString(_blockId));
    // ReadWriteLock rwLock = new ReentrantReadWriteLock();

    _rwLock = allocateReadWriteLock();

    _readLock = _rwLock.readLock();
    _writeLock = _rwLock.writeLock();

    _isFlushDirtyOnCommit = _store.isFlushDirtyBlocksOnCommit();

    _buffer = allocateBuffer();

    if (log.isLoggable(Level.ALL)) log.log(Level.ALL, this + " create");
  }
Esempio n. 11
0
  /** Forces a write of the data. */
  public boolean save() {
    if (_dirtyRange.get() == INIT_DIRTY) {
      return false;
    }

    if (toWriteQueued()) {
      _store.getWriter().addDirtyBlock(this);
    }

    return true;
  }
Esempio n. 12
0
  /**
   * Constructs a BlockChain connected to the given wallet and store. To obtain a {@link Wallet} you
   * can construct one from scratch, or you can deserialize a saved wallet from disk using {@link
   * Wallet#loadFromFile(java.io.File)}
   *
   * <p>For the store you can use a {@link MemoryBlockStore} if you don't care about saving the
   * downloaded data, or a {@link BoundedOverheadBlockStore} if you'd like to ensure fast startup
   * the next time you run the program.
   */
  public BlockChain(NetworkParameters params, Wallet wallet, BlockStore blockStore) {
    try {
      this.blockStore = blockStore;
      chainHead = blockStore.getChainHead();
      log.info("chain head is:\n{}", chainHead.getHeader());
    } catch (BlockStoreException e) {
      throw new RuntimeException(e);
    }

    this.params = params;
    this.wallet = wallet;
  }
Esempio n. 13
0
 public <T extends BlockPayload> T read(BlockPointer pos, Class<T> payloadType) {
   T block = payloadType.cast(dirty.get(pos));
   if (block != null) {
     return block;
   }
   block = payloadType.cast(indexBlockCache.get(pos));
   if (block != null) {
     return block;
   }
   block = store.read(pos, payloadType);
   maybeCache(block);
   return block;
 }
Esempio n. 14
0
  /**
   * Commits a block to Tachyon managed space. The block must be temporary. The block is persisted
   * after {@link BlockStore#commitBlock(long, long)}. The block will not be accessible until {@link
   * WorkerBlockMasterClient#commitBlock} succeeds.
   *
   * @param sessionId The id of the client
   * @param blockId The id of the block to commit
   * @throws BlockAlreadyExistsException if blockId already exists in committed blocks
   * @throws BlockDoesNotExistException if the temporary block cannot be found
   * @throws InvalidWorkerStateException if blockId does not belong to sessionId
   * @throws IOException if the block cannot be moved from temporary path to committed path
   * @throws WorkerOutOfSpaceException if there is no more space left to hold the block
   */
  public void commitBlock(long sessionId, long blockId)
      throws BlockAlreadyExistsException, BlockDoesNotExistException, InvalidWorkerStateException,
          IOException, WorkerOutOfSpaceException {
    mBlockStore.commitBlock(sessionId, blockId);

    // TODO(calvin): Reconsider how to do this without heavy locking.
    // Block successfully committed, update master with new block metadata
    Long lockId = mBlockStore.lockBlock(sessionId, blockId);
    try {
      BlockMeta meta = mBlockStore.getBlockMeta(sessionId, blockId, lockId);
      BlockStoreLocation loc = meta.getBlockLocation();
      Long length = meta.getBlockSize();
      BlockStoreMeta storeMeta = mBlockStore.getBlockStoreMeta();
      Long bytesUsedOnTier = storeMeta.getUsedBytesOnTiers().get(loc.tierAlias());
      mBlockMasterClient.commitBlock(
          WorkerIdRegistry.getWorkerId(), bytesUsedOnTier, loc.tierAlias(), blockId, length);
    } catch (IOException ioe) {
      throw new IOException("Failed to commit block to master.", ioe);
    } finally {
      mBlockStore.unlockBlock(lockId);
    }
  }
Esempio n. 15
0
 /**
  * Frees a block from Tachyon managed space.
  *
  * @param sessionId The id of the client
  * @param blockId The id of the block to be freed
  * @throws InvalidWorkerStateException if blockId has not been committed
  * @throws BlockDoesNotExistException if block cannot be found
  * @throws IOException if block cannot be removed from current path
  */
 public void removeBlock(long sessionId, long blockId)
     throws InvalidWorkerStateException, BlockDoesNotExistException, IOException {
   mBlockStore.removeBlock(sessionId, blockId);
 }
Esempio n. 16
0
 /**
  * Gets the path to the block file in local storage. The block must be a permanent block, and the
  * caller must first obtain the lock on the block.
  *
  * @param sessionId The id of the client
  * @param blockId The id of the block to read
  * @param lockId The id of the lock on this block
  * @return a string representing the path to this block in local storage
  * @throws BlockDoesNotExistException if the blockId cannot be found in committed blocks or lockId
  *     cannot be found
  * @throws InvalidWorkerStateException if sessionId or blockId is not the same as that in the
  *     LockRecord of lockId
  */
 public String readBlock(long sessionId, long blockId, long lockId)
     throws BlockDoesNotExistException, InvalidWorkerStateException {
   BlockMeta meta = mBlockStore.getBlockMeta(sessionId, blockId, lockId);
   return meta.getPath();
 }
Esempio n. 17
0
 /**
  * Gets the block reader for the block. This method is only called by a data server.
  *
  * @param sessionId The id of the client
  * @param blockId The id of the block to read
  * @param lockId The id of the lock on this block
  * @return the block reader for the block
  * @throws BlockDoesNotExistException if lockId is not found
  * @throws InvalidWorkerStateException if sessionId or blockId is not the same as that in the
  *     LockRecord of lockId
  * @throws IOException if block cannot be read
  */
 public BlockReader readBlockRemote(long sessionId, long blockId, long lockId)
     throws BlockDoesNotExistException, InvalidWorkerStateException, IOException {
   return mBlockStore.getBlockReader(sessionId, blockId, lockId);
 }
Esempio n. 18
0
 /**
  * Obtains a read lock the block.
  *
  * @param sessionId The id of the client
  * @param blockId The id of the block to be locked
  * @return the lockId that uniquely identifies the lock obtained
  * @throws BlockDoesNotExistException if blockId cannot be found, for example, evicted already
  */
 public long lockBlock(long sessionId, long blockId) throws BlockDoesNotExistException {
   return mBlockStore.lockBlock(sessionId, blockId);
 }
Esempio n. 19
0
 /**
  * Moves a block from its current location to a target location, currently only tier level moves
  * are supported
  *
  * @param sessionId The id of the client
  * @param blockId The id of the block to move
  * @param tierAlias The alias of the tier to move the block to
  * @throws IllegalArgumentException if tierAlias is out of range of tiered storage
  * @throws BlockDoesNotExistException if blockId cannot be found
  * @throws BlockAlreadyExistsException if blockId already exists in committed blocks of the
  *     newLocation
  * @throws InvalidWorkerStateException if blockId has not been committed
  * @throws WorkerOutOfSpaceException if newLocation does not have enough extra space to hold the
  *     block
  * @throws IOException if block cannot be moved from current location to newLocation
  */
 public void moveBlock(long sessionId, long blockId, String tierAlias)
     throws BlockDoesNotExistException, BlockAlreadyExistsException, InvalidWorkerStateException,
         WorkerOutOfSpaceException, IOException {
   BlockStoreLocation dst = BlockStoreLocation.anyDirInTier(tierAlias);
   mBlockStore.moveBlock(sessionId, blockId, dst);
 }
Esempio n. 20
0
 /**
  * Checks if the storage has a given block.
  *
  * @param blockId the block ID
  * @return true if the block is contained, false otherwise
  */
 public boolean hasBlockMeta(long blockId) {
   return mBlockStore.hasBlockMeta(blockId);
 }
Esempio n. 21
0
 /**
  * Gets the metadata of a block given its blockId or throws IOException. This method does not
  * require a lock ID so the block is possible to be moved or removed after it returns.
  *
  * @param blockId the block ID
  * @return metadata of the block
  * @throws BlockDoesNotExistException if no BlockMeta for this blockId is found
  */
 public BlockMeta getVolatileBlockMeta(long blockId) throws BlockDoesNotExistException {
   return mBlockStore.getVolatileBlockMeta(blockId);
 }
Esempio n. 22
0
 /**
  * Gets the metadata for the entire block store. Contains the block mapping per storage dir and
  * the total capacity and used capacity of each tier.
  *
  * @return the block store metadata
  */
 public BlockStoreMeta getStoreMeta() {
   return mBlockStore.getBlockStoreMeta();
 }
Esempio n. 23
0
 /**
  * Request an amount of space for a block in its storage directory. The block must be a temporary
  * block.
  *
  * @param sessionId The id of the client
  * @param blockId The id of the block to allocate space to
  * @param additionalBytes The amount of bytes to allocate
  * @throws BlockDoesNotExistException if blockId can not be found, or some block in eviction plan
  *     cannot be found
  * @throws WorkerOutOfSpaceException if requested space can not be satisfied
  * @throws IOException if blocks in {@link tachyon.worker.block.evictor.EvictionPlan} fail to be
  *     moved or deleted on file system
  */
 public void requestSpace(long sessionId, long blockId, long additionalBytes)
     throws BlockDoesNotExistException, WorkerOutOfSpaceException, IOException {
   mBlockStore.requestSpace(sessionId, blockId, additionalBytes);
 }
Esempio n. 24
0
 // TODO(calvin): Remove when lock and reads are separate operations.
 public void unlockBlock(long sessionId, long blockId) throws BlockDoesNotExistException {
   mBlockStore.unlockBlock(sessionId, blockId);
 }
Esempio n. 25
0
 /**
  * Relinquishes the lock with the specified lock id.
  *
  * @param lockId The id of the lock to relinquish
  * @throws BlockDoesNotExistException if lockId cannot be found
  */
 public void unlockBlock(long lockId) throws BlockDoesNotExistException {
   mBlockStore.unlockBlock(lockId);
 }
Esempio n. 26
0
 /**
  * Creates a block. This method is only called from a data server.
  *
  * <p>Call {@link #getTempBlockWriterRemote(long, long)} to get a writer for writing to the block.
  *
  * @param sessionId The id of the client
  * @param blockId The id of the block to be created
  * @param tierAlias The alias of the tier to place the new block in
  * @param initialBytes The initial amount of bytes to be allocated
  * @throws IllegalArgumentException if location does not belong to tiered storage
  * @throws BlockAlreadyExistsException if blockId already exists, either temporary or committed,
  *     or block in eviction plan already exists
  * @throws WorkerOutOfSpaceException if this Store has no more space than the initialBlockSize
  * @throws IOException if blocks in eviction plan fail to be moved or deleted
  */
 public void createBlockRemote(long sessionId, long blockId, String tierAlias, long initialBytes)
     throws BlockAlreadyExistsException, WorkerOutOfSpaceException, IOException {
   BlockStoreLocation loc = BlockStoreLocation.anyDirInTier(tierAlias);
   TempBlockMeta createdBlock = mBlockStore.createBlockMeta(sessionId, blockId, loc, initialBytes);
   FileUtils.createBlockPath(createdBlock.getPath());
 }
Esempio n. 27
0
 /**
  * Set the pinlist for the underlying blockstore. Typically called by PinListSync.
  *
  * @param pinnedInodes a set of pinned inodes
  */
 public void updatePinList(Set<Long> pinnedInodes) {
   mBlockStore.updatePinnedInodes(pinnedInodes);
 }
Esempio n. 28
0
 /**
  * Frees space to make a specific amount of bytes available in the tier.
  *
  * @param sessionId the session ID
  * @param availableBytes the amount of free space in bytes
  * @param tierAlias the alias of the tier to free space
  * @throws WorkerOutOfSpaceException if there is not enough space
  * @throws BlockDoesNotExistException if blocks can not be found
  * @throws IOException if blocks fail to be moved or deleted on file system
  * @throws BlockAlreadyExistsException if blocks to move already exists in destination location
  * @throws InvalidWorkerStateException if blocks to move/evict is uncommitted
  */
 public void freeSpace(long sessionId, long availableBytes, String tierAlias)
     throws WorkerOutOfSpaceException, BlockDoesNotExistException, IOException,
         BlockAlreadyExistsException, InvalidWorkerStateException {
   BlockStoreLocation location = BlockStoreLocation.anyDirInTier(tierAlias);
   mBlockStore.freeSpace(sessionId, availableBytes, location);
 }
Esempio n. 29
0
 /**
  * Aborts the temporary block created by the session.
  *
  * @param sessionId The id of the client
  * @param blockId The id of the block to be aborted
  * @throws BlockAlreadyExistsException if blockId already exists in committed blocks
  * @throws BlockDoesNotExistException if the temporary block cannot be found
  * @throws InvalidWorkerStateException if blockId does not belong to sessionId
  * @throws IOException if temporary block cannot be deleted
  */
 public void abortBlock(long sessionId, long blockId)
     throws BlockAlreadyExistsException, BlockDoesNotExistException, InvalidWorkerStateException,
         IOException {
   mBlockStore.abortBlock(sessionId, blockId);
 }
Esempio n. 30
0
 /**
  * Opens a {@link BlockWriter} for an existing temporary block. This method is only called from a
  * data server.
  *
  * <p>The temporary block must already exist with {@link #createBlockRemote(long, long, String,
  * long)}.
  *
  * @param sessionId The id of the client
  * @param blockId The id of the block to be opened for writing
  * @return the block writer for the local block file
  * @throws BlockDoesNotExistException if the block cannot be found
  * @throws IOException if block cannot be created
  */
 public BlockWriter getTempBlockWriterRemote(long sessionId, long blockId)
     throws BlockDoesNotExistException, IOException {
   return mBlockStore.getBlockWriter(sessionId, blockId);
 }