/** * Request space from the worker * * @param userId The id of the user who send the request * @param requestBytes The requested space size, in bytes * @return true if succeed, false otherwise * @throws TException */ public boolean requestSpace(long userId, long requestBytes) throws TException { LOG.info( "requestSpace(" + userId + ", " + requestBytes + "): Current available: " + mWorkerSpaceCounter.getAvailableBytes() + " requested: " + requestBytes); if (mWorkerSpaceCounter.getCapacityBytes() < requestBytes) { LOG.info( "user_requestSpace(): requested memory size is larger than the total memory on" + " the machine."); return false; } while (!mWorkerSpaceCounter.requestSpaceBytes(requestBytes)) { if (!memoryEvictionLRU(requestBytes)) { return false; } } mUsers.addOwnBytes(userId, requestBytes); return true; }
/** * Check worker's status. This should be executed periodically. * * <p>It finds the timeout users and cleans them up. */ public void checkStatus() { List<Long> removedUsers = mUsers.checkStatus(); for (long userId : removedUsers) { mWorkerSpaceCounter.returnUsedBytes(mUsers.removeUser(userId)); synchronized (mUsersPerLockedBlock) { Set<Long> blockds = mLockedBlocksPerUser.get(userId); mLockedBlocksPerUser.remove(userId); if (blockds != null) { for (long blockId : blockds) { try { unlockBlock(blockId, userId); } catch (TException e) { throw Throwables.propagate(e); } } } } } }
/** * Return the space which has been requested * * @param userId The id of the user who wants to return the space * @param returnedBytes The returned space size, in bytes * @throws TException */ public void returnSpace(long userId, long returnedBytes) throws TException { long preAvailableBytes = mWorkerSpaceCounter.getAvailableBytes(); if (returnedBytes > mUsers.ownBytes(userId)) { LOG.error("User " + userId + " does not own " + returnedBytes + " bytes."); } else { mWorkerSpaceCounter.returnUsedBytes(returnedBytes); mUsers.addOwnBytes(userId, -returnedBytes); } LOG.info( "returnSpace(" + userId + ", " + returnedBytes + ") : " + preAvailableBytes + " returned: " + returnedBytes + ". New Available: " + mWorkerSpaceCounter.getAvailableBytes()); }
/** * Notify the worker the block is cached. * * <p>This call is called remotely from {@link tachyon.client.TachyonFS#cacheBlock(long)} which is * only ever called from {@link tachyon.client.BlockOutStream#close()} (though its a public api so * anyone could call it). There are a few interesting preconditions for this to work. * * <p>1) Client process writes to files locally under a tachyon defined temp directory. 2) Worker * process is on the same node as the client 3) Client is talking to the local worker directly * * <p>If all conditions are true, then and only then can this method ever be called; all * operations work on local files. * * @param userId The user id of the client who send the notification * @param blockId The id of the block * @throws FileDoesNotExistException * @throws SuspectedFileSizeException * @throws BlockInfoException * @throws TException */ public void cacheBlock(long userId, long blockId) throws FileDoesNotExistException, SuspectedFileSizeException, BlockInfoException, TException { File srcFile = new File(CommonUtils.concat(getUserTempFolder(userId), blockId)); File dstFile = new File(CommonUtils.concat(mLocalDataFolder, blockId)); long fileSizeBytes = srcFile.length(); if (!srcFile.exists()) { throw new FileDoesNotExistException("File " + srcFile + " does not exist."); } if (!srcFile.renameTo(dstFile)) { throw new FileDoesNotExistException( "Failed to rename file from " + srcFile.getPath() + " to " + dstFile.getPath()); } addBlockId(blockId, fileSizeBytes); mUsers.addOwnBytes(userId, -fileSizeBytes); mMasterClient.worker_cacheBlock( mWorkerId, mWorkerSpaceCounter.getUsedBytes(), blockId, fileSizeBytes); LOG.info(userId + " " + dstFile); }
/** * Handle the user's heartbeat. * * @param userId The id of the user * @throws TException */ public void userHeartbeat(long userId) throws TException { mUsers.userHeartbeat(userId); }
/** * Get the user temporary folder in the under file system of the specified user. * * <p>This method is a wrapper around {@link tachyon.Users#getUserUnderfsTempFolder(long)}, and as * such should be referentially transparent with {@link Users#getUserUnderfsTempFolder(long)}. In * the context of {@code this}, this call will output the result of path concat of {@link * #mUnderfsWorkerFolder} with the provided {@literal userId}. * * <p>This method differs from {@link #getUserTempFolder(long)} in the context of where write * operations end up. This temp folder generated lives inside the {@link tachyon.UnderFileSystem}, * and as such, will be stored remotely, most likely on disk. * * @param userId The id of the user * @return The user temporary folder in the under file system * @throws TException */ public String getUserUnderfsTempFolder(long userId) throws TException { String ret = mUsers.getUserUnderfsTempFolder(userId); LOG.info("Return UserHdfsTempFolder for " + userId + " : " + ret); return ret; }
/** * Get the local user temporary folder of the specified user. * * <p>This method is a wrapper around {@link tachyon.Users#getUserTempFolder(long)}, and as such * should be referentially transparent with {@link tachyon.Users#getUserTempFolder(long)}. In the * context of {@code this}, this call will output the result of path concat of {@link * #mLocalUserFolder} with the provided {@literal userId}. * * <p>This method differs from {@link #getUserUfsTempFolder(long)} in the context of where write * operations end up. This temp folder generated lives inside the tachyon file system, and as * such, will be stored in memory. * * @see tachyon.Users#getUserTempFolder(long) * @param userId The id of the user * @return The local user temporary folder of the specified user * @throws IOException */ public String getUserLocalTempFolder(long userId) throws IOException { String ret = mUsers.getUserTempFolder(userId); LOG.info("Return UserTempFolder for " + userId + " : " + ret); return ret; }