1 29 30 package com.caucho.server.cluster; 31 32 import com.caucho.config.types.Period; 33 import com.caucho.lifecycle.Lifecycle; 34 import com.caucho.loader.ClassLoaderListener; 35 import com.caucho.loader.DynamicClassLoader; 36 import com.caucho.loader.Environment; 37 import com.caucho.loader.EnvironmentClassLoader; 38 import com.caucho.loader.EnvironmentListener; 39 import com.caucho.management.server.PersistentStoreMXBean; 40 import com.caucho.util.Alarm; 41 import com.caucho.util.AlarmListener; 42 import com.caucho.util.L10N; 43 import com.caucho.util.Log; 44 import com.caucho.util.LruCache; 45 import com.caucho.vfs.TempStream; 46 47 import javax.annotation.PostConstruct; 48 import java.io.IOException ; 49 import java.util.HashMap ; 50 import java.util.logging.Level ; 51 import java.util.logging.Logger ; 52 53 56 abstract public class StoreManager 57 implements AlarmListener, EnvironmentListener, ClassLoaderListener { 58 static protected final Logger log = Log.open(StoreManager.class); 59 static final L10N L = new L10N(StoreManager.class); 60 61 private static int DECODE[]; 62 63 private Cluster _cluster; 64 private String _serverId; 65 66 protected int _selfIndex; 67 private ServerConnector []_serverList; 68 69 private Alarm _alarm; 70 71 protected long _maxIdleTime = 3 * 3600 * 1000L; 73 protected long _idleCheckInterval = 5 * 60 * 1000L; 74 75 protected boolean _isAlwaysLoad; 76 protected boolean _isAlwaysSave; 77 78 protected HashMap <String ,Store> _storeMap; 79 protected LruCache<String ,ClusterObject> _clusterObjects 80 = new LruCache<String ,ClusterObject>(4096); 81 82 private final Lifecycle _lifecycle = new Lifecycle(log, toString()); 83 84 88 protected volatile long _loadCount; 89 protected volatile long _loadFailCount; 90 91 protected volatile long _saveCount; 92 protected volatile long _saveFailCount; 93 94 protected StoreManager() 95 { 96 _storeMap = new HashMap <String ,Store>(); 97 98 _alarm = new Alarm(this); 99 100 Environment.addClassLoaderListener(this); 101 } 102 103 106 public void setCluster(Cluster cluster) 107 { 108 _cluster = cluster; 109 } 110 111 114 public Cluster getCluster() 115 { 116 return _cluster; 117 } 118 119 122 public PersistentStoreMXBean getAdmin() 123 { 124 return null; 125 } 126 127 130 public void setAlwaysLoad(boolean alwaysLoad) 131 { 132 _isAlwaysLoad = alwaysLoad; 133 } 134 135 138 public boolean isAlwaysLoad() 139 { 140 return _isAlwaysLoad; 141 } 142 143 146 public void setAlwaysSave(boolean alwaysSave) 147 { 148 _isAlwaysSave = alwaysSave; 149 } 150 151 154 public boolean isAlwaysSave() 155 { 156 return _isAlwaysSave; 157 } 158 159 163 public long getMaxIdleTime() 164 { 165 return _maxIdleTime; 166 } 167 168 172 public void setMaxIdleTime(Period maxIdleTime) 173 { 174 _maxIdleTime = maxIdleTime.getPeriod(); 175 } 176 177 180 public void updateIdleCheckInterval(long idleCheckInterval) 181 { 182 if (_idleCheckInterval > 0 && idleCheckInterval > 0 && 183 idleCheckInterval < _idleCheckInterval) { 184 _idleCheckInterval = idleCheckInterval; 185 _alarm.queue(idleCheckInterval); 186 } 187 188 if (_idleCheckInterval >= 0 && _idleCheckInterval < 1000) 189 _idleCheckInterval = 1000; 190 } 191 192 195 public long getIdleCheckTime() 196 { 197 if (_idleCheckInterval > 0) 198 return _idleCheckInterval; 199 else 200 return _maxIdleTime; 201 } 202 203 207 public long getAccessWindowTime() 208 { 209 long window = _maxIdleTime / 4; 210 211 if (window < 60000L) 212 return 60000L; 213 else 214 return window; 215 } 216 217 221 224 public long getObjectCount() 225 { 226 return -1; 227 } 228 229 232 public long getLoadCount() 233 { 234 return _loadCount; 235 } 236 237 240 public long getLoadFailCount() 241 { 242 return _loadFailCount; 243 } 244 245 248 public long getSaveCount() 249 { 250 return _saveCount; 251 } 252 253 256 public long getSaveFailCount() 257 { 258 return _saveFailCount; 259 } 260 261 268 public Store createStore(String storeId, ObjectManager objectManager) 269 { 270 Store store = getStore(storeId); 271 272 store.setObjectManager(objectManager); 273 274 return store; 275 } 276 277 284 public Store removeStore(String storeId) 285 { 286 Store store = getStore(storeId); 287 288 store.setObjectManager(null); 289 290 return store; 291 } 292 293 300 public Store getStore(String storeId) 301 { 302 synchronized (_storeMap) { 303 Store store = _storeMap.get(storeId); 304 if (store == null) { 305 store = new Store(storeId, this); 306 _storeMap.put(storeId, store); 307 } 308 309 return store; 310 } 311 } 312 313 316 @PostConstruct 317 public boolean init() 318 throws Exception 319 { 320 if (! _lifecycle.toInit()) 321 return false; 322 323 _lifecycle.setName(toString()); 324 325 if (_cluster == null) 326 _cluster = Cluster.getLocal(); 327 328 if (_cluster != null) { 329 _serverId = _cluster.getServerId(); 330 ClusterServer selfServer = _cluster.getSelfServer(); 331 332 if (selfServer != null) 333 _selfIndex = selfServer.getIndex(); 334 else if (_cluster.getServerList().length > 1) { 335 log.warning(L.l("cluster-store for '{0}' needs an <srun> configuration for it.", 337 _serverId)); 338 } 339 340 ClusterServer []serverList = _cluster.getServerList(); 341 342 _serverList = new ServerConnector[serverList.length]; 343 344 for (int i = 0; i < serverList.length; i++) { 345 _serverList[i] = serverList[i].getServerConnector(); 346 } 347 } 348 349 350 Environment.addEnvironmentListener(this); 351 352 return true; 353 } 354 355 358 public boolean start() 359 throws Exception 360 { 361 if (! _lifecycle.toActive()) 362 return false; 363 364 if (_serverList != null) { 366 ServerConnector []serverList = _serverList; 367 368 for (int i = 0; i < serverList.length; i++) { 369 ServerConnector server = serverList[i]; 370 371 if (server == null) 372 continue; 373 374 ClusterClient client = server.getClient(); 375 376 try { 377 if (client != null) { 378 ClusterStream s = client.open(); 379 s.close(); 380 } 381 } catch (Throwable e) { 382 } 383 } 384 385 } 386 387 handleAlarm(_alarm); 388 389 return true; 390 } 391 392 397 public void clearOldObjects() 398 throws Exception 399 { 400 } 401 402 405 protected boolean isPrimary(String id) 406 { 407 return getPrimaryIndex(id, 0) == getSelfIndex(); 408 } 409 410 413 public int getPrimaryIndex(String id, int offset) 414 { 415 return 0; 416 } 417 418 421 public int getSecondaryIndex(String id, int offset) 422 { 423 return 0; 424 } 425 426 429 public int getTertiaryIndex(String id, int offset) 430 { 431 return 0; 432 } 433 434 439 abstract protected boolean load(ClusterObject clusterObject, Object obj) 440 throws Exception ; 441 442 448 public void access(String uniqueId) 449 throws Exception 450 { 451 ClusterObject obj = getClusterObject(uniqueId); 452 453 if (obj != null) 454 obj.access(); 455 else 456 accessImpl(uniqueId); 457 } 458 459 465 public void access(Store store, String id) 466 throws Exception 467 { 468 getClusterObject(store, id).access(); 469 } 470 471 476 abstract public void accessImpl(String uniqueId) 477 throws Exception ; 478 479 485 public void setExpireInterval(String uniqueId, long expires) 486 throws Exception 487 { 488 } 489 490 496 public void update(String storeId, String objectId) 497 throws Exception 498 { 499 ClusterObject obj = getClusterObject(storeId, objectId); 500 501 if (obj != null) 502 obj.update(); 503 } 504 505 510 public void updateOwner(String objectId, String uniqueId) 511 throws Exception 512 { 513 514 } 515 516 522 public void store(Store store, String id, Object obj) 523 throws IOException 524 { 525 ClusterObject clusterObj = getClusterObject(store, id); 526 527 if (clusterObj != null) { 528 } 529 else if (store.getObjectManager().isEmpty(obj)) 530 return; 531 else 532 clusterObj = createClusterObject(store, id); 533 534 clusterObj.store(obj); 535 } 536 537 543 ClusterObject createClusterObject(Store store, String id) 544 { 545 try { 546 String uniqueId = store.getId() + ';' + id; 547 548 synchronized (this) { 549 ClusterObject clusterObj = _clusterObjects.get(uniqueId); 550 if (clusterObj == null) { 551 clusterObj = create(store, id); 552 _clusterObjects.put(clusterObj.getUniqueId(), clusterObj); 553 } 554 555 return clusterObj; 556 } 557 } catch (Throwable e) { 558 log.log(Level.WARNING, e.toString(), e); 559 560 return null; 561 } 562 } 563 564 570 ClusterObject getClusterObject(Store store, String id) 571 { 572 return getClusterObject(makeUniqueId(store, id)); 573 } 574 575 581 ClusterObject getClusterObject(String storeId, String id) 582 { 583 return getClusterObject(makeUniqueId(storeId, id)); 584 } 585 586 592 ClusterObject getClusterObject(String uniqueId) 593 { 594 return _clusterObjects.get(uniqueId); 595 } 596 597 603 ClusterObject removeClusterObject(String storeId, String id) 604 { 605 synchronized (this) { 606 return _clusterObjects.remove(makeUniqueId(storeId, id)); 607 } 608 } 609 610 613 ClusterObject create(Store store, String id) 614 { 615 return new ClusterObject(this, store, id); 616 } 617 618 624 abstract protected void store(ClusterObject clusterObject, 625 TempStream tempStream, 626 long crc) 627 throws Exception ; 628 629 632 public void handleAlarm(Alarm alarm) 633 { 634 if (! _lifecycle.isActive()) 635 return; 636 637 try { 638 clearOldObjects(); 639 } catch (Throwable e) { 640 log.log(Level.WARNING, e.toString(), e); 641 } finally { 642 _alarm.queue(getIdleCheckTime()); 643 } 644 } 645 646 651 public void remove(ClusterObject obj) 652 throws Exception 653 { 654 655 } 656 657 663 public void remove(Store store, String objectId) 664 throws Exception 665 { 666 } 667 668 671 private String makeUniqueId(Store store, String objectId) 672 { 673 return store.getId() + ';' + objectId; 674 } 675 676 679 private String makeUniqueId(String storeId, String objectId) 680 { 681 return storeId + ';' + objectId; 682 } 683 684 687 protected int getSelfIndex() 688 { 689 return _selfIndex; 690 } 691 692 695 protected ServerConnector []getServerList() 696 { 697 return _serverList; 698 } 699 700 703 protected ServerConnector getOwningServer(String objectId) 704 { 705 if (_cluster == null) 706 return null; 707 708 char ch = objectId.charAt(0); 709 710 ServerConnector []serverList = _serverList; 711 712 if (serverList.length > 0) { 713 int srunIndex = decode(ch) % serverList.length; 714 715 return serverList[srunIndex]; 716 } 717 else 718 return null; 719 } 720 721 724 public void environmentStart(EnvironmentClassLoader loader) 725 { 726 try { 727 start(); 728 } catch (Exception e) { 729 log.log(Level.WARNING, e.toString(), e); 730 } 731 } 732 733 736 public void environmentStop(EnvironmentClassLoader loader) 737 { 738 } 739 740 743 public void classLoaderInit(DynamicClassLoader loader) 744 { 745 } 746 747 750 public void classLoaderDestroy(DynamicClassLoader loader) 751 { 752 destroy(); 753 } 754 755 758 public void destroy() 759 { 760 if (! _lifecycle.toDestroy()) 761 return; 762 763 _alarm.dequeue(); 764 } 765 766 static class ObjectKey { 767 private String _storeId; 768 private String _objectId; 769 770 ObjectKey() 771 { 772 } 773 774 ObjectKey(String storeId, String objectId) 775 { 776 init(storeId, objectId); 777 } 778 779 void init(String storeId, String objectId) 780 { 781 _storeId = storeId; 782 _objectId = objectId; 783 } 784 785 public int hashCode() 786 { 787 return _storeId.hashCode() * 65521 + _objectId.hashCode(); 788 } 789 790 public boolean equals(Object o) 791 { 792 if (this == o) 793 return true; 794 else if (! (o instanceof ObjectKey)) 795 return false; 796 797 ObjectKey key = (ObjectKey) o; 798 799 return _objectId.equals(key._objectId) && _storeId.equals(key._storeId); 800 } 801 } 802 803 static int decode(int code) 804 { 805 return DECODE[code & 0x7f]; 806 } 807 808 811 private static char convert(long code) 812 { 813 code = code & 0x3f; 814 815 if (code < 26) 816 return (char) ('a' + code); 817 else if (code < 52) 818 return (char) ('A' + code - 26); 819 else if (code < 62) 820 return (char) ('0' + code - 52); 821 else if (code == 62) 822 return '_'; 823 else 824 return '-'; 825 } 826 827 static { 828 DECODE = new int[128]; 829 for (int i = 0; i < 64; i++) 830 DECODE[(int) convert(i)] = i; 831 } 832 } 833 | Popular Tags |