1 package org.apache.commons.jcs.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.jcs.engine.behavior.IElementAttributes;
26 import org.apache.commons.jcs.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 = 0;
72
73 /** The creation time. This is used to enforce the max life. */
74 private long createTime = 0;
75
76 /** The last access time. This is used to enforce the max idel time. */
77 private long lastAccessTime = 0;
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( 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(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( 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 -1 by default.
164 * <p>
165 * @param size The new size value
166 */
167 @Override
168 public void setSize( int size )
169 {
170 this.size = size;
171 }
172
173 /**
174 * Gets the size attribute of the IAttributes object
175 * <p>
176 * @return The size value
177 */
178 @Override
179 public int getSize()
180 {
181 return size;
182 }
183
184 /**
185 * Gets the createTime attribute of the IAttributes object.
186 * <p>
187 * This should be the current time in milliseconds returned by the sysutem call when the element
188 * is put in the cache.
189 * <p>
190 * Putting an item in the cache overrides any existing items.
191 * @return The createTime value
192 */
193 @Override
194 public long getCreateTime()
195 {
196 return createTime;
197 }
198
199 /**
200 * Sets the createTime attribute of the IElementAttributes object
201 */
202 public void setCreateTime()
203 {
204 createTime = System.currentTimeMillis();
205 }
206
207 /**
208 * Gets the idleTime attribute of the IAttributes object.
209 * <p>
210 * @return The idleTime value
211 */
212 @Override
213 public long getIdleTime()
214 {
215 return this.maxIdleTime;
216 }
217
218 /**
219 * Gets the time left to live of the IAttributes object.
220 * <p>
221 * This is the (max life + create time) - current time.
222 * @return The TimeToLiveSeconds value
223 */
224 @Override
225 public long getTimeToLiveSeconds()
226 {
227 final long now = System.currentTimeMillis();
228 final long timeFactorForMilliseconds = getTimeFactorForMilliseconds();
229 return ( this.getCreateTime() + this.getMaxLife() * timeFactorForMilliseconds - now ) / 1000;
230 }
231
232 /**
233 * Gets the LastAccess attribute of the IAttributes object.
234 * <p>
235 * @return The LastAccess value.
236 */
237 @Override
238 public long getLastAccessTime()
239 {
240 return this.lastAccessTime;
241 }
242
243 /**
244 * Sets the LastAccessTime as now of the IElementAttributes object
245 */
246 @Override
247 public void setLastAccessTimeNow()
248 {
249 this.lastAccessTime = System.currentTimeMillis();
250 }
251
252 /**
253 * only for use from test code
254 */
255 public void setLastAccessTime(long time)
256 {
257 this.lastAccessTime = time;
258 }
259
260 /**
261 * Can this item be spooled to disk
262 * <p>
263 * By default this is true.
264 * @return The spoolable value
265 */
266 @Override
267 public boolean getIsSpool()
268 {
269 return this.IS_SPOOL;
270 }
271
272 /**
273 * Sets the isSpool attribute of the IElementAttributes object
274 * <p>
275 * By default this is true.
276 * @param val The new isSpool value
277 */
278 @Override
279 public void setIsSpool( boolean val )
280 {
281 this.IS_SPOOL = val;
282 }
283
284 /**
285 * Is this item laterally distributable. Can it be sent to auxiliaries of type lateral.
286 * <p>
287 * By default this is true.
288 * @return The isLateral value
289 */
290 @Override
291 public boolean getIsLateral()
292 {
293 return this.IS_LATERAL;
294 }
295
296 /**
297 * Sets the isLateral attribute of the IElementAttributes object
298 * <p>
299 * By default this is true.
300 * @param val The new isLateral value
301 */
302 @Override
303 public void setIsLateral( boolean val )
304 {
305 this.IS_LATERAL = val;
306 }
307
308 /**
309 * Can this item be sent to the remote cache
310 * @return true if the item can be sent to a remote auxiliary
311 */
312 @Override
313 public boolean getIsRemote()
314 {
315 return this.IS_REMOTE;
316 }
317
318 /**
319 * Sets the isRemote attribute of the ElementAttributes object
320 * @param val The new isRemote value
321 */
322 @Override
323 public void setIsRemote( boolean val )
324 {
325 this.IS_REMOTE = val;
326 }
327
328 /**
329 * You can turn off expiration by setting this to true. The max life value will be ignored.
330 * <p>
331 * @return true if the item cannot expire.
332 */
333 @Override
334 public boolean getIsEternal()
335 {
336 return this.IS_ETERNAL;
337 }
338
339 /**
340 * Sets the isEternal attribute of the ElementAttributes object. True means that the item should
341 * never expire. If can still be removed if it is the least recently used, and you are using the
342 * LRUMemory cache. it just will not be filtered for expiration by the cache hub.
343 * <p>
344 * @param val The new isEternal value
345 */
346 @Override
347 public void setIsEternal( boolean val )
348 {
349 this.IS_ETERNAL = val;
350 }
351
352 /**
353 * Adds a ElementEventHandler. Handler's can be registered for multiple events. A registered
354 * handler will be called at every recognized event.
355 * <p>
356 * The alternative would be to register handlers for each event. Or maybe The handler interface
357 * should have a method to return whether it cares about certain events.
358 * <p>
359 * @param eventHandler The ElementEventHandler to be added to the list.
360 */
361 @Override
362 public void addElementEventHandler( IElementEventHandler eventHandler )
363 {
364 // lazy here, no concurrency problems expected
365 if ( this.eventHandlers == null )
366 {
367 this.eventHandlers = new ArrayList<IElementEventHandler>();
368 }
369 this.eventHandlers.add( eventHandler );
370 }
371
372 /**
373 * Sets the eventHandlers of the IElementAttributes object.
374 * <p>
375 * This add the references to the local list. Subsequent changes in the caller's list will not
376 * be reflected.
377 * <p>
378 * @param eventHandlers List of IElementEventHandler objects
379 */
380 @Override
381 public void addElementEventHandlers( List<IElementEventHandler> eventHandlers )
382 {
383 if ( eventHandlers == null )
384 {
385 return;
386 }
387
388 for (IElementEventHandler handler : eventHandlers)
389 {
390 addElementEventHandler(handler);
391 }
392 }
393
394 @Override
395 public long getTimeFactorForMilliseconds()
396 {
397 return timeFactor;
398 }
399
400 @Override
401 public void setTimeFactorForMilliseconds(long factor)
402 {
403 this.timeFactor = factor;
404 }
405
406 /**
407 * Gets the elementEventHandlers. Returns null if none exist. Makes checking easy.
408 * <p>
409 * @return The elementEventHandlers List of IElementEventHandler objects
410 */
411 @Override
412 public ArrayList<IElementEventHandler> getElementEventHandlers()
413 {
414 return this.eventHandlers;
415 }
416
417 /**
418 * For logging and debugging the element IElementAttributes.
419 * <p>
420 * @return String info about the values.
421 */
422 @Override
423 public String toString()
424 {
425 StringBuilder dump = new StringBuilder();
426
427 dump.append( "[ IS_LATERAL = " ).append( IS_LATERAL );
428 dump.append( ", IS_SPOOL = " ).append( IS_SPOOL );
429 dump.append( ", IS_REMOTE = " ).append( IS_REMOTE );
430 dump.append( ", IS_ETERNAL = " ).append( IS_ETERNAL );
431 dump.append( ", MaxLifeSeconds = " ).append( this.getMaxLife() );
432 dump.append( ", IdleTime = " ).append( this.getIdleTime() );
433 dump.append( ", CreateTime = " ).append( this.getCreateTime() );
434 dump.append( ", LastAccessTime = " ).append( this.getLastAccessTime() );
435 dump.append( ", getTimeToLiveSeconds() = " ).append( String.valueOf( getTimeToLiveSeconds() ) );
436 dump.append( ", createTime = " ).append( String.valueOf( createTime ) ).append( " ]" );
437
438 return dump.toString();
439 }
440
441 /**
442 * @see java.lang.Object#clone()
443 */
444 @Override
445 public IElementAttributes clone()
446 {
447 try
448 {
449 ElementAttributes c = (ElementAttributes) super.clone();
450 c.setCreateTime();
451 return c;
452 }
453 catch (CloneNotSupportedException e)
454 {
455 throw new RuntimeException("Clone not supported. This should never happen.", e);
456 }
457 }
458 }