0001: package com.jofti.cache.adapter;
0002:
0003: import java.util.ArrayList;
0004: import java.util.Collection;
0005: import java.util.HashMap;
0006: import java.util.HashSet;
0007: import java.util.Iterator;
0008: import java.util.List;
0009: import java.util.Map;
0010: import java.util.Properties;
0011: import java.util.Set;
0012:
0013: import javax.transaction.HeuristicMixedException;
0014: import javax.transaction.HeuristicRollbackException;
0015: import javax.transaction.RollbackException;
0016: import javax.transaction.Status;
0017: import javax.transaction.Synchronization;
0018: import javax.transaction.SystemException;
0019: import javax.transaction.Transaction;
0020:
0021: import net.sf.ehcache.CacheException;
0022:
0023: import org.apache.commons.logging.Log;
0024: import org.apache.commons.logging.LogFactory;
0025: import org.jboss.cache.Fqn;
0026: import org.jboss.cache.GlobalTransaction;
0027: import org.jboss.cache.Node;
0028: import org.jboss.cache.PropertyConfigurator;
0029: import org.jboss.cache.TreeCache;
0030: import org.jboss.cache.TreeCacheListener;
0031: import org.jboss.cache.lock.IsolationLevel;
0032: import org.jgroups.View;
0033:
0034: import com.jofti.api.IndexCache;
0035: import com.jofti.api.IndexQuery;
0036: import com.jofti.api.NameSpaceKey;
0037: import com.jofti.cache.CacheAdapter;
0038: import com.jofti.cache.BaseAdaptor;
0039: import com.jofti.cache.NameSpacedCacheAdapter;
0040: import com.jofti.core.INameSpaceAware;
0041: import com.jofti.core.IParsedQuery;
0042: import com.jofti.core.ITransactionAware;
0043: import com.jofti.core.InternalIndex;
0044: import com.jofti.core.QueryId;
0045: import com.jofti.core.QueryType;
0046: import com.jofti.core.TransactionLevel;
0047: import com.jofti.exception.JoftiException;
0048: import com.jofti.introspect.ClassIntrospector;
0049: import com.jofti.parser.ClassFieldMethods;
0050: import com.jofti.tree.NameSpacedTreeIndex;
0051: import com.jofti.util.CompositeComparator;
0052: import com.jofti.util.ObjectProcedureAdapter;
0053: import com.jofti.util.OpenHashMap;
0054: import com.jofti.util.ValueTreeMap;
0055: import com.tangosol.dev.compiler.Manager;
0056:
0057: import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
0058:
0059: /**
0060: *
0061: *
0062: * The adapter is responsible for interaction between the index and JBossCache.
0063: * <p>
0064: *
0065: * The main difference between JBossCache and the other caches is its use of
0066: * transactions. The adapter is responsible for maintaining the transactional
0067: * semantics of the index.
0068: * <p>
0069: *
0070: * @author Steve Woodcock (steve@jofti.com)<br>
0071: * @version 1.0<br>
0072: */
0073: public class JBossCacheAdapter extends BaseAdaptor implements
0074: CacheAdapter, NameSpacedCacheAdapter, ITransactionAware {
0075:
0076: TreeCache cache = null;
0077:
0078: javax.transaction.TransactionManager txMgr = null;
0079:
0080: private static Log log = LogFactory.getLog(JBossCacheAdapter.class);
0081:
0082: private String name;
0083:
0084: TransactionLevel level = null;
0085:
0086: private int expiryTime = 3600; // seconds
0087:
0088: private boolean requiresStarting;
0089:
0090: // used for non-existent transactions
0091: private Indexer defaultIndexer = new Indexer();
0092:
0093: private Map transactionMap = new ConcurrentHashMap();
0094:
0095: private Map xaMap = new ConcurrentHashMap();
0096:
0097: /**
0098: * @return Returns the expiryTime.
0099: */
0100: public int getExpiryTime() {
0101: return expiryTime;
0102: }
0103:
0104: /**
0105: * @param expiryTime
0106: * The expiryTime to set.
0107: */
0108: public void setExpiryTime(int expiryTime) {
0109: this .expiryTime = expiryTime;
0110: }
0111:
0112: public JBossCacheAdapter() {
0113: requiresStarting = true;
0114: }
0115:
0116: public JBossCacheAdapter(Object cache) {
0117: this .cache = (TreeCache) cache;
0118: }
0119:
0120: public void setCacheImpl(Object cache) {
0121: this .cache = (TreeCache) cache;
0122: try {
0123: initCache(this .cache);
0124: } catch (Exception e) {
0125: throw new RuntimeException(e);
0126: }
0127:
0128: }
0129:
0130: /* (non-Javadoc)
0131: * @see com.jofti.api.IndexCache#get(java.lang.Object)
0132: */
0133: public Object get(Object key) {
0134:
0135: // test the key
0136: if (key != null) {
0137: if (key instanceof NameSpaceKey) {
0138: NameSpaceKey temp = null;
0139: try {
0140: temp = (NameSpaceKey) key;
0141: } catch (ClassCastException cce) {
0142: log.warn("key value must be a NameSpaceKey ", cce);
0143: return null;
0144: }
0145: // do the get on the tree
0146:
0147: try {
0148: synchronized (getCacheLock(key)) {
0149: Object val = cache.get((Fqn) temp
0150: .getNameSpace(), temp.getKey());
0151: return val;
0152: }
0153: } catch (org.jboss.cache.CacheException ce) {
0154: log
0155: .warn(
0156: "Unable to retrieve value from cache ",
0157: ce);
0158: }
0159:
0160: } else {
0161: log
0162: .warn("Unable to retrieve value from cache Key type must be "
0163: + NameSpaceKey.class);
0164: }
0165:
0166: }
0167: // we return null here if we got an exception because it is consistent
0168: // with most other cache implementations
0169: return null;
0170: }
0171:
0172: private Object getFromCache(Object key) throws JoftiException {
0173:
0174: // test the key
0175: if (key instanceof NameSpaceKey) {
0176: NameSpaceKey temp = null;
0177: try {
0178: temp = (NameSpaceKey) key;
0179: } catch (ClassCastException cce) {
0180: log.warn("key value must be a NameSpaceKey ", cce);
0181: return null;
0182: }
0183: // do the get on the tree
0184:
0185: try {
0186: Object val = cache.get((Fqn) temp.getNameSpace(), temp
0187: .getKey());
0188: return val;
0189: } catch (Throwable ce) {
0190: throw new JoftiException(ce);
0191: }
0192:
0193: } else {
0194: log
0195: .warn("Unable to retrieve value from cache Key type must be "
0196: + NameSpaceKey.class);
0197: }
0198:
0199: // we return null here if we got an exception because it is consistent
0200: // with most other cache implementations
0201: return null;
0202: }
0203:
0204: /* (non-Javadoc)
0205: * @see com.jofti.api.IndexCache#put(java.lang.Object, java.lang.Object)
0206: */
0207: public void put(Object key, Object value) throws JoftiException {
0208:
0209: NameSpaceKey temp = null;
0210:
0211: try {
0212: temp = (NameSpaceKey) key;
0213: } catch (ClassCastException cce) {
0214: throw new JoftiException(
0215: "key value must be a NameSpaceKey ", cce);
0216: }
0217:
0218: // get the transaction for the thread
0219: Transaction tx = getTransaction();
0220:
0221: // get the indexer to be used for the transaction
0222: JBossIndexer indexer = getIndexer(tx);
0223:
0224: try {
0225: acquireUpdateLock();
0226: } catch (Exception e) {
0227: log.error("unable to acquire update lock ", e);
0228: throw new JoftiException(e);
0229: }
0230: try {
0231: synchronized (getCacheLock(key)) {
0232: // first see if it already exists
0233: Object result = cache.get((Fqn) temp.getNameSpace(),
0234: temp.getKey());
0235: if (log.isDebugEnabled()) {
0236: log.debug("inserting " + temp.getNameSpace() + " "
0237: + temp.getKey());
0238: }
0239: cache.put((Fqn) temp.getNameSpace(), temp.getKey(),
0240: value);
0241:
0242: if (result != null) {
0243: indexer.update(temp, result, value);
0244: } else {
0245: indexer.add(temp, value);
0246: }
0247: }
0248: registerIndexer(indexer, tx);
0249:
0250: } catch (org.jboss.cache.CacheException ce) {
0251: throw new JoftiException(ce);
0252: } catch (Exception e) {
0253: throw new JoftiException(e);
0254: } finally {
0255: releaseUpdateLock();
0256: }
0257:
0258: }
0259:
0260: // get a transaction from the transaction manager
0261: private Transaction getTransaction() throws JoftiException {
0262: Transaction tx = null;
0263: try {
0264: if (txMgr != null) {
0265: tx = txMgr.getTransaction();
0266: }
0267: } catch (SystemException se) {
0268: throw new JoftiException(se);
0269: }
0270: return tx;
0271: }
0272:
0273: /**
0274: * Removes the element which matches the namespace.
0275: * <p>
0276: * If no element matches, nothing is removed and no Exception is thrown.
0277: *
0278: * @param namespace the namespace to remove
0279: * @throws CacheException
0280: */
0281: public void removeNameSpace(Object nameSpace) throws JoftiException {
0282: try {
0283:
0284: acquireUpdateLock();
0285: try {
0286: synchronized (getCacheLock(nameSpace)) {
0287: // first see if it already exists
0288: Node result = null;
0289: Fqn temp = null;
0290: if (nameSpace instanceof String) {
0291: temp = Fqn.fromString((String) nameSpace);
0292:
0293: } else if (nameSpace instanceof Fqn) {
0294: temp = (Fqn) nameSpace;
0295: } else {
0296: throw new JoftiException(
0297: "namespace object must be a String or an Fqn object "
0298: + nameSpace.getClass());
0299: }
0300: // we have the node here
0301: result = cache.get(temp);
0302:
0303: // lets loop through and get a full list of child nodes that
0304: // are going to be removed
0305: if (result != null) {
0306:
0307: Map childMap = result.getChildren();
0308: List nodesToRemove = parseChildren(childMap,
0309: new ArrayList(), temp.toString() + "/");
0310: nodesToRemove.add(temp.toString());
0311: if (log.isDebugEnabled()) {
0312: log.debug(nodesToRemove);
0313: }
0314:
0315: for (Iterator it = nodesToRemove.iterator(); it
0316: .hasNext();) {
0317: cache.remove((String) it.next());
0318: }
0319:
0320: }
0321: }
0322: } catch (org.jboss.cache.CacheException ce) {
0323: throw new JoftiException(ce);
0324: } catch (Exception e) {
0325: throw new JoftiException(e);
0326: } finally {
0327: releaseUpdateLock();
0328: }
0329: } catch (Exception e) {
0330: log.error("unable to acquire update lock", e);
0331: }
0332: }
0333:
0334: private List parseChildren(Map childMap, List tempList,
0335: String prefix) {
0336: if (childMap != null) {
0337: for (Iterator it = childMap.entrySet().iterator(); it
0338: .hasNext();) {
0339: Map.Entry entry = (Map.Entry) it.next();
0340: Map map = ((Node) entry.getValue()).getChildren();
0341: parseChildren(map, tempList, prefix + "/"
0342: + entry.getKey() + "/");
0343: tempList.add(prefix + entry.getKey());
0344: }
0345: }
0346: return tempList;
0347: }
0348:
0349: /* (non-Javadoc)
0350: * @see com.jofti.api.IndexCache#remove(java.lang.Object)
0351: */
0352: public void remove(Object key) throws JoftiException {
0353:
0354: NameSpaceKey temp = null;
0355:
0356: try {
0357: temp = (NameSpaceKey) key;
0358: } catch (ClassCastException cce) {
0359: throw new JoftiException(
0360: "key value must be a JBossKeyWrapper ", cce);
0361: }
0362: Transaction tx = getTransaction();
0363: JBossIndexer indexer = getIndexer(tx);
0364:
0365: try {
0366: acquireUpdateLock();
0367: try {
0368:
0369: synchronized (getCacheLock(key)) {
0370:
0371: Object result = cache.remove((Fqn) temp
0372: .getNameSpace(), temp.getKey());
0373:
0374: if (result != null) {
0375: indexer.remove(temp, result);
0376: } else {
0377: if (index.contains(temp)) {
0378: indexer.remove(temp);
0379: }
0380: }
0381: }
0382: registerIndexer(indexer, tx);
0383: } catch (org.jboss.cache.CacheException ce) {
0384: throw new JoftiException(ce);
0385: } catch (Exception e) {
0386: throw new JoftiException(e);
0387: } finally {
0388: releaseUpdateLock();
0389: }
0390: } catch (Exception e) {
0391: log.error("unable to acquire update lock", e);
0392: }
0393:
0394: }
0395:
0396: /**
0397: * Remove all elements in the cache, but leave the cache in a useable state.
0398: *
0399: * @throws CacheException
0400: */
0401: public void removeAll() throws JoftiException {
0402: try {
0403: cache.remove("/");
0404:
0405: index.removeAll();
0406:
0407: } catch (Exception ce) {
0408: throw new JoftiException(ce);
0409: }
0410:
0411: }
0412:
0413: private synchronized JBossIndexer getIndexer(Transaction tx)
0414: throws JoftiException {
0415:
0416: JBossIndexer indexer = null;
0417:
0418: if (tx == null || level == TransactionLevel.NONE
0419: || level == TransactionLevel.READ_UNCOMMITTED) {
0420: // we have no transaction
0421: indexer = defaultIndexer;
0422: } else {
0423: // get an existing indexer if we have one or create a new one
0424:
0425: indexer = (JBossIndexer) transactionMap.get(tx);
0426:
0427: if (indexer == null) {
0428: indexer = new TransactionIndexer(index
0429: .getIntrospector());
0430: ((TransactionIndexer) indexer).init();
0431: transactionMap.put(tx, indexer);
0432: }
0433: }
0434: return indexer;
0435: }
0436:
0437: private synchronized void registerIndexer(JBossIndexer indexer,
0438: Transaction tx) throws SystemException, RollbackException,
0439: JoftiException {
0440: if (indexer instanceof TransactionIndexer
0441: && (!xaMap.containsKey(indexer))) {
0442: try {
0443: tx.registerSynchronization((Synchronization) indexer);
0444: transactionMap.put(tx, indexer);
0445: xaMap.put(indexer, tx);
0446: if (log.isDebugEnabled()) {
0447: log.debug("registering transaction " + tx
0448: + " in cache " + cache.getLocalAddress());
0449: }
0450: } catch (Exception e) {
0451: throw new JoftiException(e);
0452: }
0453: }
0454:
0455: }
0456:
0457: /* (non-Javadoc)
0458: * @see com.jofti.cache.LifeCycleAdapter#init(java.util.Properties)
0459: */
0460: public synchronized void init(Properties properties)
0461: throws JoftiException {
0462: try {
0463: String cacheConfigFile = null;
0464: if (properties != null) {
0465: String key = null;
0466: for (Iterator it = properties.keySet().iterator(); it
0467: .hasNext();) {
0468: key = (String) it.next();
0469: if (MUTABLE_VALUES.equalsIgnoreCase(key)) {
0470: checkMutable = Boolean.valueOf(
0471: properties.getProperty(key))
0472: .booleanValue();
0473: if (log.isInfoEnabled()) {
0474: log.info("Mutability checking is set to "
0475: + checkMutable);
0476: }
0477: }
0478: if ("file".equalsIgnoreCase(key)) {
0479: cacheConfigFile = properties.getProperty(key);
0480: }
0481: }
0482: }
0483: if (cache == null) {
0484: cache = new TreeCache();
0485: }
0486: if (requiresStarting) {
0487: PropertyConfigurator config = new PropertyConfigurator();
0488: if (cacheConfigFile == null) {
0489: throw new JoftiException(
0490: "Config file cannot be null in config - check you have set the config file property correctly");
0491: } else {
0492: config.configure(cache, cacheConfigFile);
0493: }
0494: }
0495:
0496: initCache(cache);
0497:
0498: } catch (Exception e) {
0499: throw new JoftiException(e);
0500: }
0501:
0502: }
0503:
0504: private void initCache(TreeCache cache) throws JoftiException {
0505: cache.addTreeCacheListener(new EventListener());
0506: txMgr = cache.getTransactionManager();
0507: level = getTransactionLevel();
0508: }
0509:
0510: /* (non-Javadoc)
0511: * @see com.jofti.cache.LifeCycleAdapter#destroy()
0512: */
0513: public void destroy() throws JoftiException {
0514: cache.destroy();
0515: }
0516:
0517: public String getName() {
0518: return name;
0519: }
0520:
0521: public void setName(String name) {
0522: this .name = name;
0523: }
0524:
0525: public String toString() {
0526: return "JBossCache(" + getName() + ')';
0527: }
0528:
0529: /*
0530: * (non-Javadoc)
0531: *
0532: * @see com.jofti.api.IndexCache#getCacheImpl()
0533: */
0534: public Object getCacheImpl() {
0535: return cache;
0536: }
0537:
0538: /*
0539: * (non-Javadoc)
0540: *
0541: * @see com.jofti.cache.CacheAdapter#setInternalIndex(com.jofti.core.InternalIndex)
0542: */
0543: public void setInternalIndex(InternalIndex index) {
0544: if (!(index instanceof NameSpacedTreeIndex)) {
0545: throw new RuntimeException(
0546: "JBossCache tree index must be set to "
0547: + NameSpacedTreeIndex.class);
0548: }
0549: this .index = index;
0550:
0551: }
0552:
0553: class TransactionIndexer implements Synchronization, JBossIndexer {
0554:
0555: protected ChangeRecorder recorder = null;
0556:
0557: TransactionIndexer(ClassIntrospector parser) {
0558: recorder = new ChangeRecorder(parser);
0559: }
0560:
0561: /*
0562: * (non-Javadoc)
0563: *
0564: * @see javax.transaction.Synchronization#beforeCompletion()
0565: */
0566:
0567: public void init() throws JoftiException {
0568: recorder.init(new Properties(), index.getClass().getName());
0569: }
0570:
0571: public void beforeCompletion() {
0572: // we do not care
0573:
0574: }
0575:
0576: /*
0577: * (non-Javadoc)
0578: *
0579: * @see javax.transaction.Synchronization#afterCompletion(int)
0580: */
0581: public void afterCompletion(int status) {
0582: // first remove
0583: // first remove ourselves
0584: Object obj = xaMap.get(this );
0585: xaMap.remove(this );
0586: transactionMap.remove(obj);
0587: switch (status) {
0588: case Status.STATUS_COMMITTED:
0589: try {
0590:
0591: acquireUpdateLock();
0592: try {
0593: applyAll();
0594: } catch (Throwable e) {
0595: log.error("failed committing changes to index",
0596: e);
0597: } finally {
0598: releaseUpdateLock();
0599: }
0600: } catch (JoftiException e) {
0601: log.error("unable to acquire update lock", e);
0602: }
0603: break;
0604:
0605: case Status.STATUS_MARKED_ROLLBACK: // this one is probably not
0606: // needed
0607: case Status.STATUS_ROLLEDBACK:
0608: default:
0609: ;
0610: }
0611:
0612: }
0613:
0614: public void update(NameSpaceKey keyWrapper, Object oldValue,
0615: Object newValue) throws JoftiException {
0616:
0617: recorder.update(keyWrapper, oldValue, newValue, index
0618: .getIntrospector());
0619:
0620: }
0621:
0622: public void add(NameSpaceKey keyWrapper, Object value)
0623: throws JoftiException {
0624: recorder.add(keyWrapper, value, index.getIntrospector());
0625: }
0626:
0627: public void remove(NameSpaceKey keyWrapper, Object value)
0628: throws JoftiException {
0629: recorder.remove(keyWrapper, value, index.getIntrospector());
0630: }
0631:
0632: public void remove(NameSpaceKey keyWrapper)
0633: throws JoftiException {
0634: recorder.remove(keyWrapper, index.getIntrospector());
0635:
0636: }
0637:
0638: private void applyAll() throws JoftiException {
0639: // first do removes
0640: if (log.isDebugEnabled()) {
0641: log
0642: .debug("Applying all index updates after transaction commit on cache "
0643: + cache.getLocalAddress());
0644: }
0645: Map removes = recorder.getRemovedMap();
0646: for (Iterator it = removes.entrySet().iterator(); it
0647: .hasNext();) {
0648: Map.Entry entry = (Map.Entry) it.next();
0649: Object key = entry.getKey();
0650: List values = (List) entry.getValue();
0651:
0652: synchronized (getCacheLock(key)) {
0653: for (Iterator valIt = values.iterator(); valIt
0654: .hasNext();) {
0655: Object value = valIt.next();
0656:
0657: index.removeByKey((Comparable) key);
0658: if (log.isDebugEnabled()) {
0659: log.info("index removed " + key
0660: + " value " + value);
0661: }
0662: }
0663: }
0664: }
0665: // now remove key only
0666: for (Iterator it = recorder.getRemovedKeys().iterator(); it
0667: .hasNext();) {
0668: Object key = it.next();
0669:
0670: synchronized (getCacheLock(key)) {
0671:
0672: index.removeByKey((Comparable) key);
0673: if (log.isDebugEnabled()) {
0674: log.debug("index removed entries for " + key);
0675: }
0676: }
0677: }
0678:
0679: // now remove the updates
0680: Map updates = recorder.getUpdatedMap();
0681: for (Iterator it = updates.entrySet().iterator(); it
0682: .hasNext();) {
0683: Map.Entry entry = (Map.Entry) it.next();
0684: Object key = entry.getKey();
0685: List values = (List) entry.getValue();
0686: synchronized (getCacheLock(key)) {
0687: for (Iterator valIt = values.iterator(); valIt
0688: .hasNext();) {
0689: Object value = valIt.next();
0690: index.removeByKey((Comparable) key);
0691: if (log.isDebugEnabled()) {
0692: log.debug("index removed for update " + key
0693: + " value " + value);
0694: }
0695: }
0696: }
0697: }
0698:
0699: // now add all the adds
0700: Collection col = recorder.getAllTreeValues();
0701: for (Iterator it = col.iterator(); it.hasNext();) {
0702: NameSpaceKey wrapper = (NameSpaceKey) it.next();
0703:
0704: synchronized (getCacheLock(wrapper)) {
0705: Object val = null;
0706:
0707: try {
0708: val = cache._get((Fqn) wrapper.getNameSpace(),
0709: wrapper.getKey(), false);
0710: // val =
0711: // cache.peek(wrapper.fqn).getData().get(wrapper.key);
0712: } catch (Exception e) {
0713: log.warn("Unable to insert entry " + wrapper
0714: + " into index ", e);
0715: }
0716: if (val != null) {
0717: if (log.isDebugEnabled()) {
0718: log.debug("index removed for update "
0719: + wrapper + " value " + val);
0720: }
0721: index.insert(wrapper, val);
0722: } else {
0723: log
0724: .warn("Entry lookup for "
0725: + wrapper
0726: + " in transaction tree is null in cache ");
0727: }
0728: }
0729: }
0730: if (log.isDebugEnabled()) {
0731: log
0732: .debug("Finished Applying all index updates after transaction commit "
0733: + cache.getLocalAddress());
0734: }
0735: }
0736:
0737: /*
0738: * (non-Javadoc)
0739: *
0740: * @see com.jofti.cache.adapter.JBossIndexer#contains(com.jofti.cache.adapter.JBossKeyWrapper)
0741: */
0742: public boolean contains(NameSpaceKey keyWrapper)
0743: throws JoftiException {
0744:
0745: return index.contains(keyWrapper);
0746: }
0747:
0748: /*
0749: * (non-Javadoc)
0750: *
0751: * @see com.jofti.cache.adapter.JBossIndexer#query(com.jofti.api.IndexQuery,
0752: * com.jofti.api.CacheAccessor)
0753: */
0754: public Map query(IndexQuery query, IndexCache parent)
0755: throws JoftiException {
0756:
0757: // repeatable read - always return previous results plus any new
0758: // ones
0759:
0760: // serializable - block if any are blocked
0761: acquireQueryLock();
0762:
0763: OpenHashMap localResults = null;
0764: final ChangeRecorder tempRecorder = recorder;
0765: OpenHashMap processedQueryMap = null;
0766:
0767: Object nameSpace = ((INameSpaceAware) query).getNameSpace();
0768:
0769: if (((QueryId) query).getQueryType() != QueryType.PARSED_QUERY) {
0770: query = index.getParserManager().parseQuery(query);
0771:
0772: }
0773:
0774: try {
0775: // query the main index
0776: final OpenHashMap queryMap = (OpenHashMap) index
0777: .query(query);
0778:
0779: // remove all stuff in our transaction
0780:
0781: queryMap.forEachKey(new ObjectProcedureAdapter() {
0782: public boolean apply(Object key) {
0783:
0784: if (tempRecorder.getRemovedKeys().contains(key)
0785: || tempRecorder.getRemovedMap()
0786: .containsKey(key)
0787: || tempRecorder.getUpdatedMap()
0788: .containsKey(key)) {
0789: queryMap.removeNoReHash(key);
0790: }
0791: return true;
0792: }
0793: });
0794: processedQueryMap = queryMap;
0795:
0796: // query the local index
0797: localResults = (OpenHashMap) recorder.query(query);
0798: } finally {
0799: releaseQueryLock();
0800: }
0801: // now let us merge the results
0802: Map res = mergeOpenMaps(parent, processedQueryMap,
0803: localResults);
0804:
0805: return getCacheValues(parent, res, nameSpace,
0806: (IParsedQuery) query, index.getIntrospector());
0807:
0808: }
0809:
0810: protected Map mergeOpenMaps(IndexCache parent,
0811: OpenHashMap map1, OpenHashMap map2) {
0812: OpenHashMap smaller = null;
0813: OpenHashMap larger = null;
0814: if (map1.size() < map2.size()) {
0815: smaller = map1;
0816: larger = map2;
0817: } else {
0818: smaller = map2;
0819: larger = map1;
0820: }
0821:
0822: larger.ensureCapacity(larger.size() + smaller.size() * 2);
0823:
0824: final OpenHashMap tempLarger = larger;
0825: smaller.forEachPair(new ObjectProcedureAdapter() {
0826: public boolean apply(Object key, Object value) {
0827: if (!tempLarger.containsKey(key)) {
0828: tempLarger.put(key, value);
0829: }
0830: return false;
0831: }
0832: });
0833: return larger;
0834: }
0835:
0836: }
0837:
0838: /**
0839: * @param parent
0840: * @param map2
0841: * @param previousResults
0842: * @param resultMap
0843: * @throws JoftiException
0844: */
0845:
0846: class Indexer implements JBossIndexer {
0847:
0848: /*
0849: * (non-Javadoc)
0850: *
0851: * @see com.jofti.cache.JBossIndexer#update(com.jofti.cache.JBossKeyWrapper,
0852: * java.lang.Object, java.lang.Object)
0853: */
0854: public void update(NameSpaceKey keyWrapper, Object oldValue,
0855: Object newValue) throws JoftiException {
0856:
0857: index.removeByKey(keyWrapper);
0858:
0859: index.insert(keyWrapper, newValue);
0860:
0861: }
0862:
0863: /*
0864: * (non-Javadoc)
0865: *
0866: * @see com.jofti.cache.JBossIndexer#add(com.jofti.cache.JBossKeyWrapper,
0867: * java.lang.Object)
0868: */
0869: public void add(NameSpaceKey keyWrapper, Object value)
0870: throws JoftiException {
0871: index.insert(keyWrapper, value);
0872:
0873: }
0874:
0875: /*
0876: * (non-Javadoc)
0877: *
0878: * @see com.jofti.cache.JBossIndexer#remove(com.jofti.cache.JBossKeyWrapper,
0879: * java.lang.Object)
0880: */
0881: public void remove(NameSpaceKey keyWrapper, Object value)
0882: throws JoftiException {
0883: index.removeByKey(keyWrapper);
0884:
0885: }
0886:
0887: /*
0888: * (non-Javadoc)
0889: *
0890: * @see com.jofti.cache.JBossIndexer#remove(com.jofti.cache.JBossKeyWrapper)
0891: */
0892: public void remove(NameSpaceKey keyWrapper)
0893: throws JoftiException {
0894: index.removeByKey(keyWrapper);
0895:
0896: }
0897:
0898: /*
0899: * (non-Javadoc)
0900: *
0901: * @see com.jofti.cache.adapter.JBossIndexer#contains(com.jofti.cache.adapter.JBossKeyWrapper)
0902: */
0903: public boolean contains(NameSpaceKey keyWrapper)
0904: throws JoftiException {
0905:
0906: return index.contains(keyWrapper);
0907: }
0908:
0909: /*
0910: * (non-Javadoc)
0911: *
0912: * @see com.jofti.cache.adapter.JBossIndexer#query(com.jofti.api.IndexQuery)
0913: */
0914: public Map query(IndexQuery query, IndexCache parent)
0915: throws JoftiException {
0916:
0917: Map temp = null;
0918:
0919: Object nameSpace = ((INameSpaceAware) query).getNameSpace();
0920:
0921: if (((QueryId) query).getQueryType() != QueryType.PARSED_QUERY) {
0922: query = index.getParserManager().parseQuery(query);
0923:
0924: }
0925:
0926: acquireQueryLock();
0927:
0928: try {
0929: temp = index.query(query);
0930: } finally {
0931: releaseQueryLock();
0932: }
0933:
0934: return getCacheValues(parent, temp, nameSpace,
0935: (IParsedQuery) query, index.getIntrospector());
0936: }
0937:
0938: }
0939:
0940: private boolean isValidForNameSpace(Object nameSpace,
0941: Object keyNameSpace) {
0942:
0943: return (nameSpace.equals(keyNameSpace) || ((Fqn) keyNameSpace)
0944: .isChildOf((Fqn) nameSpace));
0945: }
0946:
0947: /*
0948: * (non-Javadoc)
0949: *
0950: * @see com.jofti.cache.CacheAdapter#start()
0951: */
0952: public void start() throws JoftiException {
0953:
0954: try {
0955: if (requiresStarting) {
0956: if (cache == null) {
0957: log
0958: .warn("JBossCache instance is NULL in adaptor - ensure Cache has been configured correctly");
0959: }
0960: cache.start();
0961: }
0962: txMgr = cache.getTransactionManager();
0963: loadInitialValues(cache);
0964: } catch (Exception e) {
0965:
0966: throw new JoftiException(e);
0967: }
0968: }
0969:
0970: /*
0971: * (non-Javadoc)
0972: *
0973: * @see com.jofti.api.NameSpacedIndex#put(java.lang.Object,
0974: * java.lang.Object, java.lang.Object)
0975: */
0976: public void put(Object nameSpace, Object key, Object value)
0977: throws JoftiException {
0978: if (nameSpace instanceof Fqn) {
0979: put(new NameSpaceKeyWrapper((Fqn) nameSpace, key), value);
0980: } else if (nameSpace instanceof String) {
0981: put(new NameSpaceKeyWrapper(Fqn
0982: .fromString((String) nameSpace), key), value);
0983: } else {
0984: throw new JoftiException("Unable to insert value " + value
0985: + " namespace must be either a " + Fqn.class
0986: + "or a String ");
0987: }
0988: }
0989:
0990: /*
0991: * (non-Javadoc)
0992: *
0993: * @see com.jofti.api.NameSpacedIndex#get(java.lang.Object,
0994: * java.lang.Object)
0995: */
0996: public Object get(Object nameSpace, Object key) {
0997:
0998: if (nameSpace instanceof Fqn) {
0999: return get(new NameSpaceKeyWrapper((Fqn) nameSpace, key));
1000: } else if (nameSpace instanceof String) {
1001: return get(new NameSpaceKeyWrapper(Fqn
1002: .fromString((String) nameSpace), key));
1003: } else {
1004: return null;
1005: }
1006: }
1007:
1008: /* (non-Javadoc)
1009: * @see com.jofti.api.NameSpacedIndex#remove(java.lang.Object, java.lang.Object)
1010: */
1011: public void remove(Object nameSpace, Object key)
1012: throws JoftiException {
1013: if (nameSpace instanceof Fqn) {
1014: remove(new NameSpaceKeyWrapper((Fqn) nameSpace, key));
1015: } else if (nameSpace instanceof String) {
1016: remove(new NameSpaceKeyWrapper(Fqn
1017: .fromString((String) nameSpace), key));
1018: }
1019:
1020: }
1021:
1022: /*
1023: * (non-Javadoc)
1024: *
1025: * @see com.jofti.api.IndexCache#query(com.jofti.api.IndexQuery)
1026: */
1027: public Map query(IndexQuery query) throws JoftiException {
1028:
1029: IndexQuery origQuery = query;
1030: if (((QueryId) query).getQueryType() == QueryType.UNPARSED_QUERY) {
1031: query = (IndexQuery) index.getParserManager().parseQuery(
1032: query);
1033: }
1034: // decorate the query with the fqn
1035: if (query instanceof INameSpaceAware) {
1036: INameSpaceAware orig = (INameSpaceAware) query;
1037: // reset the namespace object to make sure it is an fqn
1038: Fqn tempFqn = null;
1039:
1040: Object tempNameSpace = orig.getNameSpace();
1041: if (tempNameSpace == null) {
1042: throw new JoftiException(
1043: "NameSpace is required for JBossCache query: "
1044: + origQuery);
1045: } else if (orig.getNameSpace() instanceof String) {
1046: tempFqn = Fqn.fromString((String) orig.getNameSpace());
1047: orig.setNameSpace(tempFqn);
1048: } else if (!(orig.getNameSpace() instanceof Fqn)) {
1049: throw new JoftiException(
1050: "name space object must be a string or Fqn for JBoss IndexCache");
1051: }
1052:
1053: }
1054:
1055: Transaction tx = getTransaction();
1056:
1057: JBossIndexer indexer = getIndexer(tx);
1058:
1059: try {
1060: registerIndexer(indexer, tx);
1061: } catch (Exception e) {
1062: throw new JoftiException(e);
1063: }
1064:
1065: return indexer.query(query, this );
1066:
1067: }
1068:
1069: public IndexQuery addQuery(String name, IndexQuery query)
1070: throws JoftiException {
1071:
1072: return index.getParserManager().addQuery(name, query);
1073: }
1074:
1075: /* (non-Javadoc)
1076: * @see com.jofti.api.Index#getQuery(java.lang.String)
1077: */
1078: public IndexQuery getQuery(String name) {
1079:
1080: return index.getParserManager().getQuery(name);
1081: }
1082:
1083: protected Map getCacheValues(final IndexCache cache, Map col,
1084: final Object nameSpace, final IParsedQuery query,
1085: ClassIntrospector introspector) throws JoftiException {
1086: final Map returnClasses = query.getResultFieldsMap();
1087: final CompositeComparator comp = query.getOrderingComparator();
1088: final int maxResults = query.getMaxResults();
1089: final int startEntry = query.getFirstResult();
1090:
1091: Map interim = null;
1092: if (comp == null || comp.getSize() == 0) {
1093: interim = new HashMap(col.size() + 2, 1.00f);
1094: } else {
1095: interim = new ValueTreeMap(comp);
1096: }
1097:
1098: // return map
1099: final Map temp = interim;
1100:
1101: final Object[] errors = new Object[1];
1102: // Map returnClasses = parsedQuery.getResultFieldsMap();
1103: OpenHashMap originalMap = (OpenHashMap) col;
1104:
1105: boolean noError = originalMap
1106: .forEachPair(new ObjectProcedureAdapter() {
1107: public boolean apply(Object key, Object value) {
1108:
1109: if (value == null
1110: || returnClasses.containsKey(value)) {
1111:
1112: Object result = null;
1113:
1114: //get value if valid namespace or subnamespace for query namespace
1115: if (isValidForNameSpace(nameSpace,
1116: ((NameSpaceKey) key).getNameSpace())) {
1117: try {
1118: result = getCacheValue(cache, key,
1119: nameSpace);
1120:
1121: } catch (JoftiException e) {
1122: log.warn(
1123: "unable to get cache value for key "
1124: + key
1125: + " in nameSpace "
1126: + nameSpace, e);
1127: errors[0] = new JoftiException(
1128: "unable to get cache value for key "
1129: + key
1130: + " in nameSpace "
1131: + nameSpace, e);
1132: return false;
1133: }
1134:
1135: if (result == null) {
1136:
1137: if (log.isWarnEnabled()) {
1138: log
1139: .warn("Index and cache have become out of date for key "
1140: + key);
1141: }
1142:
1143: return true;
1144: } else {
1145:
1146: if (checkMutable) {
1147: result = checkMutable(key,
1148: result);
1149: // mutability check failed
1150: if (result == null) {
1151: if (log.isDebugEnabled()) {
1152: log
1153: .debug("Object under key:"
1154: + key
1155: + " has changed in cache since it was indexed");
1156: }
1157: return true;
1158: }
1159: }
1160:
1161: if (returnClasses != null) {
1162: // we need to get the value from result if we are using fields
1163: ClassFieldMethods fieldSet = (ClassFieldMethods) returnClasses
1164: .get(value);
1165:
1166: Map tempMap = fieldSet != null ? fieldSet
1167: .getFieldMap()
1168: : null;
1169:
1170: if (tempMap != null
1171: && tempMap.size() > 0) {
1172: // get the fields and apply the values to them
1173: log
1174: .warn("field is set for "
1175: + value);
1176: } else {
1177: // there are no fields just return the value
1178: temp.put(key, result);
1179: }
1180: } else {
1181: temp.put(key, result);
1182: }
1183:
1184: }
1185: }
1186: }
1187: return true;
1188: }
1189: });
1190: if (noError) {
1191: // now limit result size
1192: if (maxResults > 0 || startEntry > 0) {
1193: return limitResults(temp, startEntry, maxResults);
1194: } else if (startEntry < 0 || maxResults < 0) {
1195: if (startEntry < 0) {
1196: throw new IllegalArgumentException(
1197: "startResult cannot be less than 0:"
1198: + startEntry);
1199: }
1200: if (maxResults < 0) {
1201: throw new IllegalArgumentException(
1202: "maxResults cannot be less than 0:"
1203: + maxResults);
1204: }
1205: }
1206: return temp;
1207: } else {
1208: throw (JoftiException) errors[0];
1209: }
1210:
1211: }
1212:
1213: protected Object checkMutable(Object key, Object result) {
1214: try {
1215: // first parse the object - again
1216: Map cacheObjectValues = index.getIntrospector()
1217: .getAttributeValues(result);
1218:
1219: Map indexObjectValues = index
1220: .getAttributesByKey((Comparable) key);
1221: if (cacheObjectValues.equals(indexObjectValues)) {
1222: return result;
1223: } else {
1224: if (log.isDebugEnabled()) {
1225: log
1226: .debug("Object under Key "
1227: + key
1228: + " - attributes changed without re-insert");
1229: }
1230: }
1231:
1232: } catch (JoftiException e) {
1233: log.warn("Error checking mutability", e);
1234: }
1235:
1236: return null;
1237: }
1238:
1239: private void loadInitialValues(TreeCache temp)
1240: throws JoftiException {
1241: Throwable t = null;
1242: // get a list of all the children in the tree
1243: Collection fqns = new ArrayList();
1244:
1245: Transaction tx = null;
1246:
1247: try {
1248: if (cache.getIsolationLevelClass() != IsolationLevel.NONE) {
1249: tx = getTransaction();
1250: if (tx == null) {
1251: if (cache.getTransactionManager() == null) {
1252: log
1253: .warn("No TransactionManager founf in TreeCache for isolation level "
1254: + cache.getIsolationLevel());
1255: throw new JoftiException(
1256: "You must have a transaction manager configured in JBossCache to use Isolation level "
1257: + cache.getIsolationLevel());
1258: }
1259: cache.getTransactionManager().begin();
1260: tx = getTransaction();
1261: }
1262: }
1263: Fqn start = cache.getRoot().getFqn();
1264: fqns.add(start);
1265: try {
1266: fqns = getChildrenForFqn(temp, start, fqns);
1267: } catch (org.jboss.cache.CacheException e) {
1268: throw new JoftiException(e);
1269: }
1270:
1271: // for each of thse then get the key and value out
1272: for (Iterator it = fqns.iterator(); it.hasNext();) {
1273: Fqn fqn = (Fqn) it.next();
1274: Node node = cache.get(fqn);
1275:
1276: if (node != null && node.getDataKeys() != null
1277: && node.getDataKeys().size() > 0) {
1278: Set dataKeys = node.getDataKeys();
1279: for (Iterator mapIt = dataKeys.iterator(); mapIt
1280: .hasNext();) {
1281: Object key = mapIt.next();
1282: Object value = node.get(key);
1283: index.insert(new NameSpaceKeyWrapper(fqn, key),
1284: value);
1285: }
1286: }
1287: }
1288: } catch (Exception e) {
1289: // dump the index
1290: t = e;
1291: index.removeAll();
1292: if (cache.getIsolationLevelClass() != IsolationLevel.NONE) {
1293: try {
1294: log
1295: .warn("Unable to complete index of initial values - rolling back "
1296: + e);
1297: if (tx != null) {
1298: tx.rollback();
1299: } else {
1300: log
1301: .warn("Expected to rollback Transaction but Transaction is null");
1302: }
1303: } catch (IllegalStateException e1) {
1304: throw new JoftiException(e1);
1305: } catch (SystemException e1) {
1306: throw new JoftiException(e1);
1307: } catch (Throwable t1) {
1308: throw new JoftiException(
1309: "Unable to rollback tx as is " + tx);
1310: }
1311: }
1312:
1313: } finally {
1314: if (cache.getIsolationLevelClass() != IsolationLevel.NONE) {
1315: try {
1316: if (tx != null && !isRollback(tx.getStatus())) {
1317:
1318: tx.commit();
1319: } else {
1320: log
1321: .info("Transaction not committed as marked as rolledback or null");
1322: }
1323: log.info("initial data transaction loaded");
1324: } catch (SecurityException e) {
1325:
1326: throw new JoftiException(e);
1327: } catch (RollbackException e) {
1328:
1329: throw new JoftiException(e);
1330: } catch (HeuristicMixedException e) {
1331:
1332: throw new JoftiException(e);
1333: } catch (HeuristicRollbackException e) {
1334:
1335: throw new JoftiException(e);
1336: } catch (SystemException e) {
1337:
1338: throw new JoftiException(e);
1339: }
1340: }
1341: if (t != null) {
1342: if (t instanceof JoftiException) {
1343: throw (JoftiException) t;
1344: } else {
1345: throw new JoftiException(t);
1346: }
1347: }
1348: }
1349:
1350: }
1351:
1352: private Collection getChildrenForFqn(TreeCache temp, Fqn fqn,
1353: Collection names) throws org.jboss.cache.CacheException {
1354:
1355: Set set = temp.getChildrenNames(fqn);
1356: if (set != null && !set.isEmpty()) {
1357: int size = set.size();
1358: Iterator it = set.iterator();
1359: for (int i = 0; i < size; i++) {
1360: Fqn tempFqn = Fqn.fromString((String) it.next());
1361:
1362: getChildrenForFqn(temp, tempFqn, names);
1363: names.add(tempFqn);
1364: }
1365: return names;
1366:
1367: } else {
1368: return names;
1369: }
1370:
1371: }
1372:
1373: private Object getCacheValue(IndexCache parent, Object key,
1374: Object nameSpace) throws JoftiException {
1375: Object result = null;
1376:
1377: if (key != null
1378: && isValidForNameSpace(nameSpace, ((NameSpaceKey) key)
1379: .getNameSpace())) {
1380:
1381: // will acquire readlock or will throw an exception after some time
1382: // if no readlock can be acquired
1383:
1384: result = ((JBossCacheAdapter) parent).getFromCache(key);
1385:
1386: }
1387: return result;
1388: }
1389:
1390: class EventListener implements TreeCacheListener {
1391:
1392: /*
1393: * (non-Javadoc)
1394: *
1395: * @see org.jboss.cache.TreeCacheListener#nodeCreated(org.jboss.cache.Fqn)
1396: */
1397: public void nodeCreated(Fqn arg0) {
1398: // check with loading otherwise we do not care about node
1399: // creation yet
1400:
1401: }
1402:
1403: /*
1404: * (non-Javadoc)
1405: *
1406: * @see org.jboss.cache.TreeCacheListener#nodeRemoved(org.jboss.cache.Fqn)
1407: */
1408: public void nodeRemoved(Fqn arg0) {
1409: if (log.isDebugEnabled()) {
1410: log.debug("node removed triggered for " + arg0);
1411: }
1412: try {
1413: Transaction tx = getTransaction();
1414:
1415: final JBossIndexer indexer = getIndexer(tx);
1416: registerIndexer(indexer, tx);
1417:
1418: OpenHashMap searchKeys = (OpenHashMap) index
1419: .getEntries(new NameSpaceWrapper(arg0));
1420:
1421: // this is an openHashMap
1422: searchKeys.forEachKey(new ObjectProcedureAdapter() {
1423: /* (non-Javadoc)
1424: * @see com.jofti.util.ObjectProcedureAdapter#apply(java.lang.Object)
1425: */
1426: public boolean apply(Object element) {
1427: try {
1428: indexer
1429: .remove((NameSpaceKeyWrapper) element);
1430: } catch (Exception e) {
1431: // we should log this
1432: log.warn("unable to remove key " + element);
1433: }
1434: return true;
1435: }
1436: });
1437:
1438: } catch (Exception e) {
1439: log.warn("unable to remove entries in node removal "
1440: + arg0);
1441: }
1442:
1443: }
1444:
1445: /*
1446: * (non-Javadoc)
1447: *
1448: * @see org.jboss.cache.TreeCacheListener#nodeLoaded(org.jboss.cache.Fqn)
1449: */
1450: public void nodeLoaded(Fqn arg0) {
1451: // we do not care
1452:
1453: }
1454:
1455: /*
1456: * (non-Javadoc)
1457: *
1458: * @see org.jboss.cache.TreeCacheListener#nodeEvicted(org.jboss.cache.Fqn)
1459: */
1460: public void nodeEvicted(Fqn arg0) {
1461: // we do not care
1462:
1463: }
1464:
1465: /*
1466: * (non-Javadoc)
1467: *
1468: * @see org.jboss.cache.TreeCacheListener#nodeModified(org.jboss.cache.Fqn)
1469: */
1470: public void nodeModified(Fqn arg0) {
1471:
1472: // this can be either a put or a remove - all this work because
1473: // JBOSS APIs
1474: // give no information to go on
1475: try {
1476: //see if transaction is local
1477:
1478: Transaction tx = getTransaction();
1479:
1480: GlobalTransaction gtx = cache.getTransactionTable()
1481: .get(tx);
1482:
1483: if (gtx != null
1484: && gtx.getAddress() != null
1485: && (!gtx.getAddress().equals(
1486: cache.getLocalAddress()))) {
1487: if (log.isDebugEnabled()) {
1488: log.debug("gtx " + gtx.getAddress()
1489: + " cache address "
1490: + cache.getLocalAddress());
1491: }
1492: //is remote - now find the indexed key list
1493: final List indexKeys = new ArrayList();
1494:
1495: OpenHashMap searchKeys = (OpenHashMap) index
1496: .getEntries(new NameSpaceWrapper(arg0));
1497:
1498: // this is an openHashMap
1499: searchKeys.forEachKey(new ObjectProcedureAdapter() {
1500: /* (non-Javadoc)
1501: * @see com.jofti.util.ObjectProcedureAdapter#apply(java.lang.Object)
1502: */
1503: public boolean apply(Object element) {
1504: try {
1505: NameSpaceKey entry = (NameSpaceKey) element;
1506: indexKeys.add(entry.getKey());
1507: } catch (Exception e) {
1508: // we should log this
1509: log.warn("unable to remove key "
1510: + element);
1511: }
1512: return true;
1513: }
1514: });
1515:
1516: // now update the actions
1517: JBossIndexer indexer = getIndexer(tx);
1518: registerIndexer(indexer, tx);
1519: // see if key list bigger or smaller than node set
1520:
1521: Set cacheKeys = cache._get(arg0).getDataKeys();
1522:
1523: if (indexKeys.size() == cacheKeys.size()) {
1524: // must be an update so all key/values will need
1525: // reindexing
1526: // worst cost activity
1527: if (log.isDebugEnabled()) {
1528: log.debug("Node key updated for " + arg0);
1529: }
1530: for (Iterator it = indexKeys.iterator(); it
1531: .hasNext();) {
1532: Object tempKey = it.next();
1533: if (log.isDebugEnabled()) {
1534: log.debug("Node key removing "
1535: + tempKey);
1536: }
1537:
1538: NameSpaceKey tempWrapper = new NameSpaceKeyWrapper(
1539: arg0, tempKey);
1540: indexer.remove(tempWrapper);
1541: Object temp = cache.peek(arg0, tempKey);
1542: if (log.isDebugEnabled()) {
1543: log.debug("Node key adding " + tempKey);
1544: }
1545: indexer.add(tempWrapper, temp);
1546: }
1547:
1548: } else if (indexKeys.size() < cacheKeys.size()) {
1549: //must be an add
1550: // copy set keys just to make sure
1551: if (log.isDebugEnabled()) {
1552: log.debug("Node key added for " + arg0
1553: + " indexKeys:" + indexKeys
1554: + " cacheKeys" + cacheKeys);
1555: }
1556: Set tempSet = new HashSet(cacheKeys);
1557: tempSet.removeAll(indexKeys);
1558: // should be left with new key
1559: for (Iterator it = tempSet.iterator(); it
1560: .hasNext();) {
1561: Object tempKey = it.next();
1562: Object temp = cache.peek(arg0, tempKey);
1563: if (log.isDebugEnabled()) {
1564: log.debug("Node key adding " + tempKey);
1565: }
1566: indexer.add(new NameSpaceKeyWrapper(arg0,
1567: tempKey), temp);
1568: }
1569: } else {
1570: // otherwise must be a removal
1571: if (log.isDebugEnabled()) {
1572: log.debug("Node key removed for " + arg0);
1573: }
1574: indexKeys.removeAll(cacheKeys);
1575: // should be left with new key
1576: for (Iterator it = indexKeys.iterator(); it
1577: .hasNext();) {
1578: Object tempKey = it.next();
1579: if (log.isDebugEnabled()) {
1580: log
1581: .debug("Node key removed "
1582: + tempKey);
1583: }
1584: indexer.remove(new NameSpaceKeyWrapper(
1585: arg0, tempKey));
1586: }
1587: }
1588: }
1589:
1590: } catch (Exception e) {
1591: log.warn(
1592: "node modification failed to update index with node "
1593: + arg0, e);
1594: }
1595:
1596: }
1597:
1598: /*
1599: * (non-Javadoc)
1600: *
1601: * @see org.jboss.cache.TreeCacheListener#nodeVisited(org.jboss.cache.Fqn)
1602: */
1603: public void nodeVisited(Fqn arg0) {
1604: // we do not care
1605:
1606: }
1607:
1608: /*
1609: * (non-Javadoc)
1610: *
1611: * @see org.jboss.cache.TreeCacheListener#cacheStarted(org.jboss.cache.TreeCache)
1612: */
1613: public void cacheStarted(TreeCache arg0) {
1614: // we do not care
1615:
1616: }
1617:
1618: /*
1619: * (non-Javadoc)
1620: *
1621: * @see org.jboss.cache.TreeCacheListener#cacheStopped(org.jboss.cache.TreeCache)
1622: */
1623: public void cacheStopped(TreeCache arg0) {
1624: // we do not care
1625:
1626: }
1627:
1628: /*
1629: * (non-Javadoc)
1630: *
1631: * @see org.jboss.cache.TreeCacheListener#viewChange(org.jgroups.View)
1632: */
1633: public void viewChange(View arg0) {
1634: // we do not care
1635:
1636: }
1637:
1638: }
1639:
1640: /*
1641: * (non-Javadoc)
1642: *
1643: * @see com.jofti.core.ITransactionAware#getTransactionLevel()
1644: */
1645: public TransactionLevel getTransactionLevel() throws JoftiException {
1646: if (cache.getIsolationLevelClass() == IsolationLevel.NONE) {
1647: return TransactionLevel.NONE;
1648: } else if (cache.getIsolationLevelClass() == IsolationLevel.READ_COMMITTED) {
1649: return TransactionLevel.READ_COMMITTED;
1650: } else if (cache.getIsolationLevelClass() == IsolationLevel.READ_UNCOMMITTED) {
1651: return TransactionLevel.READ_UNCOMMITTED;
1652: } else if (cache.getIsolationLevelClass() == IsolationLevel.REPEATABLE_READ) {
1653: return TransactionLevel.REPEATABLE_READ;
1654: } else {
1655: return TransactionLevel.SERIALIZABLE;
1656: }
1657: }
1658:
1659: protected Object getCacheValue(Object key) {
1660: return get(key);
1661: }
1662:
1663: /* (non-Javadoc)
1664: * @see com.jofti.cache.CacheLocking#getIndex()
1665: */
1666: public InternalIndex getIndex() {
1667:
1668: return null;
1669: }
1670:
1671: boolean isRollback(int status) {
1672: return status == Status.STATUS_MARKED_ROLLBACK
1673: || status == Status.STATUS_ROLLING_BACK
1674: || status == Status.STATUS_ROLLEDBACK;
1675: }
1676:
1677: }
|