package tachyon.master; import java.io.DataOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.log4j.Logger; import com.fasterxml.jackson.databind.ObjectWriter; import tachyon.Constants; import tachyon.conf.MasterConf; import tachyon.io.Utils; import tachyon.thrift.ClientDependencyInfo; import tachyon.util.CommonUtils; public class Dependency extends ImageWriter { private static final Logger LOG = Logger.getLogger(Constants.LOGGER_TYPE); /** * Create a new dependency from a JSON Element. * * @param ele * the JSON element * @return the loaded dependency * @throws IOException */ static Dependency loadImage(ImageElement ele) throws IOException { Dependency dep = new Dependency(ele.getInt("depID"), ele.<List<Integer>> get("parentFiles"), ele.<List<Integer>> get("childrenFiles"), ele.getString("commandPrefix"), ele.getByteBufferList("data"), ele.getString("comment"), ele.getString("framework"), ele.getString("frameworkVersion"), ele.<DependencyType> get("dependencyType"), ele.<List<Integer>> get("parentDeps"), ele.getLong("creationTimeMs")); dep.resetUncheckpointedChildrenFiles(ele.<List<Integer>> get("unCheckpointedChildrenFiles")); return dep; } public final int ID; public final long CREATION_TIME_MS; public final List<Integer> PARENT_FILES; public final List<Integer> CHILDREN_FILES; private final Set<Integer> UNCHECKPOINTED_CHILDREN_FILES; public final String COMMAND_PREFIX; public final List<ByteBuffer> DATA; public final String COMMENT; public final String FRAMEWORK; public final String FRAMEWORK_VERSION; public final DependencyType TYPE; public final List<Integer> PARENT_DEPENDENCIES; private List<Integer> mChildrenDependencies; private Set<Integer> mLostFileIds; public Dependency(int id, List<Integer> parents, List<Integer> children, String commandPrefix, List<ByteBuffer> data, String comment, String framework, String frameworkVersion, DependencyType type, Collection<Integer> parentDependencies, long creationTimeMs) { ID = id; CREATION_TIME_MS = creationTimeMs; PARENT_FILES = new ArrayList<Integer>(parents.size()); PARENT_FILES.addAll(parents); CHILDREN_FILES = new ArrayList<Integer>(children.size()); CHILDREN_FILES.addAll(children); UNCHECKPOINTED_CHILDREN_FILES = new HashSet<Integer>(); UNCHECKPOINTED_CHILDREN_FILES.addAll(CHILDREN_FILES); COMMAND_PREFIX = commandPrefix; DATA = CommonUtils.cloneByteBufferList(data); COMMENT = comment; FRAMEWORK = framework; FRAMEWORK_VERSION = frameworkVersion; TYPE = type; PARENT_DEPENDENCIES = new ArrayList<Integer>(parentDependencies.size()); PARENT_DEPENDENCIES.addAll(parentDependencies); mChildrenDependencies = new ArrayList<Integer>(0); mLostFileIds = new HashSet<Integer>(0); } public synchronized void addChildrenDependency(int childDependencyId) { for (int dependencyId : mChildrenDependencies) { if (dependencyId == childDependencyId) { return; } } mChildrenDependencies.add(childDependencyId); } public synchronized void addLostFile(int fileId) { mLostFileIds.add(fileId); } public synchronized void childCheckpointed(int childFileId) { UNCHECKPOINTED_CHILDREN_FILES.remove(childFileId); LOG.debug("Child got checkpointed " + childFileId + " : " + toString()); } public ClientDependencyInfo generateClientDependencyInfo() { ClientDependencyInfo ret = new ClientDependencyInfo(); ret.id = ID; ret.parents = new ArrayList<Integer>(PARENT_FILES.size()); ret.parents.addAll(PARENT_FILES); ret.children = new ArrayList<Integer>(CHILDREN_FILES.size()); ret.children.addAll(CHILDREN_FILES); ret.data = CommonUtils.cloneByteBufferList(DATA); return ret; } public synchronized List<Integer> getChildrenDependency() { List<Integer> ret = new ArrayList<Integer>(mChildrenDependencies.size()); ret.addAll(mChildrenDependencies); return ret; } public synchronized String getCommand() { // TODO We should support different types of command in the future. // For now, assume there is only one command model. StringBuilder sb = new StringBuilder(parseCommandPrefix()); sb.append(" ").append(MasterConf.get().MASTER_ADDRESS); sb.append(" ").append(ID); for (int k = 0; k < CHILDREN_FILES.size(); k ++) { int id = CHILDREN_FILES.get(k); if (mLostFileIds.contains(id)) { sb.append(" ").append(k); } } mLostFileIds.clear(); return sb.toString(); } public synchronized List<Integer> getLostFiles() { List<Integer> ret = new ArrayList<Integer>(); ret.addAll(mLostFileIds); return ret; } synchronized List<Integer> getUncheckpointedChildrenFiles() { List<Integer> ret = new ArrayList<Integer>(UNCHECKPOINTED_CHILDREN_FILES.size()); ret.addAll(UNCHECKPOINTED_CHILDREN_FILES); return ret; } public synchronized boolean hasCheckpointed() { return UNCHECKPOINTED_CHILDREN_FILES.size() == 0; } public synchronized boolean hasChildrenDependency() { return !mChildrenDependencies.isEmpty(); } public synchronized boolean hasLostFile() { return !mLostFileIds.isEmpty(); } String parseCommandPrefix() { String rtn = COMMAND_PREFIX; for (String s : DependencyVariables.sVariables.keySet()) { rtn = rtn.replace("$" + s, DependencyVariables.sVariables.get(s)); } return rtn; } synchronized void resetUncheckpointedChildrenFiles( Collection<Integer> uncheckpointedChildrenFiles) { UNCHECKPOINTED_CHILDREN_FILES.clear(); UNCHECKPOINTED_CHILDREN_FILES.addAll(uncheckpointedChildrenFiles); } @Override public String toString() { StringBuilder sb = new StringBuilder("Dependency["); sb.append("ID:").append(ID).append(", CREATION_TIME_MS:").append(CREATION_TIME_MS); sb.append(", Parents:").append(PARENT_FILES).append(", Children:").append(CHILDREN_FILES); sb.append(", COMMAND_PREFIX:").append(COMMAND_PREFIX); sb.append(", PARSED_COMMAND_PREFIX:").append(parseCommandPrefix()); sb.append(", COMMENT:").append(COMMENT); sb.append(", FRAMEWORK:").append(FRAMEWORK); sb.append(", FRAMEWORK_VERSION:").append(FRAMEWORK_VERSION); sb.append(", PARENT_DEPENDENCIES:").append(PARENT_DEPENDENCIES); sb.append(", ChildrenDependencies:").append(mChildrenDependencies); sb.append(", UncheckpointedChildrenFiles:").append(UNCHECKPOINTED_CHILDREN_FILES); sb.append("]"); return sb.toString(); } @Override public synchronized void writeImage(ObjectWriter objWriter, DataOutputStream dos) throws IOException { ImageElement ele = new ImageElement(ImageElementType.Dependency).withParameter("depID", ID) .withParameter("parentFiles", PARENT_FILES) .withParameter("childrenFiles", CHILDREN_FILES) .withParameter("commandPrefix", COMMAND_PREFIX) .withParameter("data", Utils.byteBufferListToBase64(DATA)) .withParameter("comment", COMMENT).withParameter("framework", FRAMEWORK) .withParameter("frameworkVersion", FRAMEWORK_VERSION).withParameter("depType", TYPE) .withParameter("parentDeps", PARENT_DEPENDENCIES) .withParameter("creationTimeMs", CREATION_TIME_MS) .withParameter("unCheckpointedChildrenFiles", getUncheckpointedChildrenFiles()); writeElement(objWriter, dos, ele); } }