[Design of Messaging on JBoss (Messaging/JBoss)] - Failover refactoring
by ovidiu.feodorov@jboss.com
1. The clustering/failover support has been refactored as follows:
There is a new PER_INSTANCE ClusteringAspect part of ClusteredConnectionFactory's stack, which encapsulates load balancing and failover node picking policies. Each client-side delegate is guarded by a PER_INSTANCE FailoverValveInterceptor instance. The valve is normally open. On failover, all valves under a connection are closed recursively. If there are active threads through valve on closing, the current behavior is that closeValve() waits until all active threads unwrap (I could change this if necessary). Once the valve is closed, no threads are allowed through it until is explicitly opened again. The client-side failover event (which includes operating the valves, among other things) is detected and controlled by PER_VM FailoverAspect.
2. ClientClusteredConnectionFactoryDelegate doesn't extend ClientConnectionFactoryDelegate anymore. Also, I introduced two distinct aspect stacks corresponding to clustered ConnectionFactories and non-clustered ConnectionFactories.
3. One can register a FailoverListener to a JBossConnection and so to be notified when a failover starts and ends. So far, known events are FAILURE_DETECTED, FAILOVER_STARTED, FAILOVER_COMPLETED, FAILOVER_FAILED.
4. The initialization of the AOP stack is done by a specialized component (ClientAOPStackLoader). Both ConnectionDelegate and ClusteredConnectionDelegate delegate to it. getAOPStackConfig() is not part of the ConnectionFactory interface anymore.
Some tests fail, but I will follow up on that soon.
I added a boatload of failover mop-up tasks, grouped under http://jira.jboss.org/jira/browse/JBMESSAGING-706
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3997042#3997042
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3997042
18 years
[Design of Messaging on JBoss (Messaging/JBoss)] - Expiring/DLQ same message from multiple subscriptions
by timfox
If I send a message to a topic, and it ends up being delivered to n subscriptions on that topic, then the message expires, should the message be added to the expiry queue n times, one for each subscription, or only once?
A more complex but related situation is for messages that have exceeded max delivery attempts.
If a message is sent to a topic with n subscriptions. Then depending on how many times the client calls recover() or rollback() for one or more of the subscriptions, then the message could have exceeded max delivery attempts for some of the subscriptions but not with others.
So the message needs to be added to the DLQ for some of the subscriptions, but not for others - how does this effect the subscriptions who have not exceeded max delivery attempts.
Can we end up with a situation where the same message (same message id) is in the queue (dlq or expiry queue) multiple times? Would we get primary key violations in the database?
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3997033#3997033
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3997033
18 years
[Design of AOP on JBoss (Aspects/JBoss)] - Array interception needed for jboss cache
by kabir.khan@jboss.com
I have commited an initial prototype of the array interception needed for POJO Cache. It is available in svn in a separate branch:
| $ svn co https://svn.jboss.org/repos/jbossas/projects/aop/branches/arrays/ jboss-aop-arrays
| $ cd jboss-aop-arrays/build
| $ build.sh
| $ cd ../aop
| $ build.sh -f build-tests-jdk50.xml
| $ build.sh -f build-tests-jdk50.xml loadtime-ga-test -Dtest=array
|
The test files are in jboss-aop-arrays\aop\src\test\org\jboss\test\aop\array and configured in jboss-aop-arrays\aop\src\resources\test\array. The invocations and things needed for the array interceptions are in jboss-aop-arrays\aop\src\main\org\jboss\aop\array.
I will merge this code to trunk, once the POJO cache guys approve.
Brief details of how it works follow:
It was too hard (impossible?) to figure out who the owning object of the array is from the bytecode, since as far as the VM is concerned, the target for the Xastore and Xaload jvm instructions is the array itself. This is different from what happens when you read/write a field directly, since the putfield and getfield instructions take the object containing the fields as the target object.
So what we do now is replace ALL array access within classes caught by arrayreplacement expressions
jboss-aop.xml
| <aop>
| <arrayreplacement class="POJO"/>
| <arrayreplacement expr="class(@ReplaceArrayAccess)"/>
| </aop>
|
so that the follwing
| arr[5] = 100;
| int i = arr[5]
|
becomes
| ArrayAdvisor.arrayWriteInt(arr, 5, 100);
| int i = ArrayAdvisor.arrayReadInt(arr, 5);
|
To determine if an array should be intercepted, if a field
1) is woven from a field() expression
and
2) is captured by an arrayreplacement expression
and
3) Is of type array or Object (since that can hold an array)
then we extend the existing hooks for the field write to register the array with an "ArrayRegistry" if the new value is an array.
| class POJO{
| int[] array = new array[]{1,2,3};
| Object couldBeAnArray = 10;
| int[] notadvised = new array[]{1,2,3};
| int x;
| }
| <aop>
| <arrayreplacement class="POJO"/>
| <prepare pointcut="field(* POJO->array)"/>
| <prepare pointcut="field(* POJO->couldBeAnArray)"/>
| </aop>
|
| POJO pojo = new POJO();
|
In the above example only POJO.array gets registered with the ArrayRegistry. If we now do:
| pojo.couldBeAnArray = new int[]{1,2,3};
|
pojo.couldBeAnArray gets registered in the ArrayRegistry.
If the ArrayAdvisor.arrayWriteXXX() and arrayReadXXX() methods does not find the passed in array in the ArrayRegistry, it simply updates/reads the array. If the passed in array is in the ArrayRegistry, and we have interceptors defined for arrays, we create an ArrayElementReadInvocation or an ArrayElementWriteInvocation (actually a subclass depending on the type of array) and invoke on that.
Since the "target" for an array access is the array itself, the array is the TargetObject in the XXXArrayElementXXXInvocation classes. We only allow PER_VM scoped interceptors to be used for arrays, and interceptors set up apply to ALL registered arrays. They are defined using the arraybind keyword:
| <aop>
| <interceptor class="ArrayAccessInterceptor"/>
| <arrayreplacement class="POJO"/>
| <prepare pointcut="field(* POJO->array)"/>
| <prepare pointcut="field(* POJO->couldBeAnArray)"/>
| <arraybind>
| <interceptor-ref name="ArrayAccessInterceptor"/>
| </arraybind>
| </aop>
|
I will also introduce some arrayread and arraywrite keywords, so we can differentiate whether an element is being read or written (arraybind intercepts both reads and writes).
The method ArrayRegistry.getArrayOwners(Object array), which is also accessible from ArrayElementInvocation.getArrayOwners(), allows you to get hold of all references to the array. it is returned as a list of org.jboss.aop.array.ArrayReference objects, each of which contains information about one reference to the array. It gives you access to the object containing the reference, the field this reference is stored in, and if the field is an array containing the target array within one of its elements a list of the indexes from the top of the field to get to the array.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3996995#3996995
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3996995
18 years