/* * Entry.java May 2004 * * Copyright (C) 2004, Niall Gallagher <niallg@users.sf.net> * * 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.simpleframework.util.lease; import static java.util.concurrent.TimeUnit.NANOSECONDS; import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit; /** * A <code>Entry</code> is used to represent the contract a lease has been * issued. This contains all relevant information for the the lease, such as the * keyed resource that has been leased and the duration of the lease. Durations * for the contract can be measured in any <code>TimeUnit</code> for * convenience. * * @author Niall Gallagher */ class Entry<T> implements Contract<T> { /** * This is the time that this entry expires in nanoseconds. */ private volatile long time; /** * This is the key representing the resource being lease. */ private T key; /** * Constructor for the <code>Entry</code> object. This is used to create a * contract with an initial expiry period. Once this is created the time is * taken and the contract can be issued. * * @param key * this is the key that this contract represents * @param lease * this is the initial lease duration to be used * @param scale * this is the time unit scale that is to be used */ public Entry(T key, long lease, TimeUnit scale) { this.time = this.getTime() + scale.toNanos(lease); this.key = key; } /** * This returns the key for the resource this represents. This is used when * the contract has expired to clean resources associated with the lease. It * is passed in to the cleaner as an parameter to the callback. The cleaner * is then responsible for cleaning any resources associated with the lease. * * @return returns the resource key that this represents */ @Override public T getKey() { return this.key; } /** * This method will return the number of <code>TimeUnit</code> seconds that * remain in the contract. If the value returned is less than or equal to * zero then it should be assumed that the lease has expired, if greater * than zero the lease is active. * * @return returns the duration in the time unit remaining */ @Override public long getDelay(TimeUnit unit) { return unit.convert(this.time - this.getTime(), NANOSECONDS); } /** * This method is used to set the number of <code>TimeUnit</code> seconds * that should remain within the contract. This is used when the contract is * to be reissued. Once a new duration has been set the contract for the * lease has been changed and the previous expiry time is ignores, so only * one clean is called. * * @param delay * this is the delay to be used for this contract * @param unit * this is the time unit measurment for the delay */ @Override public void setDelay(long delay, TimeUnit unit) { this.time = this.getTime() + unit.toNanos(delay); } /** * This method returns the current time in nanoseconds. This is used to * allow the duration of the lease to be calculated with any given time unit * which allows flexibility in setting and getting the current delay for the * contract. * * @return returns the current time in nanoseconds remaining */ private long getTime() { return System.nanoTime(); } /** * This is used to compare the specified delay to this delay. The result of * this operation is used to prioritize contracts in order of first to * expire. Contracts that expire first reach the top of the contract queue * and are taken off for cleaning. * * @param other * this is the delay to be compared with this * * @return this returns zero if equal otherwise the difference */ @Override public int compareTo(Delayed other) { Entry entry = (Entry) other; if (other == this) return 0; return this.compareTo(entry); } /** * This is used to compare the specified delay to this delay. The result of * this operation is used to prioritize contracts in order of first to * expire. Contracts that expire first reach the top of the contract queue * and are taken off for cleaning. * * @param entry * this is the entry to be compared with this * * @return this returns zero if equal otherwise the difference */ private int compareTo(Entry entry) { long diff = this.time - entry.time; if (diff < 0) return -1; else if (diff > 0) return 1; return 0; } /** * This is used to provide a description of the contract that the instance * represents. A description well contain the key owned by the contract as * well as the expiry time expected for it. This is used to provide * descriptive messages in the exceptions. * * @return a descriptive message describing the contract object */ @Override public String toString() { return String.format("contract %s", this.key); } }