1 23 24 package com.sun.jdo.spi.persistence.support.sqlstore.impl; 25 26 import java.util.Collections ; 27 import java.util.HashMap ; 28 import java.util.Iterator ; 29 import java.util.Map ; 30 import java.util.Properties ; 31 import java.util.ResourceBundle ; 32 33 import com.sun.appserv.util.cache.Cache; 34 import com.sun.appserv.util.cache.CacheListener; 35 import com.sun.appserv.util.cache.LruCache; 36 37 import com.sun.jdo.spi.persistence.support.sqlstore.LogHelperPersistenceManager; 38 import com.sun.jdo.spi.persistence.support.sqlstore.StateManager; 39 import com.sun.jdo.spi.persistence.support.sqlstore.VersionConsistencyCache; 40 41 import com.sun.jdo.spi.persistence.utility.BucketizedHashtable; 42 import com.sun.jdo.spi.persistence.utility.I18NHelper; 43 import com.sun.jdo.spi.persistence.utility.logging.Logger; 44 45 46 53 public class VersionConsistencyCacheImpl implements VersionConsistencyCache { 54 55 private final Map pcTypeMap = new HashMap (); 56 57 58 private static CacheFactory cacheFactory; 60 61 private final static ResourceBundle messages = 62 I18NHelper.loadBundle(VersionConsistencyCacheImpl.class); 63 64 65 private static Logger logger = LogHelperPersistenceManager.getLogger(); 66 67 68 private static final String LRU_CACHE_CLASSNAME = 69 "com.sun.appserv.util.cache.LruCache"; 71 72 76 77 private static final String PROPERTY_PREFIX = 78 "com.sun.jdo.spi.persistence.support.sqlstore.impl.VersionConsistency."; 80 81 82 private static boolean lruCache = false; 83 84 85 private static final String LRU_CACHE_PROPERTY = PROPERTY_PREFIX + "LruCache"; 87 88 89 private static float loadFactor = 0.75F; 90 91 92 private static final String LOAD_FACTOR_PROPERTY = 93 PROPERTY_PREFIX + "loadFactor"; 95 96 97 private static int bucketSize = 13; 98 99 100 private static final String BUCKET_SIZE_PROPERTY = 101 PROPERTY_PREFIX + "bucketSize"; 103 104 105 private static int initialCapacity = 131; 106 107 108 private static final String INITIAL_CAPACITY_PROPERTY = 109 PROPERTY_PREFIX + "initialCapacity"; 111 112 113 private static int maxEntries = 131; 114 115 116 private static final String MAX_ENTRIES_PROPERTY = 117 PROPERTY_PREFIX + "maxEntries"; 119 120 121 private static long timeout = 1000L * 60 * 10; 122 123 124 private static final String TIMEOUT_PROPERTY = 125 PROPERTY_PREFIX + "timeout"; 127 static { 129 cacheFactory = createCacheFactory(); 130 } 131 132 133 134 private VersionConsistencyCacheImpl() { 135 } 136 137 141 protected VersionConsistencyCacheImpl(boolean highPerf) { 142 if (highPerf) { 143 cacheFactory = new LruCacheFactory(); 144 } else { 145 cacheFactory = new BasicCacheFactory(); 146 } 147 } 148 149 159 static VersionConsistencyCache create() { 160 return new VersionConsistencyCacheImpl(); 161 } 162 163 167 static CacheFactory createCacheFactory() { 168 CacheFactory rc = null; 169 170 loadFactor = getFloatValue(LOAD_FACTOR_PROPERTY, loadFactor); 171 172 bucketSize = getIntValue(BUCKET_SIZE_PROPERTY, bucketSize); 173 174 initialCapacity = getIntValue(INITIAL_CAPACITY_PROPERTY, initialCapacity); 175 176 maxEntries = getIntValue(MAX_ENTRIES_PROPERTY, maxEntries); 177 178 timeout = getLongValue(TIMEOUT_PROPERTY, timeout); 179 180 boolean lruCache = false; 182 try { 183 184 String s = System.getProperty(LRU_CACHE_PROPERTY); 187 if (s != null) { 188 lruCache = Boolean.valueOf(s).booleanValue(); 189 if (lruCache) { 190 191 try { 194 Class.forName(LRU_CACHE_CLASSNAME); 195 } catch (Exception ex) { 196 logger.warning( 197 I18NHelper.getMessage( 198 messages, 199 "jdo.versionconsistencycacheimpl.lrucachenotfound")); lruCache = false; 201 } 202 } 203 204 } else { 205 try { 207 Class.forName(LRU_CACHE_CLASSNAME); 208 lruCache = true; 209 } catch (Exception ex) { 210 } 212 } 213 } catch (Exception ex) { 214 215 lruCache = false; 218 logger.warning( 219 I18NHelper.getMessage( 220 messages, 221 "jdo.versionconsistencycacheimpl.unexpectedduringcreate", ex)); } 223 224 if (lruCache) { 225 rc = new LruCacheFactory(); 226 } else { 227 rc = new BasicCacheFactory(); 228 } 229 230 if (logger.isLoggable(Logger.FINER)) { 231 String values = 232 "\nloadFactor= " + loadFactor + "\nbucketSize= " + bucketSize + "\ninitialCapacity=" + initialCapacity + "\nmaxEntries=" + maxEntries + "\ntimeout=" + timeout + "\nlruCache=" + lruCache; logger.finer( 239 I18NHelper.getMessage( 240 messages, 241 "jdo.versionconsistencycacheimpl.created", 242 values)); } 244 245 return rc; 246 } 247 248 256 private static int getIntValue(String propName, int defaultVal) { 257 int rc = defaultVal; 258 String valString = System.getProperty(propName); 259 if (null != valString && valString.length() > 0) { 260 try { 261 rc = Integer.parseInt(valString); 262 } catch (NumberFormatException ex) { 263 logBadConfigValue(propName, valString); 264 } 265 } 266 return rc; 267 } 268 269 277 private static float getFloatValue(String propName, float defaultVal) { 278 float rc = defaultVal; 279 String valString = System.getProperty(propName); 280 if (null != valString && valString.length() > 0) { 281 try { 282 rc = Float.parseFloat(valString); 283 } catch (NumberFormatException ex) { 284 logBadConfigValue(propName, valString); 285 } 286 } 287 return rc; 288 } 289 290 298 private static long getLongValue(String propName, long defaultVal) { 299 long rc = defaultVal; 300 String valString = System.getProperty(propName); 301 if (null != valString && valString.length() > 0) { 302 try { 303 rc = Long.parseLong(valString); 304 } catch (NumberFormatException ex) { 305 logBadConfigValue(propName, valString); 306 } 307 } 308 return rc; 309 } 310 311 316 private static void logBadConfigValue(String propName, String valString) { 317 logger.warning( 318 I18NHelper.getMessage( 319 messages, 320 "jdo.versionconsistencycacheimpl.badconfigvalue", propName, valString)); 322 } 323 324 327 public StateManager put(Class pcType, Object oid, StateManager sm) { 328 boolean logAtFinest = logger.isLoggable(Logger.FINEST); 329 330 if (logAtFinest) { 331 logger.finest( 332 I18NHelper.getMessage( 333 messages, 334 "jdo.versionconsistencycacheimpl.put.entering", new Object [] {pcType, oid, sm})); 336 } 337 338 StateManager rc = null; 339 VCCache oid2sm = null; 340 synchronized (pcTypeMap) { 341 oid2sm = (VCCache) pcTypeMap.get(pcType); 342 343 if (null == oid2sm) { 344 oid2sm = cacheFactory.create(); 345 pcTypeMap.put(pcType, oid2sm); 346 } 347 } 348 349 rc = oid2sm.put(oid, sm); 350 351 if (logAtFinest) { 352 logger.finest( 353 I18NHelper.getMessage( 354 messages, 355 "jdo.versionconsistencycacheimpl.put.returning", rc)); 357 } 358 359 return rc; 360 } 361 362 365 public StateManager get(Class pcType, Object oid) { 366 boolean logAtFinest = logger.isLoggable(Logger.FINEST); 367 368 if (logAtFinest) { 369 logger.finest( 370 I18NHelper.getMessage( 371 messages, 372 "jdo.versionconsistencycacheimpl.get.entering", new Object [] {pcType, oid})); 374 } 375 StateManager rc = null; 376 377 VCCache oid2sm = null; 378 synchronized (pcTypeMap) { 379 oid2sm = (VCCache) pcTypeMap.get(pcType); 380 } 381 382 if (null != oid2sm) { 383 rc = oid2sm.get(oid); 384 } 385 386 if (logAtFinest) { 387 logger.finest( 388 I18NHelper.getMessage( 389 messages, 390 "jdo.versionconsistencycacheimpl.get.returning", rc)); 392 } 393 return rc; 394 } 395 396 397 400 public StateManager remove(Class pcType, Object oid) { 401 boolean logAtFinest = logger.isLoggable(Logger.FINEST); 402 403 if (logAtFinest) { 404 logger.finest( 405 I18NHelper.getMessage( 406 messages, 407 "jdo.versionconsistencycacheimpl.remove.entering", new Object [] {pcType, oid})); 409 } 410 411 StateManager rc = null; 412 synchronized (pcTypeMap) { 413 VCCache oid2sm = (VCCache) pcTypeMap.get(pcType); 414 415 if (null != oid2sm) { 416 rc = (StateManager) oid2sm.remove(oid); 417 if (oid2sm.isEmpty()) { 418 pcTypeMap.remove(pcType); 419 } 420 } 421 } 422 423 if (logAtFinest) { 424 logger.finest( 425 I18NHelper.getMessage( 426 messages, 427 "jdo.versionconsistencycacheimpl.remove.returning", rc)); 429 } 430 return rc; 431 } 432 433 437 public void addPCType(Class pcType) { 438 if (logger.isLoggable(Logger.FINEST)) { 439 logger.finest( 440 I18NHelper.getMessage( 441 messages, 442 "jdo.versionconsistencycacheimpl.addpctype", pcType)); 444 } 445 } 447 448 451 public void removePCType(Class pcType) { 452 if (logger.isLoggable(Logger.FINEST)) { 453 logger.finest( 454 I18NHelper.getMessage( 455 messages, 456 "jdo.versionconsistencycacheimpl.removepctype", pcType)); 458 } 459 460 synchronized (pcTypeMap) { 461 VCCache oid2sm = (VCCache) pcTypeMap.get(pcType); 462 463 if (null != oid2sm) { 464 oid2sm.clear(); 465 } 466 pcTypeMap.remove(pcType); 467 } 468 } 469 470 473 public int size() { 474 int rc = 0; 475 synchronized (pcTypeMap) { 476 for (Iterator i = pcTypeMap.keySet().iterator(); i.hasNext();) { 477 VCCache oid2sm = (VCCache) pcTypeMap.get(i.next()); 478 rc += oid2sm.size(); 479 } 480 } 481 return rc; 482 } 483 484 487 public boolean isHighPerf() { 488 return LruCacheFactory.class.equals(cacheFactory.getClass()); 489 } 490 491 495 496 interface VCCache { 497 498 public StateManager put(Object key, StateManager value); 499 500 501 public StateManager get(Object key); 502 503 504 public StateManager remove(Object key); 505 506 507 public void clear(); 508 509 510 public boolean isEmpty(); 511 512 513 public int size(); 514 } 515 516 520 static class BasicVCCache implements VCCache { 521 private final Map cache; 522 523 BasicVCCache() { 524 if (logger.isLoggable(Logger.FINER)) { 525 logger.finer( 526 I18NHelper.getMessage( 527 messages, 528 "jdo.versionconsistencycacheimpl.usinghashmap", new Object [] { 530 new Integer (bucketSize), 531 new Long (initialCapacity), 532 new Float (loadFactor)})); 533 } 534 535 cache = Collections.synchronizedMap( 536 new BucketizedHashtable( 537 bucketSize, initialCapacity, loadFactor)); 538 } 539 540 541 public StateManager put(Object key, StateManager value) { 542 return (StateManager) cache.put(key, value); 543 } 544 545 546 public StateManager get(Object key) { 547 return (StateManager) cache.get(key); 548 } 549 550 551 public StateManager remove(Object key) { 552 return (StateManager) cache.remove(key); 553 } 554 555 556 public void clear() { 557 cache.clear(); 558 } 559 560 561 public boolean isEmpty() { 562 return cache.isEmpty(); 563 } 564 565 566 public int size() { 567 return cache.size(); 568 } 569 } 570 571 575 static class LruVCCache implements VCCache { 576 580 private final Cache cache; 581 582 587 LruVCCache(int maxEntries, long timeout, float loadFactor) { 588 if (logger.isLoggable(Logger.FINER)) { 589 logger.finer( 590 I18NHelper.getMessage( 591 messages, 592 "jdo.versionconsistencycacheimpl.usinglrucache", new Object [] { 594 new Integer (maxEntries), 595 new Long (timeout), 596 new Float (loadFactor)})); 597 } 598 599 LruCache c = new LruCache(); 600 c.init(maxEntries, timeout, loadFactor, (Properties ) null); 601 c.addCacheListener( 602 new CacheListener() { 603 public void trimEvent(Object key, Object value) { 604 cache.remove(key); 605 if (logger.isLoggable(Logger.FINER)) { 606 logger.finer( 607 I18NHelper.getMessage( 608 messages, 609 "jdo.versionconsistencycacheimpl.trimevent")); } 611 } 612 }); 613 cache = c; 614 } 615 616 617 public StateManager put(Object key, StateManager value) { 618 return (StateManager) cache.put(key, value); 619 } 620 621 622 public StateManager get(Object key) { 623 return (StateManager) cache.get(key); 624 } 625 626 627 public StateManager remove(Object key) { 628 return (StateManager) cache.remove(key); 629 } 630 631 632 public void clear() { 633 cache.clear(); 634 } 635 636 637 public boolean isEmpty() { 638 return cache.isEmpty(); 639 } 640 641 642 public int size() { 643 return cache.getEntryCount(); 644 } 645 } 646 647 651 652 interface CacheFactory { 653 654 public VCCache create(); 655 } 656 657 658 static class BasicCacheFactory implements CacheFactory { 659 660 661 public VCCache create() { 662 return new BasicVCCache(); 663 } 664 } 665 666 667 static class LruCacheFactory implements CacheFactory { 668 669 670 public VCCache create() { 671 return new LruVCCache(maxEntries, timeout, loadFactor); 672 } 673 } 674 } 675 | Popular Tags |