1 package com.jofti.cache.adapter; 2 3 import java.util.HashMap ; 4 import java.util.Iterator ; 5 import java.util.LinkedHashMap ; 6 import java.util.List ; 7 import java.util.Map ; 8 import java.util.Properties ; 9 import java.util.Set ; 10 import java.util.Map.Entry; 11 12 import org.apache.commons.logging.Log; 13 import org.apache.commons.logging.LogFactory; 14 15 import com.ibm.websphere.objectgrid.BackingMap; 16 import com.ibm.websphere.objectgrid.IndexAlreadyDefinedException; 17 import com.ibm.websphere.objectgrid.IndexUndefinedException; 18 import com.ibm.websphere.objectgrid.ObjectGridException; 19 import com.ibm.websphere.objectgrid.ObjectMap; 20 import com.ibm.websphere.objectgrid.Session; 21 import com.ibm.websphere.objectgrid.TxID; 22 import com.ibm.websphere.objectgrid.plugins.index.DynamicIndexCallback; 23 import com.jofti.api.CacheAccessor; 24 import com.jofti.api.IndexQuery; 25 import com.jofti.cache.BaseAdaptor; 26 import com.jofti.cache.CacheListenerAdapter; 27 import com.jofti.cache.adapter.listener.ObjectGridEventListener; 28 import com.jofti.core.IParsedQuery; 29 import com.jofti.core.InternalIndex; 30 import com.jofti.exception.JoftiException; 31 import com.jofti.introspect.ClassIntrospector; 32 import com.jofti.parser.ClassFieldMethods; 33 import com.jofti.util.CompositeComparator; 34 import com.jofti.util.ObjectProcedureAdapter; 35 import com.jofti.util.OpenHashMap; 36 import com.jofti.util.ValueTreeMap; 37 import com.tangosol.net.NamedCache; 38 import com.tangosol.util.MapEvent; 39 40 60 public class ObjectGridListenerAdapter extends BaseAdaptor implements CacheAccessor, CacheListenerAdapter 61 { 62 63 64 private static Log log = LogFactory 65 .getLog(ObjectGridListenerAdapter.class); 66 67 68 private String name; 69 70 public InternalIndex index; 71 72 private ObjectGridEventListener eventListener = null; 73 74 75 private BackingMap cache =null; 76 77 private Object loadLock = new Object (); 78 79 private boolean loaded =true; 80 81 private boolean dynamicIndex =false; 82 83 private boolean plugIn =false; 84 85 public ObjectGridListenerAdapter() 86 { 87 } 88 89 public ObjectGridListenerAdapter(Object cache) 90 { 91 this.cache = (BackingMap) cache; 92 93 } 94 97 public synchronized void init(Properties properties) throws JoftiException 98 { 99 if (properties != null) { 100 String key = null; 101 for (Iterator it = properties.keySet().iterator(); it.hasNext();) { 102 key = (String ) it.next(); 103 if (MUTABLE_VALUES.equalsIgnoreCase(key)) { 104 checkMutable = Boolean.valueOf( 105 properties.getProperty(key)).booleanValue(); 106 if (log.isInfoEnabled()) { 107 log.info("Mutability checking is set to " 108 + checkMutable); 109 } 110 } 111 if ("file".equalsIgnoreCase(key)) { 112 log.warn("Listener adapters cannot be used to start up a Cache - check docs for Adapter Type"); 113 throw new JoftiException("Listener adapters cannot be used to start up a Cache - check docs for Adapter Type"); 114 } 115 if ("plugin".equalsIgnoreCase(key)) { 116 log.info("Listener used as plug-in"); 117 plugIn =true; 118 } 119 } 120 } 121 122 123 if (cache == null) { 124 throw new JoftiException("Cache cannot be null for listener adapter"); 125 } else { 126 log.info("Index started using cache "+ cache.getName()); 127 } 128 eventListener = new ObjectGridEventListener(this, name); 129 130 } 131 132 133 134 135 136 139 public synchronized void destroy() throws JoftiException 140 { 141 142 try { 143 cache.removeMapEventListener(eventListener); 144 } catch (IllegalStateException e) { 145 log.warn("Unable to remove event listener:",e); 146 } 147 if (!dynamicIndex){ 148 List indexes = cache.getMapIndexPlugins(); 149 for(int i=0;i<indexes.size();i++){ 150 if (indexes.get(i) == eventListener){ 151 indexes.remove(i); 152 } 153 } 154 }else{ 155 try { 156 cache.removeDynamicIndex(name); 157 } catch (IndexUndefinedException e) { 158 log.warn("Unable to remove dynamic Index:",e); 159 } catch (IllegalArgumentException e) { 160 161 log.warn("Unable to remove dynamic Index:",e); 162 } 163 164 } 165 if (index != null){ 166 index.removeAll(); 167 } 168 log.info("Removed index from cache:"+name); 169 170 } 171 172 175 public String getName() 176 { 177 return name; 178 } 179 180 183 public void setName(String name) 184 { 185 this.name = name; 186 } 187 188 public String toString() 189 { 190 return "ObjectGridCache(" + getName() + ')'; 191 } 192 193 194 195 196 201 public void setInternalIndex(InternalIndex index) 202 { 203 this.index = index; 204 205 } 206 207 210 public Map query(IndexQuery query) throws JoftiException 211 { 212 213 while (!loaded){ 214 synchronized (loadLock) { 215 try { 216 loadLock.wait(); 217 }catch (InterruptedException e){ 218 219 } 220 } 221 } 222 Map temp = null; 223 224 query = processQuery(query,index.getParserManager()); 225 226 acquireQueryLock(); 227 try { 228 229 temp=index.query(query); 230 } finally { 231 releaseQueryLock(); 232 } 233 return getCacheValues(temp, (IParsedQuery)query,index.getIntrospector()); 234 235 } 236 237 238 239 242 protected Object checkMutable(Object key, Object result) 243 { 244 try { 245 Map cacheObjectValues = index.getIntrospector().getAttributeValues( 247 result); 248 249 Map indexObjectValues = index.getAttributesByKey(decorateKey( key)); 250 251 if (cacheObjectValues.equals(indexObjectValues)) { 252 return result; 253 } else { 254 if (log.isDebugEnabled()) { 255 log.debug("Object under Key " + key 256 + " - attributes changed without re-insert"); 257 } 258 } 259 261 } catch (JoftiException e) { 262 log.warn("Error checking mutability", e); 263 } 264 265 return null; 266 } 267 268 271 public void setCacheImpl(Object cache){ 272 ObjectGridListenerAdapter.this.cache = (BackingMap)cache; 273 274 275 } 276 277 public Map getCacheValues(Map col, final IParsedQuery query, 278 final ClassIntrospector introspector) throws JoftiException { 279 280 281 final Map returnClasses = query.getResultFieldsMap(); 282 final CompositeComparator comp = query.getOrderingComparator(); 283 final int maxResults = query.getMaxResults(); 284 final int startEntry = query.getFirstResult(); 285 286 Map interim = null; 287 if (comp ==null || comp.getSize() ==0){ 288 interim =new HashMap (col.size() + 2, 1.00f); 289 }else{ 290 interim = new ValueTreeMap(comp); 291 } 292 293 final Map temp = interim; 295 296 297 298 OpenHashMap originalMap = (OpenHashMap) col; 300 301 Session session =null; 302 try { 304 session= cache.getObjectGrid().getSession(); 305 306 307 308 final ObjectMap map =session.getMap(cache.getName()); 309 310 311 session.begin(); 312 originalMap.forEachPair(new ObjectProcedureAdapter() { 314 315 public boolean apply(Object key, Object value) throws RuntimeException { 316 317 if (value == null || returnClasses ==null || returnClasses.containsKey(value)) { 319 321 key = stripKey(key); 323 324 Object result = null; 325 try { 326 result =getCacheValue(map, key); 327 } catch (Exception e) { 328 throw new RuntimeException (e); 329 } 330 331 if (result == null) { 332 if (log.isWarnEnabled()) { 333 log 334 .warn("Index and cache have become out of date for key " 335 + key); 336 } 337 } else { 338 if (checkMutable) { 340 result = checkMutable(key, result); 341 if (result == null) { 343 if (log.isDebugEnabled()) { 344 log 345 .debug("Object under key:" 346 + key 347 + " has changed in cache since it was indexed"); 348 } 349 return true; 350 } 351 } 352 353 354 if (returnClasses != null) { 355 ClassFieldMethods fieldSet = (ClassFieldMethods) returnClasses 357 .get(value); 358 359 Map tempMap = fieldSet != null ? fieldSet 360 .getFieldMap() : null; 361 362 if (tempMap != null && tempMap.size() > 0) { 363 365 Map resultMap = new LinkedHashMap (); 366 367 resultMap = introspector.getResultValuesFromObject(resultMap,result,tempMap); 368 369 if (resultMap.size()>0){ 371 Object [] res = new Object [resultMap.size()]; 372 Iterator it = resultMap.entrySet().iterator(); 373 for (int i = 0;i<resultMap.size();i++){ 374 Map.Entry entry = (Map.Entry )it.next(); 375 res[i]= entry.getValue(); 376 } 377 temp.put(key,res); 378 } 379 380 } else { 381 temp.put(key, result); 383 } 384 } else { 385 temp.put(key, result); 386 } 387 } 388 389 } 390 return true; 391 } 392 }); 393 394 } catch(Exception e){ 395 throw new JoftiException(e); 396 }finally{ 397 if (session != null){ 398 try { 399 if(log.isDebugEnabled()){ 400 log.debug("finished search: terminating search tx "+session.getTxID()); 401 } 402 session.commit(); 403 } catch(Exception e){ 404 log.warn("unable to close transaction for query", e); 405 } 406 } 407 } 408 if (maxResults >0 || startEntry >0){ 410 return limitResults(temp, startEntry, maxResults); 411 }else if (startEntry <0 || maxResults <0){ 412 if (startEntry <0){ 413 throw new IllegalArgumentException ("startResult cannot be less than 0:"+startEntry); 414 } 415 if (maxResults <0){ 416 throw new IllegalArgumentException ("maxResults cannot be less than 0:"+maxResults); 417 } 418 } 419 420 421 return temp; 422 } 423 424 protected Object getCacheValue(ObjectMap map, Object key) throws ObjectGridException{ 425 426 return map.get(key); 427 428 } 429 430 433 public void start() throws JoftiException { 434 if (cache != null){ 435 addListener(); 436 437 } 438 439 440 441 } 442 443 private void addListener() throws JoftiException { 444 cache.addMapEventListener(eventListener); 445 446 if (!plugIn){ 447 try { 448 cache.addMapIndexPlugin(eventListener); 449 } catch (IllegalStateException e) { 450 loaded =false; 452 try { 453 cache.createDynamicIndex(eventListener, new DynamicListener()); 454 dynamicIndex =true; 455 } catch (Exception e1) { 458 throw new JoftiException(e1); 459 } 460 461 } catch (IndexAlreadyDefinedException iae){ 462 throw new JoftiException(iae); 463 } 464 } 465 } 466 467 class DynamicListener implements DynamicIndexCallback{ 468 469 public void destroy(String s) { 470 log.info("dynamic index destroyed:"+s); 471 472 } 473 474 public void error(String s, Throwable throwable) { 475 log.error(s, throwable); 476 synchronized (loadLock) { 477 loaded =true; 478 loadLock.notifyAll(); 479 } 480 481 482 } 483 484 public void ready(String s) { 485 log.info("dynamic index ready:"+s); 486 synchronized (loadLock) { 487 loaded =true; 488 loadLock.notifyAll(); 489 } 490 491 492 } 493 494 } 495 496 497 500 public InternalIndex getIndex() { 501 502 return index; 503 } 504 505 508 public Object getCacheImpl() { 509 510 return cache; 511 } 512 513 public IndexQuery addQuery(String name, IndexQuery query)throws JoftiException { 514 515 return index.getParserManager().addQuery(name, query); 516 } 517 518 521 public IndexQuery getQuery(String name) { 522 523 return index.getParserManager().getQuery(name); 524 } 525 526 protected Object getCacheValue(Object key) { 527 return null; 529 } 530 531 public ObjectGridEventListener getEventListener() { 532 return eventListener; 533 } 534 535 } | Popular Tags |