/* * Copyright (C) 2015 hops.io. * * Licensed 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 org.apache.hadoop.hdfs.server.namenode; import io.hops.exception.StorageException; import io.hops.exception.TransactionContextException; import io.hops.metadata.common.CounterType; import io.hops.metadata.common.FinderType; import io.hops.metadata.hdfs.entity.LeasePath; import io.hops.transaction.EntityManager; import org.apache.hadoop.hdfs.protocol.Block; import java.util.Collection; import java.util.TreeSet; /** * ********************************************************** * A Lease governs all the locks held by a single client. For each client * there's a corresponding lease, whose timestamp is updated when the client * periodically checks in. If the client dies and allows its lease to expire, * all the corresponding locks can be released. * *********************************************************** */ public class Lease implements Comparable<Lease> { public static enum Counter implements CounterType<Lease> { All; @Override public Class getType() { return Lease.class; } } public static enum Finder implements FinderType<Lease> { ByHolder, ByHolderId; @Override public Class getType() { return Lease.class; } @Override public Annotation getAnnotated() { switch (this) { case ByHolder: return Annotation.PrimaryKey; case ByHolderId: return Annotation.PrunedIndexScan; default: throw new IllegalStateException(); } } } private final String holder; private long lastUpdate; private Collection<LeasePath> paths = null; private int holderID; public Lease(String holder, int holderID, long lastUpd) { this.holder = holder; this.holderID = holderID; this.lastUpdate = lastUpd; } public void setLastUpdate(long lastUpd) { this.lastUpdate = lastUpd; } public void setPaths(TreeSet<LeasePath> paths) { this.paths = paths; } public long getLastUpdate() { return this.lastUpdate; } public void setHolderID(int holderID) { this.holderID = holderID; } public int getHolderID() { return this.holderID; } public boolean removePath(LeasePath lPath) throws StorageException, TransactionContextException { return getPaths().remove(lPath); } public void addPath(LeasePath lPath) throws StorageException, TransactionContextException { getPaths().add(lPath); } public void addFirstPath(LeasePath lPath) { this.paths = new TreeSet<LeasePath>(); this.paths.add(lPath); } /** * Does this lease contain any path? */ boolean hasPath() throws StorageException, TransactionContextException { return !this.getPaths().isEmpty(); } /** * {@inheritDoc} */ @Override public String toString() { int size = 0; if (paths != null) { size = paths.size(); } return "[Lease. Holder: " + holder + ", pendingcreates: " + size + "]"; } /** * {@inheritDoc} */ @Override public int compareTo(Lease o) { Lease l1 = this; Lease l2 = o; long lu1 = l1.lastUpdate; long lu2 = l2.lastUpdate; if (lu1 < lu2) { return -1; } else if (lu1 > lu2) { return 1; } else { return l1.holder.compareTo(l2.holder); } } /** * {@inheritDoc} */ @Override public boolean equals(Object o) { if (!(o instanceof Lease)) { return false; } Lease obj = (Lease) o; if (lastUpdate == obj.lastUpdate && holder.equals(obj.holder)) { return true; } return false; } /** * {@inheritDoc} */ @Override public int hashCode() { return holder.hashCode(); } public Collection<LeasePath> getPaths() throws StorageException, TransactionContextException { if (paths == null) { paths = EntityManager.findList(LeasePath.Finder.ByHolderId, holderID); } return paths; } public String getHolder() { return holder; } // void replacePath(LeasePath oldpath, LeasePath newpath) // throws StorageException, TransactionContextException { // getPaths().remove(oldpath); // getPaths().add(newpath); // } public static int getHolderId(String holder){ return holder.hashCode(); } public void updateLastTwoBlocksInLeasePath(String path, Block lastBlock, Block penultimateBlock) throws TransactionContextException, StorageException { updateLastTwoBlocksInLeasePath(path, lastBlock == null ? -1 : lastBlock .getBlockId(), penultimateBlock == null ? -1 : penultimateBlock.getBlockId()); } private void updateLastTwoBlocksInLeasePath(String path, long lastBlockId, long penultimateBlockId) throws TransactionContextException, StorageException { Collection<LeasePath> lps = getPaths(); for(LeasePath lp : lps){ if(lp.getPath().equals(path)){ lp.setLastBlockId(lastBlockId); lp.setPenultimateBlockId(penultimateBlockId); EntityManager.update(lp); break; } } } public LeasePath getLeasePath(String path) throws TransactionContextException, StorageException { Collection<LeasePath> lps = getPaths(); for(LeasePath lp : lps){ if(lp.getPath().equals(path)){ return lp; } } return null; } }