package org.apache.commons.jcs.engine; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ import java.util.ArrayList; import java.util.List; import org.apache.commons.jcs.engine.behavior.IElementAttributes; import org.apache.commons.jcs.engine.control.event.behavior.IElementEventHandler; /** * This it the element attribute descriptor class. Each element in the cache has an ElementAttribute * object associated with it. An ElementAttributes object can be associated with an element in 3 * ways: * <ol> * <li>When the item is put into the cache, you can associate an element attributes object.</li> * <li>If not attributes object is include when the element is put into the cache, then the default * attributes for the region will be used.</li> * <li>The element attributes can be reset. This effectively results in a retrieval followed by a * put. Hence, this is the same as 1.</li> * </ol> */ public class ElementAttributes implements IElementAttributes { /** Don't change. */ private static final long serialVersionUID = 7814990748035017441L; /** Can this item be flushed to disk */ private boolean IS_SPOOL = true; /** Is this item laterally distributable */ private boolean IS_LATERAL = true; /** Can this item be sent to the remote cache */ private boolean IS_REMOTE = true; /** * You can turn off expiration by setting this to true. This causes the cache to bypass both max * life and idle time expiration. */ private boolean IS_ETERNAL = true; /** Max life seconds */ private long maxLife = -1; /** * The maximum time an entry can be idle. Setting this to -1 causes the idle time check to be * ignored. */ private long maxIdleTime = -1; /** The byte size of the field. Must be manually set. */ private int size = 0; /** The creation time. This is used to enforce the max life. */ private long createTime = 0; /** The last access time. This is used to enforce the max idel time. */ private long lastAccessTime = 0; /** * The list of Event handlers to use. This is transient, since the event handlers cannot usually * be serialized. This means that you cannot attach a post serialization event to an item. * <p> * TODO we need to check that when an item is passed to a non-local cache that if the local * cache had a copy with event handlers, that those handlers are used. */ private transient ArrayList<IElementEventHandler> eventHandlers; private long timeFactor = 1000; /** * Constructor for the IElementAttributes object */ public ElementAttributes() { this.createTime = System.currentTimeMillis(); this.lastAccessTime = this.createTime; } /** * Constructor for the IElementAttributes object * <p> * @param attr */ protected ElementAttributes( ElementAttributes attr ) { IS_ETERNAL = attr.IS_ETERNAL; // waterfall onto disk, for pure disk set memory to 0 IS_SPOOL = attr.IS_SPOOL; // lateral IS_LATERAL = attr.IS_LATERAL; // central rmi store IS_REMOTE = attr.IS_REMOTE; maxLife = attr.maxLife; // time-to-live maxIdleTime = attr.maxIdleTime; size = attr.size; } /** * Sets the maxLife attribute of the IAttributes object. * <p> * @param mls The new MaxLifeSeconds value */ @Override public void setMaxLife(long mls) { this.maxLife = mls; } /** * Sets the maxLife attribute of the IAttributes object. How many seconds it can live after * creation. * <p> * If this is exceeded the element will not be returned, instead it will be removed. It will be * removed on retrieval, or removed actively if the memory shrinker is turned on. * @return The MaxLifeSeconds value */ @Override public long getMaxLife() { return this.maxLife; } /** * Sets the idleTime attribute of the IAttributes object. This is the maximum time the item can * be idle in the cache, that is not accessed. * <p> * If this is exceeded the element will not be returned, instead it will be removed. It will be * removed on retrieval, or removed actively if the memory shrinker is turned on. * @param idle The new idleTime value */ @Override public void setIdleTime( long idle ) { this.maxIdleTime = idle; } /** * Size in bytes. This is not used except in the admin pages. It will be -1 by default. * <p> * @param size The new size value */ @Override public void setSize( int size ) { this.size = size; } /** * Gets the size attribute of the IAttributes object * <p> * @return The size value */ @Override public int getSize() { return size; } /** * Gets the createTime attribute of the IAttributes object. * <p> * This should be the current time in milliseconds returned by the sysutem call when the element * is put in the cache. * <p> * Putting an item in the cache overrides any existing items. * @return The createTime value */ @Override public long getCreateTime() { return createTime; } /** * Sets the createTime attribute of the IElementAttributes object */ public void setCreateTime() { createTime = System.currentTimeMillis(); } /** * Gets the idleTime attribute of the IAttributes object. * <p> * @return The idleTime value */ @Override public long getIdleTime() { return this.maxIdleTime; } /** * Gets the time left to live of the IAttributes object. * <p> * This is the (max life + create time) - current time. * @return The TimeToLiveSeconds value */ @Override public long getTimeToLiveSeconds() { final long now = System.currentTimeMillis(); final long timeFactorForMilliseconds = getTimeFactorForMilliseconds(); return ( this.getCreateTime() + this.getMaxLife() * timeFactorForMilliseconds - now ) / 1000; } /** * Gets the LastAccess attribute of the IAttributes object. * <p> * @return The LastAccess value. */ @Override public long getLastAccessTime() { return this.lastAccessTime; } /** * Sets the LastAccessTime as now of the IElementAttributes object */ @Override public void setLastAccessTimeNow() { this.lastAccessTime = System.currentTimeMillis(); } /** * only for use from test code */ public void setLastAccessTime(long time) { this.lastAccessTime = time; } /** * Can this item be spooled to disk * <p> * By default this is true. * @return The spoolable value */ @Override public boolean getIsSpool() { return this.IS_SPOOL; } /** * Sets the isSpool attribute of the IElementAttributes object * <p> * By default this is true. * @param val The new isSpool value */ @Override public void setIsSpool( boolean val ) { this.IS_SPOOL = val; } /** * Is this item laterally distributable. Can it be sent to auxiliaries of type lateral. * <p> * By default this is true. * @return The isLateral value */ @Override public boolean getIsLateral() { return this.IS_LATERAL; } /** * Sets the isLateral attribute of the IElementAttributes object * <p> * By default this is true. * @param val The new isLateral value */ @Override public void setIsLateral( boolean val ) { this.IS_LATERAL = val; } /** * Can this item be sent to the remote cache * @return true if the item can be sent to a remote auxiliary */ @Override public boolean getIsRemote() { return this.IS_REMOTE; } /** * Sets the isRemote attribute of the ElementAttributes object * @param val The new isRemote value */ @Override public void setIsRemote( boolean val ) { this.IS_REMOTE = val; } /** * You can turn off expiration by setting this to true. The max life value will be ignored. * <p> * @return true if the item cannot expire. */ @Override public boolean getIsEternal() { return this.IS_ETERNAL; } /** * Sets the isEternal attribute of the ElementAttributes object. True means that the item should * never expire. If can still be removed if it is the least recently used, and you are using the * LRUMemory cache. it just will not be filtered for expiration by the cache hub. * <p> * @param val The new isEternal value */ @Override public void setIsEternal( boolean val ) { this.IS_ETERNAL = val; } /** * Adds a ElementEventHandler. Handler's can be registered for multiple events. A registered * handler will be called at every recognized event. * <p> * The alternative would be to register handlers for each event. Or maybe The handler interface * should have a method to return whether it cares about certain events. * <p> * @param eventHandler The ElementEventHandler to be added to the list. */ @Override public void addElementEventHandler( IElementEventHandler eventHandler ) { // lazy here, no concurrency problems expected if ( this.eventHandlers == null ) { this.eventHandlers = new ArrayList<IElementEventHandler>(); } this.eventHandlers.add( eventHandler ); } /** * Sets the eventHandlers of the IElementAttributes object. * <p> * This add the references to the local list. Subsequent changes in the caller's list will not * be reflected. * <p> * @param eventHandlers List of IElementEventHandler objects */ @Override public void addElementEventHandlers( List<IElementEventHandler> eventHandlers ) { if ( eventHandlers == null ) { return; } for (IElementEventHandler handler : eventHandlers) { addElementEventHandler(handler); } } @Override public long getTimeFactorForMilliseconds() { return timeFactor; } @Override public void setTimeFactorForMilliseconds(long factor) { this.timeFactor = factor; } /** * Gets the elementEventHandlers. Returns null if none exist. Makes checking easy. * <p> * @return The elementEventHandlers List of IElementEventHandler objects */ @Override public ArrayList<IElementEventHandler> getElementEventHandlers() { return this.eventHandlers; } /** * For logging and debugging the element IElementAttributes. * <p> * @return String info about the values. */ @Override public String toString() { StringBuilder dump = new StringBuilder(); dump.append( "[ IS_LATERAL = " ).append( IS_LATERAL ); dump.append( ", IS_SPOOL = " ).append( IS_SPOOL ); dump.append( ", IS_REMOTE = " ).append( IS_REMOTE ); dump.append( ", IS_ETERNAL = " ).append( IS_ETERNAL ); dump.append( ", MaxLifeSeconds = " ).append( this.getMaxLife() ); dump.append( ", IdleTime = " ).append( this.getIdleTime() ); dump.append( ", CreateTime = " ).append( this.getCreateTime() ); dump.append( ", LastAccessTime = " ).append( this.getLastAccessTime() ); dump.append( ", getTimeToLiveSeconds() = " ).append( String.valueOf( getTimeToLiveSeconds() ) ); dump.append( ", createTime = " ).append( String.valueOf( createTime ) ).append( " ]" ); return dump.toString(); } /** * @see java.lang.Object#clone() */ @Override public IElementAttributes clone() { try { ElementAttributes c = (ElementAttributes) super.clone(); c.setCreateTime(); return c; } catch (CloneNotSupportedException e) { throw new RuntimeException("Clone not supported. This should never happen.", e); } } }