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 }