/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package tachyon.master; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.Collections; import org.apache.log4j.Logger; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.ObjectWriter; import tachyon.Constants; import tachyon.thrift.ClientFileInfo; /** * Tachyon file system's folder representation in master. */ public class InodeFolder extends Inode { private static final Logger LOG = Logger.getLogger(Constants.LOGGER_TYPE); /** * Create a new InodeFile from a JsonParser and an image Json element. * * @param parser * the JsonParser to get the next element * @param ele * the current InodeFolder's Json image element. * @return the constructed InodeFolder. * @throws IOException */ static InodeFolder loadImage(JsonParser parser, ImageElement ele) throws IOException { long creationTimeMs = ele.getLong("creationTimeMs"); int fileId = ele.getInt("id"); String fileName = ele.getString("name"); int parentId = ele.getInt("parentId"); boolean isPinned = ele.getBoolean("pinned"); List<Integer> childrenIds = ele.<List<Integer>> get("childrenIds"); int numberOfChildren = childrenIds.size(); Inode[] children = new Inode[numberOfChildren]; for (int k = 0; k < numberOfChildren; k ++) { try { ele = parser.readValueAs(ImageElement.class); LOG.debug("Read Element: " + ele); } catch (IOException e) { throw e; } switch (ele.type) { case InodeFile: { children[k] = InodeFile.loadImage(ele); break; } case InodeFolder: { children[k] = InodeFolder.loadImage(parser, ele); break; } default: throw new IOException("Invalid element type " + ele); } } InodeFolder folder = new InodeFolder(fileName, fileId, parentId, creationTimeMs); folder.setPinned(isPinned); folder.addChildren(children); return folder; } private Set<Inode> mChildren = new HashSet<Inode>(); public InodeFolder(String name, int id, int parentId, long creationTimeMs) { super(name, id, parentId, true, creationTimeMs); } /** * Adds the given inode to the set of children. * * @param child * The inode to add */ public synchronized void addChild(Inode child) { mChildren.add(child); } /** * Adds the given inodes to the set of children. * * @param children * The inodes to add */ public synchronized void addChildren(Inode[] children) { for (Inode child : children) { addChild(child); } } /** * Generates client file info for the folder. * * @param path * The path of the folder in the filesystem * @return the generated ClientFileInfo */ @Override public ClientFileInfo generateClientFileInfo(String path) { ClientFileInfo ret = new ClientFileInfo(); ret.id = getId(); ret.name = getName(); ret.path = path; ret.ufsPath = ""; ret.length = 0; ret.blockSizeByte = 0; ret.creationTimeMs = getCreationTimeMs(); ret.isComplete = true; ret.isFolder = true; ret.isPinned = isPinned(); ret.isCache = false; ret.blockIds = null; ret.dependencyId = -1; return ret; } /** * Returns the child with the given id. * * @param fid * The id of the child * @return the inode with the given id, or null if there is no child with that id */ public synchronized Inode getChild(int fid) { for (Inode child : mChildren) { if (child.getId() == fid) { return child; } } return null; } /** * Returns the child with the given name. * * @param name * The name of the child * @return the inode with the given name, or null if there is no child with that name */ public synchronized Inode getChild(String name) { for (Inode child : mChildren) { if (child.getName().equals(name)) { return child; } } return null; } /** * Returns the folder's children. * * @return an unmodifiable set of the children inodes. */ public synchronized Set<Inode> getChildren() { return Collections.unmodifiableSet(mChildren); } /** * Returns the ids of the children. * * @return the ids of the children */ public synchronized List<Integer> getChildrenIds() { List<Integer> ret = new ArrayList<Integer>(mChildren.size()); for (Inode child : mChildren) { ret.add(child.getId()); } return ret; } /** * Returns the number of children the folder has. * * @return the number of children in the folder. */ public synchronized int getNumberOfChildren() { return mChildren.size(); } /** * Removes the given inode from the folder. * * @param child * The Inode to remove * @return true if the inode was removed, false otherwise. */ public synchronized boolean removeChild(Inode child) { return mChildren.remove(child); } /** * Removes the given child from the folder. * * @param name * The name of the Inode to remove. * @return true if the inode was removed, false otherwise. */ public synchronized boolean removeChild(String name) { for (Inode child : mChildren) { if (child.getName().equals(name)) { mChildren.remove(child); return true; } } return false; } @Override public String toString() { StringBuilder sb = new StringBuilder("InodeFolder("); sb.append(super.toString()).append(",").append(mChildren).append(")"); return sb.toString(); } /** * Write an image of the folder. * * @param os * The output stream to write the folder to */ @Override public void writeImage(ObjectWriter objWriter, DataOutputStream dos) throws IOException { ImageElement ele = new ImageElement(ImageElementType.InodeFolder) .withParameter("creationTimeMs", getCreationTimeMs()).withParameter("id", getId()) .withParameter("name", getName()).withParameter("parentId", getParentId()) .withParameter("pinned", isPinned()).withParameter("childrenIds", getChildrenIds()); writeElement(objWriter, dos, ele); for (Inode inode : getChildren()) { inode.writeImage(objWriter, dos); } } }