summaryrefslogtreecommitdiffstats
path: root/simple/simple-common/src/main/java/org/simpleframework/common/lease/Expiration.java
blob: fca1c140b425246a416b21939d042d13aabe502c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
 * Expiration.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.common.lease;

import static java.util.concurrent.TimeUnit.NANOSECONDS;

import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * A <code>Expiration</code> is used to represent the expiration
 * for a lease. 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 Expiration<T> implements Contract<T> {

   /**
    * This is the expiration time in nanoseconds for this.
    */
   private volatile long time;
   
   /**
    * This is the key representing the resource being lease.
    */   
   private T key;
   
   /**
    * Constructor for the <code>Expiration</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 Expiration(T key, long lease, TimeUnit scale) {
      this.time = 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
    */   
   public T getKey() {
      return 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
    */   
   public long getDelay(TimeUnit unit) {
      return unit.convert(time - 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
    */   
   public void setDelay(long delay, TimeUnit unit) {
      this.time = 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
    */   
   public int compareTo(Delayed other) {
      Expiration value = (Expiration) other;  
      
      if(other == this) {
         return 0;
      }
      return compareTo(value);
   }
   
   /**
    * 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 value this is the expiration to be compared with this
    * 
    * @return this returns zero if equal otherwise the difference
    */   
   private int compareTo(Expiration value) {
      long diff = time - value.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
    */
   public String toString() {
      return String.format("contract %s", key);
   }
}