1 22 package org.jboss.cache.invalidation; 23 24 import java.io.Serializable ; 25 import java.util.HashSet ; 26 27 import javax.management.MBeanParameterInfo ; 28 import javax.management.MBeanOperationInfo ; 29 30 import org.jboss.cache.invalidation.InvalidationManager.BridgeInvalidationSubscriptionImpl; 31 32 40 public class InvalidationManager 41 extends org.jboss.system.ServiceMBeanSupport 42 implements InvalidationManagerMBean 43 { 44 45 47 public static final String DEFAULT_JMX_SERVICE_NAME = "jboss.cache:service=InvalidationManager"; 48 public static final String DEFAULT_INVALIDERS_JMX_NAME = "jboss.cache:service=InvalidationGroup"; 49 50 52 protected java.util.Hashtable groups = new java.util.Hashtable (); 53 protected java.util.Vector bridgeSubscribers = new java.util.Vector (); 54 protected int hashcode = 0; 55 56 protected boolean DEFAULT_TO_ASYNCHRONOUS_MODE = false; 57 58 60 62 public InvalidationManager () { super(); } 63 64 public void startService () throws Exception 65 { 66 log.debug ("Starting Invalidation Manager " + this.getServiceName ().toString ()); 69 org.jboss.system.Registry.bind (this.getServiceName ().toString (), this); 70 this.hashcode = this.getServiceName ().hashCode (); 71 } 72 73 public void stopService () 74 { 75 log.debug ("Stoping Invalidation Manager " + this.getServiceName ().toString ()); 76 org.jboss.system.Registry.unbind (this.getServiceName ().toString ()); 77 } 78 79 public boolean getIsAsynchByDefault() 80 { 81 return DEFAULT_TO_ASYNCHRONOUS_MODE; 82 } 83 public void setIsAsynchByDefault(boolean flag) 84 { 85 this.DEFAULT_TO_ASYNCHRONOUS_MODE = flag; 86 } 87 88 public java.util.Collection getInvalidationGroups () 89 { 90 return this.groups.values (); 91 } 92 93 public InvalidationGroup getInvalidationGroup (String groupName) 94 { 95 synchronized (this.groups) 96 { 97 InvalidationGroup group = (InvalidationGroup)this.groups.get (groupName); 98 if (group == null) 99 { 100 group = createGroup (groupName); 101 } 102 103 group.addReference (); 104 105 return group; 106 } 107 } 108 109 public synchronized BridgeInvalidationSubscription registerBridgeListener (InvalidationBridgeListener listener) 110 { 111 log.debug ("Subscribing a new cache-invalidation bridge"); 112 BridgeInvalidationSubscription subs = new BridgeInvalidationSubscriptionImpl(listener); 113 114 java.util.Vector newVector = new java.util.Vector (this.bridgeSubscribers); 115 newVector.add (subs); 116 this.bridgeSubscribers = newVector; 117 118 return subs; 119 } 120 121 public void batchInvalidate (BatchInvalidation[] invalidations) 122 { 123 this.batchInvalidate (invalidations, this.DEFAULT_TO_ASYNCHRONOUS_MODE); 124 } 125 126 public void batchInvalidate (BatchInvalidation[] invalidations, boolean asynchronous) 127 { 128 if (log.isTraceEnabled ()) 129 log.trace ("Batch cache invalidation. Caches concerned: " + invalidations.length); 130 131 this.crossDomainBatchInvalidate (null, invalidations, asynchronous); 132 } 133 134 public void invalidateAll(String groupName) 135 { 136 invalidateAll(groupName, DEFAULT_TO_ASYNCHRONOUS_MODE); 137 } 138 139 public void invalidateAll(String groupName, boolean async) 140 { 141 if (log.isTraceEnabled ()) 142 log.trace ("Invalidate all for group: " + groupName); 143 144 crossDomainInvalidateAll(null, groupName, async); 145 } 146 147 149 151 153 public int hashCode () 154 { 155 return hashcode; 156 } 157 159 161 protected InvalidationGroup createGroup (String groupName) 162 { 163 InvalidationGroup group = new org.jboss.cache.invalidation.InvalidationManager.InvalidationGroupImpl (groupName); 164 this.groups.put (groupName, group); 165 166 try 170 { 171 log.debug ("Creating and registering a new InvalidationGroup: " + groupName); 172 javax.management.ObjectName groupObjectName = new javax.management.ObjectName (DEFAULT_INVALIDERS_JMX_NAME + ",GroupName="+groupName); 173 this.getServer ().registerMBean (group, groupObjectName); 174 } 175 catch (Exception e) 176 { 177 log.debug ("Problem while trying to register a new invalidation group in JMX", e); 178 } 179 180 log.debug ("Informing bridges about new group creation ..."); 183 for (int i=0; i<bridgeSubscribers.size (); i++) 184 ((BridgeInvalidationSubscriptionImpl)(bridgeSubscribers.elementAt (i))).groupCreated (groupName); 185 186 return group; 187 } 188 189 protected void removeGroup (String groupName) 190 { 191 synchronized (this.groups) 192 { 193 this.groups.remove (groupName); 194 195 try 198 { 199 log.debug ("Removing and JMX-unregistering an InvalidationGroup: " + groupName); 200 javax.management.ObjectName groupObjectName = new javax.management.ObjectName (DEFAULT_INVALIDERS_JMX_NAME + ",GroupName="+groupName); 201 this.getServer ().unregisterMBean (groupObjectName); 202 } 203 catch (Exception e) 204 { 205 log.debug ("Problem while trying to un-register a new invalidation group in JMX", e); 206 } 207 208 for (int i=0; i<bridgeSubscribers.size (); i++) 211 ((BridgeInvalidationSubscriptionImpl)(bridgeSubscribers.elementAt (i))).groupDropped (groupName); 212 } 213 214 } 215 216 protected synchronized void unregisterBridgeListener (BridgeInvalidationSubscription bridgeSubscriber) 217 { 218 log.debug ("Unsubscription of a cache-invalidation bridge"); 221 222 java.util.Vector newVector = new java.util.Vector (this.bridgeSubscribers); 223 newVector.remove (bridgeSubscriber); 224 this.bridgeSubscribers = newVector; 225 } 226 227 protected void doLocalOnlyInvalidation (String groupName, Serializable key, boolean asynchronous) 228 { 229 InvalidationGroupImpl group = (InvalidationGroupImpl)this.groups.get (groupName); 230 if (group != null) 231 group.localOnlyInvalidate (key, asynchronous); 232 } 233 234 protected void doLocalOnlyInvalidations (String groupName, Serializable [] keys, boolean asynchronous) 235 { 236 InvalidationGroupImpl group = (InvalidationGroupImpl)this.groups.get (groupName); 237 if (group != null) 238 group.localOnlyInvalidate (keys, asynchronous); 239 } 240 241 protected void doLocalOnlyInvalidateAll (String groupName, boolean asynchronous) 242 { 243 InvalidationGroupImpl group = (InvalidationGroupImpl)this.groups.get (groupName); 244 if (group != null) 245 group.localOnlyInvalidateAll(); 246 } 247 248 protected void doBridgedOnlyInvalidation (BridgeInvalidationSubscriptionImpl exceptSource, String groupName, Serializable key) 249 { 250 for (int i=0; i<bridgeSubscribers.size (); i++) 251 { 252 BridgeInvalidationSubscriptionImpl bridge = (BridgeInvalidationSubscriptionImpl)(bridgeSubscribers.elementAt (i)); 253 if (bridge != exceptSource) 254 bridge.bridgedInvalidate (groupName, key, this.DEFAULT_TO_ASYNCHRONOUS_MODE); 255 } 256 } 257 258 protected void doBridgedOnlyInvalidation (BridgeInvalidationSubscriptionImpl exceptSource, String groupName, Serializable [] keys) 259 { 260 for (int i=0; i<bridgeSubscribers.size (); i++) 261 { 262 BridgeInvalidationSubscriptionImpl bridge = (BridgeInvalidationSubscriptionImpl)(bridgeSubscribers.elementAt (i)); 263 if (bridge != exceptSource) 264 bridge.bridgedInvalidate (groupName, keys, this.DEFAULT_TO_ASYNCHRONOUS_MODE); 265 } 266 } 267 268 protected void doBridgedOnlyInvalidateAll (BridgeInvalidationSubscriptionImpl exceptSource, String groupName) 269 { 270 for (int i=0; i<bridgeSubscribers.size (); i++) 271 { 272 BridgeInvalidationSubscriptionImpl bridge = (BridgeInvalidationSubscriptionImpl)(bridgeSubscribers.elementAt (i)); 273 if (bridge != exceptSource) 274 bridge.bridgedInvalidateAll (groupName, this.DEFAULT_TO_ASYNCHRONOUS_MODE); 275 } 276 } 277 278 protected void localGroupInvalidationEvent (String groupName, Serializable key, boolean asynchronous) 283 { 284 for (int i=0; i<bridgeSubscribers.size (); i++) 285 ((BridgeInvalidationSubscriptionImpl)(bridgeSubscribers.elementAt (i))).bridgedInvalidate (groupName, key, asynchronous); 286 } 287 288 protected void localGroupInvalidationsEvent (String groupName, Serializable [] keys, boolean asynchronous) 289 { 290 for (int i=0; i<bridgeSubscribers.size (); i++) 291 ((BridgeInvalidationSubscriptionImpl)(bridgeSubscribers.elementAt (i))).bridgedInvalidate (groupName, keys, asynchronous); 292 } 293 294 protected void localGroupInvalidateAllEvent (String groupName, boolean asynchronous) 295 { 296 for (int i=0; i<bridgeSubscribers.size (); i++) 297 ((BridgeInvalidationSubscriptionImpl)(bridgeSubscribers.elementAt (i))).bridgedInvalidateAll (groupName, asynchronous); 298 } 299 300 protected void bridgeGroupInvalidationEvent (BridgeInvalidationSubscriptionImpl source, String groupName, Serializable key) 303 { 304 doBridgedOnlyInvalidation (source, groupName, key); 305 doLocalOnlyInvalidation (groupName, key, this.DEFAULT_TO_ASYNCHRONOUS_MODE); 306 } 307 308 protected void bridgeGroupInvalidationEvent (BridgeInvalidationSubscriptionImpl source, String groupName, Serializable [] keys) 309 { 310 doBridgedOnlyInvalidation (source, groupName, keys); 311 doLocalOnlyInvalidation (groupName, keys, this.DEFAULT_TO_ASYNCHRONOUS_MODE); 312 } 313 314 protected void bridgeGroupInvalidateAllEvent (BridgeInvalidationSubscriptionImpl source, String groupName) 315 { 316 doBridgedOnlyInvalidateAll (source, groupName); 317 doLocalOnlyInvalidateAll (groupName, this.DEFAULT_TO_ASYNCHRONOUS_MODE); 318 } 319 320 protected void crossDomainBatchInvalidate (BridgeInvalidationSubscriptionImpl source, BatchInvalidation[] invalidations, boolean asynchronous) 321 { 322 if (invalidations == null) 323 return; 324 325 for (int i=0; i<invalidations.length; i++) 328 { 329 BatchInvalidation currInvalid = invalidations[i]; 330 331 doLocalOnlyInvalidations (currInvalid.getInvalidationGroupName (), 332 currInvalid.getIds (), 333 asynchronous); 334 } 335 336 for (int i=0; i<bridgeSubscribers.size (); i++) 339 { 340 BridgeInvalidationSubscriptionImpl bridge = (BridgeInvalidationSubscriptionImpl)(bridgeSubscribers.elementAt (i)); 341 if (bridge != source) 342 bridge.bridgedBatchInvalidations (invalidations, asynchronous); 343 } 344 } 345 346 protected void crossDomainInvalidateAll(BridgeInvalidationSubscriptionImpl source, String groupName, boolean asynchronous) 347 { 348 doLocalOnlyInvalidateAll(groupName, asynchronous); 351 352 for (int i=0; i<bridgeSubscribers.size (); i++) 355 { 356 BridgeInvalidationSubscriptionImpl bridge = (BridgeInvalidationSubscriptionImpl)(bridgeSubscribers.elementAt (i)); 357 if (bridge != source) 358 bridge.bridgedInvalidateAll(groupName, asynchronous); 359 } 360 } 361 362 364 366 370 class InvalidationGroupImpl implements InvalidationGroup, javax.management.DynamicMBean 371 { 372 protected org.jboss.logging.Logger igLog = null; 373 protected String groupName = null; 374 protected boolean asynchronous = DEFAULT_TO_ASYNCHRONOUS_MODE; 375 protected HashSet registered = new HashSet (); 376 protected int counter = 0; 377 378 public int hashCode () 379 { 380 return groupName.hashCode (); 381 } 382 383 public String getGroupName () 384 { 385 return this.groupName; 386 } 387 388 public InvalidationGroupImpl (String groupName) 389 { 390 this.groupName = groupName; 391 this.igLog = org.jboss.logging.Logger.getLogger(getClass() + "." + groupName); 392 } 393 394 public InvalidationManagerMBean getInvalidationManager () 395 { 396 return InvalidationManager.this; 397 } 398 399 public void invalidate (Serializable key) 400 { 401 this.invalidate (key, this.asynchronous); 402 } 403 404 public void invalidate (Serializable key, boolean asynchronous) 405 { 406 localOnlyInvalidate (key, asynchronous); 407 408 localGroupInvalidationEvent (this.groupName, key, asynchronous); 409 } 410 411 public void invalidate (Serializable [] keys) 412 { 413 this.invalidate (keys, this.asynchronous); 414 } 415 416 public void invalidate (Serializable [] keys, boolean asynchronous) 417 { 418 localOnlyInvalidate (keys, asynchronous); 419 420 localGroupInvalidationsEvent (this.groupName, keys, asynchronous); 421 } 422 423 public void invalidateAll() 424 { 425 invalidateAll(asynchronous); 426 } 427 428 public void invalidateAll(boolean asynchronous) 429 { 430 localOnlyInvalidateAll(); 431 localGroupInvalidateAllEvent(groupName, asynchronous); 432 } 433 434 public synchronized void register (Invalidatable newRegistered) 435 { 436 HashSet newlyRegistered = new HashSet (this.registered); 439 newlyRegistered.add (newRegistered); 440 441 this.registered = newlyRegistered; 442 } 443 444 public synchronized void unregister (Invalidatable oldRegistered) 445 { 446 HashSet newlyRegistered = new HashSet (this.registered); 449 newlyRegistered.remove (oldRegistered); 450 451 this.registered = newlyRegistered; 452 453 this.removeReference (); 454 } 455 456 public void setAsynchronousInvalidation (boolean async) 457 { 458 this.asynchronous = async; 459 } 460 461 public boolean getAsynchronousInvalidation () 462 { 463 return this.asynchronous; 464 } 465 466 public void addReference () 467 { 468 counter++; 469 igLog.debug ("Counter reference value (++): " + counter); 470 } 471 472 public int getReferenceCount () 473 { 474 return this.counter; 475 } 476 477 public void removeReference () 478 { 479 counter--; 480 igLog.debug ("Counter reference value (--): " + counter); 481 482 if (counter<=0) 483 { 484 removeGroup (this.groupName); 485 486 } 490 } 491 492 494 public Object getAttribute (String attribute) throws javax.management.AttributeNotFoundException , javax.management.MBeanException , javax.management.ReflectionException 495 { 496 if (attribute == null || attribute.equals ("")) 497 throw new IllegalArgumentException ("null or empty attribute name"); 498 499 if (attribute.equals ("AsynchronousInvalidation")) 500 return new Boolean (this.asynchronous); 501 else 502 throw new javax.management.AttributeNotFoundException (attribute + " is not a known attribute"); 503 } 504 505 public javax.management.AttributeList getAttributes (java.lang.String [] attributes) 506 { 507 return null; 508 } 509 510 public javax.management.MBeanInfo getMBeanInfo () 511 { 512 513 MBeanParameterInfo serSimpleParam = new MBeanParameterInfo ( 514 "key", 515 Serializable .class.getName (), 516 "Primary key to be invalidated" 517 ); 518 519 MBeanParameterInfo serArrayParam = new MBeanParameterInfo ( 520 "keys", 521 Serializable [].class .getName (), 522 "Primary keys to be invalidated" 523 ); 524 525 MBeanParameterInfo asynchParam = new MBeanParameterInfo ( 526 "asynchronous", 527 Boolean .class.getName (), 528 "Indicates if the invalidation should be asynchronous or must be synchronous" 529 ); 530 531 javax.management.MBeanAttributeInfo [] attrInfo = new javax.management.MBeanAttributeInfo [] { 532 new javax.management.MBeanAttributeInfo ("AsynchronousInvalidation", 533 Boolean .class.getName(), 534 "Indicates if invalidation, by default, should be done asynchronously", 535 true, 536 true, 537 false)}; 538 539 MBeanOperationInfo [] opInfo = { 540 new MBeanOperationInfo ("invalidate", 541 "invalidate a single key using default (a)synchronous behaviour", 542 new MBeanParameterInfo [] {serSimpleParam}, 543 void.class.getName(), 544 MBeanOperationInfo.ACTION), 545 546 new MBeanOperationInfo ("invalidate", 547 "invalidate a single key indicating the (a)synchronous behaviour", 548 new MBeanParameterInfo [] {serSimpleParam, asynchParam}, 549 void.class.getName(), 550 MBeanOperationInfo.ACTION), 551 552 new MBeanOperationInfo ("invalidate", 553 "invalidate multiple keys using default (a)synchronous behaviour", 554 new MBeanParameterInfo [] {serArrayParam}, 555 void.class.getName(), 556 MBeanOperationInfo.ACTION), 557 558 new MBeanOperationInfo ("invalidate", 559 "invalidate multiple keys indicating the (a)synchronous behaviour", 560 new MBeanParameterInfo [] {serArrayParam, asynchParam}, 561 void.class.getName(), 562 MBeanOperationInfo.ACTION), 563 564 new MBeanOperationInfo ("invalidateAll", 565 "invalidate all keys using default (a)synchronous behaviour", 566 new MBeanParameterInfo [] {}, 567 void.class.getName(), 568 MBeanOperationInfo.ACTION), 569 570 new MBeanOperationInfo ("invalidateAll", 571 "invalidate all keys with specified (a)synchronous behaviour", 572 new MBeanParameterInfo [] {asynchParam}, 573 void.class.getName(), 574 MBeanOperationInfo.ACTION) 575 }; 576 577 javax.management.MBeanNotificationInfo [] notifyInfo = null; 578 javax.management.MBeanConstructorInfo [] ctorInfo = new javax.management.MBeanConstructorInfo [] {}; 579 580 return new javax.management.MBeanInfo (getClass().getName(), 581 "Cache invalidation for group named " + this.groupName, 582 attrInfo, 583 ctorInfo, 584 opInfo, 585 notifyInfo); 586 } 587 588 public java.lang.Object invoke (java.lang.String actionName, java.lang.Object [] params, java.lang.String [] signature) throws javax.management.MBeanException , javax.management.ReflectionException 589 { 590 if ("invalidate".equals (actionName)) 591 { 592 if (params.length == 1) 593 { 594 if (params[0] instanceof Serializable []) 595 this.invalidate ((Serializable [])params[0]); 596 else if (params[0] instanceof Serializable ) 597 this.invalidate ((Serializable )params[0]); 598 else 599 throw new IllegalArgumentException ("First argument must be Serializable (or array of)"); 600 } 601 else if (params.length == 2) 602 { 603 if (params[0] instanceof Serializable []) 604 this.invalidate ((Serializable [])params[0], ((Boolean )params[1]).booleanValue ()); 605 else if (params[0] instanceof Serializable ) 606 this.invalidate ((Serializable )params[0], ((Boolean )params[1]).booleanValue ()); 607 else 608 throw new IllegalArgumentException ("First argument must be Serializable (or array of)"); 609 } 610 else 611 { 612 throw new IllegalArgumentException ("Unknown operation with these parameters: " + actionName); 613 } 614 } 615 else if("invalidateAll".equals(actionName)) 616 { 617 if(params == null || params.length == 0) 618 { 619 this.invalidateAll(); 620 } 621 else if (params.length == 1) 622 { 623 this.invalidateAll (((Boolean )params[1]).booleanValue ()); 624 } 625 else 626 { 627 throw new IllegalArgumentException ("invalidateAll can take zero or one parameter but got " + params.length); 628 } 629 } 630 else 631 { 632 throw new IllegalArgumentException ("Unknown operation: " + actionName); 633 } 634 return null; 635 } 636 637 public void setAttribute (javax.management.Attribute attribute) throws javax.management.AttributeNotFoundException , javax.management.InvalidAttributeValueException , javax.management.MBeanException , javax.management.ReflectionException 638 { 639 String attrName = attribute.getName(); 640 if (attrName == null || attrName.equals ("")) 641 throw new IllegalArgumentException ("null or empty attribute name"); 642 643 if (attrName.equals ("AsynchronousInvalidation")) 644 { 645 Object value = attribute.getValue (); 646 if (value instanceof Boolean ) 647 this.asynchronous = ((Boolean )value).booleanValue (); 648 else 649 throw new javax.management.InvalidAttributeValueException ("Attribute is of boolean type"); 650 } 651 else 652 throw new javax.management.AttributeNotFoundException (attrName + " is not a known attribute"); 653 } 654 655 public javax.management.AttributeList setAttributes (javax.management.AttributeList attributes) 656 { 657 return null; 658 } 659 660 662 protected void localOnlyInvalidate (Serializable [] keys, boolean asynchronous) 663 { 664 java.util.Iterator iter = this.registered.iterator (); 665 while (iter.hasNext ()) 666 { 667 Invalidatable inv = (Invalidatable)iter.next (); 668 inv.areInvalid (keys); 669 } 670 } 671 672 protected void localOnlyInvalidate (Serializable key, boolean asynchronous) 673 { 674 java.util.Iterator iter = this.registered.iterator (); 675 while (iter.hasNext ()) 676 { 677 Invalidatable inv = (Invalidatable)iter.next (); 678 inv.isInvalid (key); 679 } 680 681 } 682 683 protected void localOnlyInvalidateAll() 684 { 685 java.util.Iterator iter = this.registered.iterator (); 686 while (iter.hasNext ()) 687 { 688 Invalidatable inv = (Invalidatable)iter.next (); 689 inv.invalidateAll(); 690 } 691 } 692 } 693 694 698 class BridgeInvalidationSubscriptionImpl 699 implements BridgeInvalidationSubscription 700 { 701 702 protected InvalidationBridgeListener listener = null; 703 704 public BridgeInvalidationSubscriptionImpl (InvalidationBridgeListener listener) 705 { 706 this.listener = listener; 707 } 708 709 public void invalidate (String invalidationGroupName, Serializable key) 710 { 711 bridgeGroupInvalidationEvent (this, invalidationGroupName, key); 712 } 713 714 public void invalidate (String invalidationGroupName, Serializable [] keys) 715 { 716 bridgeGroupInvalidationEvent (this, invalidationGroupName, keys); 717 } 718 719 public void invalidateAll(String groupName) 720 { 721 bridgeGroupInvalidateAllEvent(this, groupName); 722 } 723 724 public void batchInvalidate (BatchInvalidation[] invalidations) 725 { 726 crossDomainBatchInvalidate (this, invalidations, DEFAULT_TO_ASYNCHRONOUS_MODE); 727 728 } 729 730 public void unregister () 731 { 732 unregisterBridgeListener (this); 733 } 734 735 738 protected void bridgedInvalidate (String invalidationGroupName, Serializable key, boolean asynchronous) 739 { 740 this.listener.invalidate (invalidationGroupName, key, asynchronous); 741 } 742 743 protected void bridgedInvalidate (String invalidationGroupName, Serializable [] keys, boolean asynchronous) 744 { 745 this.listener.invalidate (invalidationGroupName, keys, asynchronous); 746 } 747 748 protected void bridgedInvalidateAll (String invalidationGroupName, boolean asynchronous) 749 { 750 this.listener.invalidateAll (invalidationGroupName, asynchronous); 751 } 752 753 protected void bridgedBatchInvalidations (BatchInvalidation[] invalidations, boolean asynchronous) 754 { 755 this.listener.batchInvalidate (invalidations, asynchronous); 756 } 757 758 protected void groupCreated (String invalidationGroupName) 759 { 760 this.listener.newGroupCreated (invalidationGroupName); 761 } 762 763 protected void groupDropped (String invalidationGroupName) 764 { 765 this.listener.groupIsDropped (invalidationGroupName); 766 } 767 768 } 769 } 770 | Popular Tags |