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 }