com.ibatis.sqlmap.engine.cache.CacheModel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jbatis Show documentation
Show all versions of jbatis Show documentation
The jBATIS persistence framework will help you to significantly reduce the amount of Java code that you normally need to access a relational database. iBATIS simply maps JavaBeans to SQL statements using a very simple XML descriptor.
The newest version!
/*
* Copyright 2004 Clinton Begin
*
* Licensed 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.
*/
package com.ibatis.sqlmap.engine.cache;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.ibatis.client.Cache;
import com.ibatis.common.ArraySet;
import com.ibatis.common.logging.ILog;
import com.ibatis.common.logging.ILogFactory;
/**
* Wrapper for Caches.
*/
public class CacheModel implements Cache, FlushListener {
private static final ILog log = ILogFactory.getLog(CacheModel.class);
private static final int MAX_OBJECT_LOG_SIZE = 32;
private long requests = 0, hits = 0, flushs = 0;
private String id;
private int maxCacheSize = -1;
private long lastFlush;
private long flushInterval;
private long flushIntervalSeconds;
private Set flushTriggerRoots;
private Set flushTriggerStatements;
private Set flushTriggerCaches;
private Set> flushTriggerEntityClasses;
private CacheController controller;
private String resource;
private Set flushListeners = new ArraySet();
/**
* Default constructor
*/
public CacheModel() {
this.flushInterval = -1;
this.flushIntervalSeconds = -1;
this.lastFlush = System.currentTimeMillis();
this.flushTriggerRoots = new ArraySet();
this.flushTriggerStatements = new ArraySet();
this.flushTriggerCaches = new ArraySet();
this.flushTriggerEntityClasses = new ArraySet>();
}
/**
* Getter for the cache model's id
*
* @return the id
*/
@Override
public String getId() {
return id;
}
/**
* Setter for the cache model's id
*
* @param id
* - the new id
*/
public void setId(String id) {
this.id = id;
}
/**
* Getter for resource property
*
* @return the value of the resource property
*/
public String getResource() {
return resource;
}
/**
* Setter for resource property
*
* @param resource
* - the new value
*/
public void setResource(String resource) {
this.resource = resource;
}
public int getMaxCacheSize() {
return maxCacheSize;
}
public void setMaxCacheSize(int maxCacheSize) {
this.maxCacheSize = maxCacheSize;
}
/**
* Sets up the controller for the cache model
*/
public void setCacheController(CacheController controller) {
this.controller = controller;
}
public CacheController getCacheController() {
return this.controller;
}
/**
* Getter for flushInterval property
*
* @return The flushInterval (in milliseconds)
*/
public long getFlushInterval() {
return flushInterval;
}
/**
* Getter for flushInterval property
*
* @return The flushInterval (in milliseconds)
*/
public long getFlushIntervalSeconds() {
return flushIntervalSeconds;
}
/**
* Setter for flushInterval property
*
* @param flushInterval
* The new flushInterval (in milliseconds)
*/
public void setFlushInterval(long flushInterval) {
this.flushInterval = flushInterval;
this.flushIntervalSeconds = flushInterval / 1000;
}
public void addFlushTriggerRoot(String name) {
flushTriggerRoots.add(name);
}
/**
* Adds a flushTriggerStatment. When a flushTriggerStatment is executed, the cache is flushed (cleared).
*
* @param statementName
* The statement to add.
*/
public void addFlushTriggerStatement(String statementName) {
flushTriggerStatements.add(statementName);
}
/**
* Adds a flushTriggerCache. When a flushTriggerCache is flushed, the cache is flushed (cleared).
*
* @param cacheId
* The cache to add.
*/
public void addFlushTriggerCache(String cacheId) {
flushTriggerCaches.add(cacheId);
}
public void addFlushTriggerEntityClass(Class> clazz) {
flushTriggerEntityClasses.add(clazz);
}
public Set getFlushTriggerCacheRoots() {
return flushTriggerRoots;
}
/**
* Gets an Set containing all flushTriggerStatment objects for this cache.
*/
public Set getFlushTriggerStatementNames() {
return flushTriggerStatements;
}
/**
* Gets an Set containing all flushTriggerCache objects for this cache.
*/
public Set getFlushTriggerCacheNames() {
return flushTriggerCaches;
}
public Set> getFlushTriggerEntityClasses() {
return flushTriggerEntityClasses;
}
/**
* Returns statistical information about the cache.
*
* @return the number of cache hits divided by the total requests
*/
public double getHitRatio() {
return (double) hits / (double) requests;
}
/**
* Configures the cache
*
* @param props
*/
public void configure(Properties props) {
controller.setProperties(this, props);
}
/**
* Clears the cache
*/
@Override
public void flush() {
doFlush(System.currentTimeMillis());
}
synchronized void doFlush(long timestamp) {
controller.flush(this);
lastFlush = timestamp;
flushs++;
if (log.isTraceEnabled()) {
log("flushed", false, null);
}
for (FlushListener fl : flushListeners) {
fl.onFlush(id, timestamp);
}
}
@Override
public void onFlush(String id, long timestamp) {
if (lastFlush < timestamp) {
doFlush(timestamp);
}
}
/**
* Get an object out of the cache. A side effect of this method is that is may clear the cache if it has not been
* cleared in the flushInterval.
*
* @param key
* The key of the object to be returned
* @return The cached object (or null)
*/
@SuppressWarnings("unchecked")
@Override
public T getObject(Object key) {
T value = null;
synchronized (this) {
long curr = System.currentTimeMillis();
if (flushInterval > 0 && curr - lastFlush > flushInterval) {
controller.flush(this);
lastFlush = curr;
flushs++;
}
value = (T) controller.getObject(this, key);
requests++;
if (value != null) {
hits++;
}
if (log.isTraceEnabled()) {
if (value != null) {
log("retrieved #" + key, false, null);
} else {
log("cache miss #" + key, false, null);
}
}
}
return value;
}
/**
* Add an object to the cache
*
* @param key
* The key of the object to be cached
* @param value
* The object to be cached
*/
@Override
public void putObject(Object key, Object value) {
if (null == value)
value = NULL_OBJECT;
synchronized (this) {
controller.putObject(this, key, value);
if (log.isTraceEnabled()) {
log("stored object #" + key, true, value);
}
}
}
/**
* Get the maximum size of an object in the log output.
*
* @return Maximum size of a logged object in the output
*/
protected int getMaxObjectLogSize() {
return MAX_OBJECT_LOG_SIZE;
}
/**
* Log a cache action. Since this method is pretty heavy weight, it's best to enclose it with a log.isDebugEnabled()
* when called.
*
* @param action
* String to output
* @param addValue
* Add the value being cached to the log
* @param cacheValue
* The value being logged
*/
protected void log(String action, boolean addValue, Object cacheValue) {
StringBuilder output = new StringBuilder("Cache '");
output.append(getId());
output.append("': ");
output.append(action);
if (addValue) {
String cacheObjectStr = (cacheValue == null ? "null" : toStr(cacheValue));
output.append(" '");
if (cacheObjectStr.length() < getMaxObjectLogSize()) {
output.append(cacheObjectStr.toString());
} else {
output.append(cacheObjectStr.substring(0, getMaxObjectLogSize()));
output.append("...");
}
output.append("'");
}
log.trace(output.toString());
}
String toStr(Object o) {
if (o instanceof List) {
List> list = (List>) o;
if (list.isEmpty()) {
return "[]";
} else {
return "[ " + list.size() + " ) " + list.get(0)+ "]";
}
} else if (o instanceof Map) {
Map, ?> map = (Map, ?>) o;
if (map.isEmpty()) {
return "{}";
} else {
return "{ " + map.size() + " ) " + map.entrySet().iterator().next() + "}";
}
}
return o.toString();
}
public void setControllerProperties(Properties cacheProps) {
controller.setProperties(this, cacheProps);
}
@Override
public long getRequests() {
return requests;
}
@Override
public long getHits() {
return hits;
}
@Override
public long getFlushs() {
return flushs;
}
@Override
public long getPeriodMillis() {
return System.currentTimeMillis() - lastFlush;
}
// ## sunsong
@Override
public String toString() {
return "CacheModel [" + id + ", " + hits + " / " + requests + ", " + getPeriodMillis() / 1000L + "]";
}
public synchronized void addFlushListener(FlushListener listener) {
flushListeners.add(listener);
}
public synchronized void removeFlushListener(FlushListener listener) {
flushListeners.remove(listener);
}
}