View Javadoc
1   package org.apache.commons.jcs3.engine;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.List;
24  
25  import org.apache.commons.jcs3.engine.behavior.IElementAttributes;
26  import org.apache.commons.jcs3.engine.control.event.behavior.IElementEventHandler;
27  
28  /**
29   * This it the element attribute descriptor class. Each element in the cache has an ElementAttribute
30   * object associated with it. An ElementAttributes object can be associated with an element in 3
31   * ways:
32   * <ol>
33   * <li>When the item is put into the cache, you can associate an element attributes object.</li>
34   * <li>If not attributes object is include when the element is put into the cache, then the default
35   * attributes for the region will be used.</li>
36   * <li>The element attributes can be reset. This effectively results in a retrieval followed by a
37   * put. Hence, this is the same as 1.</li>
38   * </ol>
39   */
40  public class ElementAttributes
41      implements IElementAttributes
42  {
43      /** Don't change. */
44      private static final long serialVersionUID = 7814990748035017441L;
45  
46      /** Can this item be flushed to disk */
47      private boolean IS_SPOOL = true;
48  
49      /** Is this item laterally distributable */
50      private boolean IS_LATERAL = true;
51  
52      /** Can this item be sent to the remote cache */
53      private boolean IS_REMOTE = true;
54  
55      /**
56       * You can turn off expiration by setting this to true. This causes the cache to bypass both max
57       * life and idle time expiration.
58       */
59      private boolean IS_ETERNAL = true;
60  
61      /** Max life seconds */
62      private long maxLife = -1;
63  
64      /**
65       * The maximum time an entry can be idle. Setting this to -1 causes the idle time check to be
66       * ignored.
67       */
68      private long maxIdleTime = -1;
69  
70      /** The byte size of the field. Must be manually set. */
71      private int size;
72  
73      /** The creation time. This is used to enforce the max life. */
74      private long createTime;
75  
76      /** The last access time. This is used to enforce the max idel time. */
77      private long lastAccessTime;
78  
79      /**
80       * The list of Event handlers to use. This is transient, since the event handlers cannot usually
81       * be serialized. This means that you cannot attach a post serialization event to an item.
82       * <p>
83       * TODO we need to check that when an item is passed to a non-local cache that if the local
84       * cache had a copy with event handlers, that those handlers are used.
85       */
86      private transient ArrayList<IElementEventHandler> eventHandlers;
87  
88      private long timeFactor = 1000;
89  
90      /**
91       * Constructor for the IElementAttributes object
92       */
93      public ElementAttributes()
94      {
95          this.createTime = System.currentTimeMillis();
96          this.lastAccessTime = this.createTime;
97      }
98  
99      /**
100      * Constructor for the IElementAttributes object
101      * <p>
102      * @param attr
103      */
104     protected ElementAttributes( final ElementAttributes attr )
105     {
106         IS_ETERNAL = attr.IS_ETERNAL;
107 
108         // waterfall onto disk, for pure disk set memory to 0
109         IS_SPOOL = attr.IS_SPOOL;
110 
111         // lateral
112         IS_LATERAL = attr.IS_LATERAL;
113 
114         // central rmi store
115         IS_REMOTE = attr.IS_REMOTE;
116 
117         maxLife = attr.maxLife;
118         // time-to-live
119         maxIdleTime = attr.maxIdleTime;
120         size = attr.size;
121     }
122 
123     /**
124      * Sets the maxLife attribute of the IAttributes object.
125      * <p>
126      * @param mls The new MaxLifeSeconds value
127      */
128     @Override
129     public void setMaxLife(final long mls)
130     {
131         this.maxLife = mls;
132     }
133 
134     /**
135      * Sets the maxLife attribute of the IAttributes object. How many seconds it can live after
136      * creation.
137      * <p>
138      * If this is exceeded the element will not be returned, instead it will be removed. It will be
139      * removed on retrieval, or removed actively if the memory shrinker is turned on.
140      * @return The MaxLifeSeconds value
141      */
142     @Override
143     public long getMaxLife()
144     {
145         return this.maxLife;
146     }
147 
148     /**
149      * Sets the idleTime attribute of the IAttributes object. This is the maximum time the item can
150      * be idle in the cache, that is not accessed.
151      * <p>
152      * If this is exceeded the element will not be returned, instead it will be removed. It will be
153      * removed on retrieval, or removed actively if the memory shrinker is turned on.
154      * @param idle The new idleTime value
155      */
156     @Override
157     public void setIdleTime( final long idle )
158     {
159         this.maxIdleTime = idle;
160     }
161 
162     /**
163      * Size in bytes. This is not used except in the admin pages. It will be 0 by default
164      * and is only updated when the element is serialized.
165      * <p>
166      * @param size The new size value
167      */
168     @Override
169     public void setSize( final int size )
170     {
171         this.size = size;
172     }
173 
174     /**
175      * Gets the size attribute of the IAttributes object
176      * <p>
177      * @return The size value
178      */
179     @Override
180     public int getSize()
181     {
182         return size;
183     }
184 
185     /**
186      * Gets the createTime attribute of the IAttributes object.
187      * <p>
188      * This should be the current time in milliseconds returned by the sysutem call when the element
189      * is put in the cache.
190      * <p>
191      * Putting an item in the cache overrides any existing items.
192      * @return The createTime value
193      */
194     @Override
195     public long getCreateTime()
196     {
197         return createTime;
198     }
199 
200     /**
201      * Sets the createTime attribute of the IElementAttributes object
202      */
203     public void setCreateTime()
204     {
205         createTime = System.currentTimeMillis();
206     }
207 
208     /**
209      * Gets the idleTime attribute of the IAttributes object.
210      * <p>
211      * @return The idleTime value
212      */
213     @Override
214     public long getIdleTime()
215     {
216         return this.maxIdleTime;
217     }
218 
219     /**
220      * Gets the time left to live of the IAttributes object.
221      * <p>
222      * This is the (max life + create time) - current time.
223      * @return The TimeToLiveSeconds value
224      */
225     @Override
226     public long getTimeToLiveSeconds()
227     {
228         final long now = System.currentTimeMillis();
229         final long timeFactorForMilliseconds = getTimeFactorForMilliseconds();
230         return ( this.getCreateTime() + this.getMaxLife() * timeFactorForMilliseconds - now ) / 1000;
231     }
232 
233     /**
234      * Gets the LastAccess attribute of the IAttributes object.
235      * <p>
236      * @return The LastAccess value.
237      */
238     @Override
239     public long getLastAccessTime()
240     {
241         return this.lastAccessTime;
242     }
243 
244     /**
245      * Sets the LastAccessTime as now of the IElementAttributes object
246      */
247     @Override
248     public void setLastAccessTimeNow()
249     {
250         this.lastAccessTime = System.currentTimeMillis();
251     }
252 
253     /**
254      * only for use from test code
255      */
256     public void setLastAccessTime(final long time)
257     {
258         this.lastAccessTime = time;
259     }
260 
261     /**
262      * Can this item be spooled to disk
263      * <p>
264      * By default this is true.
265      * @return The spoolable value
266      */
267     @Override
268     public boolean getIsSpool()
269     {
270         return this.IS_SPOOL;
271     }
272 
273     /**
274      * Sets the isSpool attribute of the IElementAttributes object
275      * <p>
276      * By default this is true.
277      * @param val The new isSpool value
278      */
279     @Override
280     public void setIsSpool( final boolean val )
281     {
282         this.IS_SPOOL = val;
283     }
284 
285     /**
286      * Is this item laterally distributable. Can it be sent to auxiliaries of type lateral.
287      * <p>
288      * By default this is true.
289      * @return The isLateral value
290      */
291     @Override
292     public boolean getIsLateral()
293     {
294         return this.IS_LATERAL;
295     }
296 
297     /**
298      * Sets the isLateral attribute of the IElementAttributes object
299      * <p>
300      * By default this is true.
301      * @param val The new isLateral value
302      */
303     @Override
304     public void setIsLateral( final boolean val )
305     {
306         this.IS_LATERAL = val;
307     }
308 
309     /**
310      * Can this item be sent to the remote cache
311      * @return true if the item can be sent to a remote auxiliary
312      */
313     @Override
314     public boolean getIsRemote()
315     {
316         return this.IS_REMOTE;
317     }
318 
319     /**
320      * Sets the isRemote attribute of the ElementAttributes object
321      * @param val The new isRemote value
322      */
323     @Override
324     public void setIsRemote( final boolean val )
325     {
326         this.IS_REMOTE = val;
327     }
328 
329     /**
330      * You can turn off expiration by setting this to true. The max life value will be ignored.
331      * <p>
332      * @return true if the item cannot expire.
333      */
334     @Override
335     public boolean getIsEternal()
336     {
337         return this.IS_ETERNAL;
338     }
339 
340     /**
341      * Sets the isEternal attribute of the ElementAttributes object. True means that the item should
342      * never expire. If can still be removed if it is the least recently used, and you are using the
343      * LRUMemory cache. it just will not be filtered for expiration by the cache hub.
344      * <p>
345      * @param val The new isEternal value
346      */
347     @Override
348     public void setIsEternal( final boolean val )
349     {
350         this.IS_ETERNAL = val;
351     }
352 
353     /**
354      * Adds a ElementEventHandler. Handler's can be registered for multiple events. A registered
355      * handler will be called at every recognized event.
356      * <p>
357      * The alternative would be to register handlers for each event. Or maybe The handler interface
358      * should have a method to return whether it cares about certain events.
359      * <p>
360      * @param eventHandler The ElementEventHandler to be added to the list.
361      */
362     @Override
363     public void addElementEventHandler( final IElementEventHandler eventHandler )
364     {
365         // lazy here, no concurrency problems expected
366         if ( this.eventHandlers == null )
367         {
368             this.eventHandlers = new ArrayList<>();
369         }
370         this.eventHandlers.add( eventHandler );
371     }
372 
373     /**
374      * Sets the eventHandlers of the IElementAttributes object.
375      * <p>
376      * This add the references to the local list. Subsequent changes in the caller's list will not
377      * be reflected.
378      * <p>
379      * @param eventHandlers List of IElementEventHandler objects
380      */
381     @Override
382     public void addElementEventHandlers( final List<IElementEventHandler> eventHandlers )
383     {
384         if ( eventHandlers == null )
385         {
386             return;
387         }
388 
389         for (final IElementEventHandler handler : eventHandlers)
390         {
391             addElementEventHandler(handler);
392         }
393     }
394 
395     @Override
396     public long getTimeFactorForMilliseconds()
397     {
398         return timeFactor;
399     }
400 
401     @Override
402     public void setTimeFactorForMilliseconds(final long factor)
403     {
404         this.timeFactor = factor;
405     }
406 
407     /**
408      * Gets the elementEventHandlers. Returns null if none exist. Makes checking easy.
409      * <p>
410      * @return The elementEventHandlers List of IElementEventHandler objects
411      */
412     @Override
413     public ArrayList<IElementEventHandler> getElementEventHandlers()
414     {
415         return this.eventHandlers;
416     }
417 
418     /**
419      * For logging and debugging the element IElementAttributes.
420      * <p>
421      * @return String info about the values.
422      */
423     @Override
424     public String toString()
425     {
426         final StringBuilder dump = new StringBuilder();
427 
428         dump.append( "[ IS_LATERAL = " ).append( IS_LATERAL );
429         dump.append( ", IS_SPOOL = " ).append( IS_SPOOL );
430         dump.append( ", IS_REMOTE = " ).append( IS_REMOTE );
431         dump.append( ", IS_ETERNAL = " ).append( IS_ETERNAL );
432         dump.append( ", MaxLifeSeconds = " ).append( this.getMaxLife() );
433         dump.append( ", IdleTime = " ).append( this.getIdleTime() );
434         dump.append( ", CreateTime = " ).append( this.getCreateTime() );
435         dump.append( ", LastAccessTime = " ).append( this.getLastAccessTime() );
436         dump.append( ", getTimeToLiveSeconds() = " ).append( String.valueOf( getTimeToLiveSeconds() ) );
437         dump.append( ", createTime = " ).append( String.valueOf( createTime ) ).append( " ]" );
438 
439         return dump.toString();
440     }
441 
442     /**
443      * @see Object#clone()
444      */
445     @Override
446     public IElementAttributes clone()
447     {
448         try
449         {
450         	final ElementAttributes c = (ElementAttributes) super.clone();
451         	c.setCreateTime();
452             return c;
453         }
454         catch (final CloneNotSupportedException e)
455         {
456             throw new RuntimeException("Clone not supported. This should never happen.", e);
457         }
458     }
459 }