/* * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0 * (the "License"). You may not use this work except in compliance with the License, which is * available at www.apache.org/licenses/LICENSE-2.0 * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied, as more fully set forth in the License. * * See the NOTICE file distributed with this work for information regarding copyright ownership. */ package alluxio.web; import alluxio.AlluxioURI; import alluxio.WorkerStorageTierAssoc; import alluxio.client.file.FileSystem; import alluxio.client.file.URIStatus; import alluxio.exception.AlluxioException; import alluxio.exception.BlockDoesNotExistException; import alluxio.exception.FileDoesNotExistException; import alluxio.master.block.BlockId; import alluxio.worker.block.BlockStoreMeta; import alluxio.worker.block.BlockWorker; import alluxio.worker.block.meta.BlockMeta; import com.google.common.base.Preconditions; import org.apache.commons.lang3.tuple.ImmutablePair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map.Entry; import java.util.Set; import javax.annotation.concurrent.ThreadSafe; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet that provides data for displaying block info of a worker. */ @ThreadSafe public final class WebInterfaceWorkerBlockInfoServlet extends HttpServlet { private static final Logger LOG = LoggerFactory.getLogger(WebInterfaceWorkerBlockInfoServlet.class); private static final long serialVersionUID = 4148506607369321012L; private final transient BlockWorker mBlockWorker; /** * Creates a new instance of {@link WebInterfaceWorkerBlockInfoServlet}. * * @param blockWorker block worker handle */ public WebInterfaceWorkerBlockInfoServlet(BlockWorker blockWorker) { mBlockWorker = Preconditions.checkNotNull(blockWorker); } /** * Populates attributes before redirecting to a jsp. * * @param request the {@link HttpServletRequest} object * @param response the {@link HttpServletResponse} object * @throws ServletException if the target resource throws this exception */ @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setAttribute("fatalError", ""); String filePath = request.getParameter("path"); if (!(filePath == null || filePath.isEmpty())) { // Display file block info try { UIFileInfo uiFileInfo = getUiFileInfo(new AlluxioURI(filePath)); List<ImmutablePair<String, List<UIFileBlockInfo>>> fileBlocksOnTier = new ArrayList<>(); for (Entry<String, List<UIFileBlockInfo>> e : uiFileInfo.getBlocksOnTier().entrySet()) { fileBlocksOnTier.add( new ImmutablePair<>(e.getKey(), e.getValue())); } request.setAttribute("fileBlocksOnTier", fileBlocksOnTier); request.setAttribute("blockSizeBytes", uiFileInfo.getBlockSizeBytes()); request.setAttribute("path", filePath); getServletContext().getRequestDispatcher("/worker/viewFileBlocks.jsp").forward(request, response); return; } catch (FileDoesNotExistException e) { request.setAttribute("fatalError", "Error: Invalid Path " + e.getMessage()); getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response); return; } catch (IOException e) { request.setAttribute("invalidPathError", "Error: File " + filePath + " is not available " + e.getMessage()); getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response); return; } catch (BlockDoesNotExistException e) { request.setAttribute("fatalError", "Error: block not found. " + e.getMessage()); getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response); return; } catch (AlluxioException e) { request.setAttribute("fatalError", "Error: alluxio exception. " + e.getMessage()); getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response); return; } } List<Long> fileIds = getSortedFileIds(); request.setAttribute("nTotalFile", fileIds.size()); request.setAttribute("orderedTierAliases", new WorkerStorageTierAssoc().getOrderedStorageAliases()); // URL can not determine offset and limit, let javascript in jsp determine and redirect if (request.getParameter("offset") == null && request.getParameter("limit") == null) { getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response); return; } try { int offset = Integer.parseInt(request.getParameter("offset")); int limit = Integer.parseInt(request.getParameter("limit")); List<Long> subFileIds = fileIds.subList(offset, offset + limit); List<UIFileInfo> uiFileInfos = new ArrayList<>(subFileIds.size()); for (long fileId : subFileIds) { try { uiFileInfos.add(getUiFileInfo(fileId)); } catch (Exception e) { // The file might have been deleted, log a warning and ignore this file. LOG.warn("Unable to get file info for fileId {}. {}", fileId, e.getMessage()); } } request.setAttribute("fileInfos", uiFileInfos); } catch (NumberFormatException e) { request.setAttribute("fatalError", "Error: offset or limit parse error, " + e.getLocalizedMessage()); getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response); return; } catch (IndexOutOfBoundsException e) { request.setAttribute("fatalError", "Error: offset or offset + limit is out of bound, " + e.getLocalizedMessage()); getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response); return; } catch (Exception e) { request.setAttribute("fatalError", e.getLocalizedMessage()); getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response); return; } getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response); } /*** * Gets sorted file ids of the files cached in the worker. * * @return a sorted file id list */ private List<Long> getSortedFileIds() { Set<Long> fileIds = new HashSet<>(); BlockStoreMeta storeMeta = mBlockWorker.getStoreMetaFull(); for (List<Long> blockIds : storeMeta.getBlockList().values()) { for (long blockId : blockIds) { long fileId = BlockId.createBlockId(BlockId.getContainerId(blockId), BlockId.getMaxSequenceNumber()); fileIds.add(fileId); } } List<Long> sortedFileIds = new ArrayList<>(fileIds); Collections.sort(sortedFileIds); return sortedFileIds; } /*** * Gets the {@link UIFileInfo} object based on file id. * * @param fileId the file id of the file * @return the {@link UIFileInfo} object of the file */ private UIFileInfo getUiFileInfo(long fileId) throws IOException, AlluxioException { return getUiFileInfo(new URIStatus(mBlockWorker.getFileInfo(fileId))); } /** * Gets the {@link UIFileInfo} object based on file path. * * @param filePath the path of the file * @return the {@link UIFileInfo} object of the file */ private UIFileInfo getUiFileInfo(AlluxioURI filePath) throws IOException, AlluxioException { return getUiFileInfo(FileSystem.Factory.get().getStatus(filePath)); } /** * Gets the {@link UIFileInfo} object based on URI status. * * @param status the URI status to use * @return the {@link UIFileInfo} object of the file * @throws BlockDoesNotExistException if the block does not exist * @throws FileDoesNotExistException if the file does not exist */ private UIFileInfo getUiFileInfo(URIStatus status) throws BlockDoesNotExistException, FileDoesNotExistException { UIFileInfo uiFileInfo = new UIFileInfo(status); boolean blockExistOnWorker = false; for (long blockId : status.getBlockIds()) { if (mBlockWorker.hasBlockMeta(blockId)) { blockExistOnWorker = true; BlockMeta blockMeta = mBlockWorker.getVolatileBlockMeta(blockId); long blockSize = blockMeta.getBlockSize(); // The block last access time is not available. Use -1 for now. // It's not necessary to show location information here since // we are viewing at the context of this worker. uiFileInfo.addBlock(blockMeta.getBlockLocation().tierAlias(), blockId, blockSize, -1); } } if (!blockExistOnWorker) { throw new FileDoesNotExistException(status.getPath()); } return uiFileInfo; } }