package org.apache.sandesha2.storage.inmemory;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import org.apache.axis2.context.AbstractContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.sandesha2.SandeshaException;
import org.apache.sandesha2.i18n.SandeshaMessageHelper;
import org.apache.sandesha2.i18n.SandeshaMessageKeys;
import org.apache.sandesha2.storage.SandeshaStorageException;
import org.apache.sandesha2.storage.beans.RMBean;
abstract class InMemoryBeanMgr {
private static final Log log = LogFactory.getLog(InMemoryBeanMgr.class);
private Hashtable table;
protected InMemoryStorageManager mgr;
protected InMemoryBeanMgr(InMemoryStorageManager mgr, AbstractContext context, String key) {
this.mgr = mgr;
Object obj = context.getProperty(key);
if (obj != null) {
table = (Hashtable) obj;
} else {
table = new Hashtable();
context.setProperty(key, table);
}
}
protected boolean insert(Object key, RMBean bean) throws SandeshaStorageException {
mgr.enlistBean(bean);
synchronized (table) {
table.put(key, bean);
}
return true;
}
protected boolean delete(Object key) throws SandeshaStorageException {
RMBean bean = null;
synchronized (table) {
bean = (RMBean) table.get(key);
}
if(bean != null) {
mgr.enlistBean(bean);
synchronized (table) {
bean = (RMBean) table.remove(key);
}
}
return bean != null;
}
protected RMBean retrieve(Object key) throws SandeshaStorageException {
RMBean bean = null;
synchronized (table) {
bean = (RMBean) table.get(key);
}
if(bean != null) {
mgr.enlistBean(bean);
synchronized (table) {
bean = (RMBean) table.get(key);
}
}
return bean;
}
protected boolean update(Object key, RMBean bean) throws SandeshaStorageException {
mgr.enlistBean(bean);
RMBean oldBean = null;
synchronized (table) {
oldBean = (RMBean) table.get(key);
table.put(key, bean);
}
if(oldBean == null) return false;
mgr.enlistBean(oldBean);
return true;
}
protected List find(RMBean matchInfo) throws SandeshaStorageException {
ArrayList beans = new ArrayList();
synchronized (table) {
if(matchInfo == null) {
beans.addAll(table.values());
} else {
Iterator i = table.values().iterator();
while(i.hasNext()) {
RMBean candidate = (RMBean)i.next();
if(candidate.match(matchInfo)) {
beans.add(candidate);
}
}
}
}
// Now we have a point-in-time view of the beans, lock them all
Iterator i = beans.iterator();
while(i.hasNext()) mgr.enlistBean((RMBean) i.next());
// Finally remove any beans that are no longer in the table
synchronized (table) {
i = beans.iterator();
while(i.hasNext()) {
RMBean bean = (RMBean) i.next();
if(!table.containsValue(bean)) {
i.remove();
}
}
}
return beans;
}
protected RMBean findUnique (RMBean matchInfo) throws SandeshaException {
RMBean result = null;
synchronized (table) {
Iterator i = table.values().iterator();
while(i.hasNext()) {
RMBean candidate = (RMBean)i.next();
if(candidate.match(matchInfo)) {
if(result == null) {
result = candidate;
} else {
String message = SandeshaMessageHelper.getMessage(
SandeshaMessageKeys.nonUniqueResult,
result.toString(),
candidate.toString());
log.error(message);
throw new SandeshaException (message);
}
}
}
}
// Now we have a point-in-time view of the bean, lock it, and double
// check that it is still in the table
if(result != null) {
mgr.enlistBean(result);
synchronized (table) {
if(!table.containsValue(result)) result = null;
}
}
return result;
}
/**
* This try to find conflicting entries in the current table with the passed findBean list.
* Each find bean represents a key.
*
* @param findBeanList
* @throws SandeshaStorageException
*/
protected void checkKeys (List findBeanList) throws SandeshaStorageException {
for (Iterator iter = findBeanList.iterator(); iter.hasNext();) {
RMBean rmBean = (RMBean) iter.next();
List conflicts = find(rmBean);
if (conflicts.size()>0) {
//we only report the first conflict here.
throw new SandeshaStorageException ("Key conflict occured with the bean " + conflicts.get(0));
}
}
}
}