You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by fh...@apache.org on 2006/05/23 16:48:11 UTC
svn commit: r408912 - in /tomcat/container/tc5.5.x/modules/groupcom: ./
build/ doc/ src/share/org/apache/catalina/tribes/group/interceptors/
src/share/org/apache/catalina/tribes/membership/
Author: fhanik
Date: Tue May 23 07:48:10 2006
New Revision: 408912
URL: http://svn.apache.org/viewvc?rev=408912&view=rev
Log:
Updated notes about the leader election algorithm, we are no longer using Hans Svensson's algorithm as that algorithm assumes membership visibility. Instead we are using a merging algorithm that makes other members visible.
Added:
tomcat/container/tc5.5.x/modules/groupcom/doc/leader-election-initiate-election.dia (with props)
tomcat/container/tc5.5.x/modules/groupcom/doc/leader-election-initiate-election.jpg (with props)
tomcat/container/tc5.5.x/modules/groupcom/doc/leader-election-message-arrives.dia (with props)
tomcat/container/tc5.5.x/modules/groupcom/doc/leader-election-message-arrives.jpg (with props)
Modified:
tomcat/container/tc5.5.x/modules/groupcom/VERSION
tomcat/container/tc5.5.x/modules/groupcom/build/build.xml
tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/tribes/group/interceptors/NonBlockingCoordinator.java
tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/tribes/membership/Membership.java
Modified: tomcat/container/tc5.5.x/modules/groupcom/VERSION
URL: http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/modules/groupcom/VERSION?rev=408912&r1=408911&r2=408912&view=diff
==============================================================================
--- tomcat/container/tc5.5.x/modules/groupcom/VERSION (original)
+++ tomcat/container/tc5.5.x/modules/groupcom/VERSION Tue May 23 07:48:10 2006
@@ -1,3 +1,5 @@
+0.0.2.4
+ - leader election, work in progress
0.9.2.3
- Keep alive pings for AbstractReplicatedMap
- Improved TcpFailureDetector
Modified: tomcat/container/tc5.5.x/modules/groupcom/build/build.xml
URL: http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/modules/groupcom/build/build.xml?rev=408912&r1=408911&r2=408912&view=diff
==============================================================================
--- tomcat/container/tc5.5.x/modules/groupcom/build/build.xml (original)
+++ tomcat/container/tc5.5.x/modules/groupcom/build/build.xml Tue May 23 07:48:10 2006
@@ -110,6 +110,9 @@
includes="*.xml">
<param name="relative-path" expression="."/>
</style>
+ <copy todir="${docs.path}">
+ <fileset dir="${basedir}/doc"/>
+ </copy>
</target>
<target name="javadoc">
Added: tomcat/container/tc5.5.x/modules/groupcom/doc/leader-election-initiate-election.dia
URL: http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/modules/groupcom/doc/leader-election-initiate-election.dia?rev=408912&view=auto
==============================================================================
Binary file - no diff available.
Propchange: tomcat/container/tc5.5.x/modules/groupcom/doc/leader-election-initiate-election.dia
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: tomcat/container/tc5.5.x/modules/groupcom/doc/leader-election-initiate-election.jpg
URL: http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/modules/groupcom/doc/leader-election-initiate-election.jpg?rev=408912&view=auto
==============================================================================
Binary file - no diff available.
Propchange: tomcat/container/tc5.5.x/modules/groupcom/doc/leader-election-initiate-election.jpg
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: tomcat/container/tc5.5.x/modules/groupcom/doc/leader-election-message-arrives.dia
URL: http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/modules/groupcom/doc/leader-election-message-arrives.dia?rev=408912&view=auto
==============================================================================
Binary file - no diff available.
Propchange: tomcat/container/tc5.5.x/modules/groupcom/doc/leader-election-message-arrives.dia
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: tomcat/container/tc5.5.x/modules/groupcom/doc/leader-election-message-arrives.jpg
URL: http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/modules/groupcom/doc/leader-election-message-arrives.jpg?rev=408912&view=auto
==============================================================================
Binary file - no diff available.
Propchange: tomcat/container/tc5.5.x/modules/groupcom/doc/leader-election-message-arrives.jpg
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Modified: tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/tribes/group/interceptors/NonBlockingCoordinator.java
URL: http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/tribes/group/interceptors/NonBlockingCoordinator.java?rev=408912&r1=408911&r2=408912&view=diff
==============================================================================
--- tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/tribes/group/interceptors/NonBlockingCoordinator.java (original)
+++ tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/tribes/group/interceptors/NonBlockingCoordinator.java Tue May 23 07:48:10 2006
@@ -28,6 +28,8 @@
import org.apache.catalina.tribes.util.Arrays;
import org.apache.catalina.tribes.io.ChannelData;
import org.apache.catalina.tribes.Channel;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
/**
* <p>Title: NonBlockingCoordinator</p>
@@ -86,20 +88,17 @@
* <p>
* Lets assume that C1 arrives, C1 has lower priority than C, but higher priority than D.<br>
* Lets also assume that C1 sees the following view {B,D,E}<br>
- * C1 sends Z{B-ldr, C-src, mbrs-B,C1,D,E} to D<br>
- * D receives Z{B-ldr, C-src, mbrs-B,C1,D,E} sends Z{A-ldr, D-src, mbrs-A,B,C,C1,D,E} to E<br>
- * Once the message reaches A, A will issue a new view and send a new message<br>
- * A view is not accepted by a member unless ldr==src in the token.<br>
- * </p>
- * <p>
- * Lets assume that A0 arrives A0 being higher than A.<br>
- * Lets also assume that A0 sees view {B,D,E}<br>
- * A0 will issue a similar view statement and the same scenario as above will happen.<br>
- * If A0 sees {A,B,C,D} it simply sends the message to A rather than B.
+ * C1 waits for a token to arrive. When the token arrives, the same scenario as above will happen.<br>
+ * In the scenario where C1 sees {D,E} and A,B,C can not see C1, no token will ever arrive.<br>
+ * In this case, C1 sends a Z{C1-ldr, C1-src, mbrs-C1,D,E} to D<br>
+ * D receives Z{C1-ldr, C1-src, mbrs-C1,D,E} and sends Z{A-ldr, C1-src, mbrs-A,B,C,C1,D,E} to E<br>
+ * E receives Z{A-ldr, C1-src, mbrs-A,B,C,C1,D,E} and sends it to A<br>
+ * A sends Z{A-ldr, A-src, mbrs-A,B,C,C1,D,E} to B and the chain continues until A receives the token again.
+ * At that time A optionally sends out Z{A-ldr, A-src, mbrs-A,B,C,C1,D,E, confirmed} to A,B,C,C1,D,E
* </p>
* <p>If we wanted to ensure that the view gets implemented at all nodes at the same time,
* ie, implementing a blocking coordinator, we would simply require that each view, before it gets installed
- * has to receive a VIEW_CONF message.
+ * has to receive a VIEW_CONF message, this is the 'confirmed' message that is optional above.
*
* <p>Ideally, the interceptor below this one would be the TcpFailureDetector to ensure correct memberships</p>
*
@@ -107,6 +106,9 @@
* But I suck at writing state machines, my head gets all confused. One day I will document this algorithm though.<br>
* Maybe I'll do a state diagram :)
* </p>
+ * <h2>State Diagrams</h2>
+ * <a href="http://people.apache.org/~fhanik/tribes/docs/leader-election-initiate-election.jpg">Initiate an election</a><br><br>
+ * <a href="http://people.apache.org/~fhanik/tribes/docs/leader-election-message-arrives.jpg">Receive an election message</a><br><br>
*
* @author Filip Hanik
* @version 1.0
@@ -129,19 +131,32 @@
*/
protected static final byte[] COORD_CONF = new byte[] {67, 88, 107, -86, 69, 23, 76, -70, -91, -23, -87, -25, -125, 86, 75, 20};
- protected Member coordinator = null;
-
+ /**
+ * Our current view
+ */
protected Membership view = null;
- protected Membership suggestedview = null;
-
+ /**
+ * Out current viewId
+ */
protected UniqueId viewId;
+
+ /**
+ * Our nonblocking membership
+ */
+ protected Membership membership = null;
+
+ /**
+ * indicates that we are running an election
+ * and this is the one we are running
+ */
protected UniqueId suggestedviewId;
+ protected LinkedHashMap rotatingViews = new LinkedHashMap();
+
protected boolean started = false;
protected final int startsvc = 0xFFFF;
protected Object electionMutex = new Object();
- protected boolean runningElection = false;
public NonBlockingCoordinator() {
super();
@@ -159,7 +174,6 @@
}
//coordination can happen before this line of code executes
Member local = getLocalMember(false);
- if (local != null && coordinator == null) coordinator = local;
}
public void stop(int svc) throws ChannelException {
@@ -171,7 +185,10 @@
}finally {
release();
}
- this.coordinator = null;
+ }
+
+ public Membership getView(UniqueId id) {
+ return (Membership)rotatingViews.get(id);
}
public void elect() {
@@ -185,8 +202,11 @@
//I'm not the higest, exit
if ( !local.equals(mbrs[0]) ) return;
//I'm already running an election
- if ( suggestedview.hasMembers() ) return;
+ if ( suggestedviewId != null ) return;
//create a suggestedview
+ suggestedviewId = new UniqueId(UUIDGenerator.randomUUID(true));
+ Membership suggestedview = new Membership((MemberImpl)local,AbsoluteOrder.comp);
+ rotatingViews.put(suggestedviewId,suggestedview);
suggestedview.addMember((MemberImpl)local);
Arrays.fill(suggestedview,mbrs);
suggestedviewId = new UniqueId(UUIDGenerator.randomUUID(true));
@@ -218,6 +238,7 @@
//we are running our own election
if (suggestedviewId.equals(msg.getId())) {
//we received our own token
+ Membership suggestedview = getView(msg.getId());
Member[] suggested = suggestedview.getMembers();
Member[] received = msg.getMembers();
if (Arrays.sameMembers(suggested,received) ) {
@@ -225,6 +246,7 @@
view = suggestedview;
viewId = suggestedviewId;
suggestedviewId = null;
+ rotatingViews.remove(viewId);
suggestedview.reset();
viewChange(viewId,view.getMembers());
release();
@@ -253,9 +275,12 @@
}
-
+ /**
+ * Returns coordinator if one is available
+ * @return Member
+ */
public Member getCoordinator() {
- return coordinator;
+ return (view != null && view.hasMembers()) ? view.getMembers()[0] : null;
}
public void sendMessage(Member[] destination, ChannelMessage msg, InterceptorPayload payload) throws ChannelException {
@@ -277,11 +302,13 @@
public void memberAdded(Member member) {
try {
+ if ( membership == null ) setupMembership();
+ if ( membership.memberAlive((MemberImpl)member) ) super.memberAdded(member);
halt();
}finally {
release();
}
- super.memberAdded(member);
+
}
public void memberDisappeared(Member member) {
@@ -302,8 +329,8 @@
* has members
*/
public boolean hasMembers() {
- if ( view == null ) setupMembership();
- return view.hasMembers();
+ if ( membership == null ) setupMembership();
+ return membership.hasMembers();
}
/**
@@ -311,9 +338,8 @@
* @return all members or empty array
*/
public Member[] getMembers() {
- if ( view == null ) setupMembership();
- Member[] members = view.getMembers();
- return members;
+ if ( membership == null ) setupMembership();
+ throw new UnsupportedOperationException("Not yet implemented");
}
/**
@@ -322,8 +348,8 @@
* @return Member
*/
public Member getMember(Member mbr) {
- if ( view == null ) setupMembership();
- return view.getMember(mbr);
+ if ( membership == null ) setupMembership();
+ throw new UnsupportedOperationException("Not yet implemented");
}
/**
@@ -338,9 +364,9 @@
}
protected synchronized void setupMembership() {
- if ( view == null || suggestedview == null ) {
- view = new Membership((MemberImpl)super.getLocalMember(true));
- suggestedview = new Membership((MemberImpl)super.getLocalMember(true));
+ if ( view == null || membership == null ) {
+ view = new Membership((MemberImpl)super.getLocalMember(true),AbsoluteOrder.comp);
+ membership = new Membership((MemberImpl)super.getLocalMember(true),AbsoluteOrder.comp);
}
}
@@ -373,6 +399,7 @@
protected MemberImpl[] view;
protected UniqueId id;
protected byte[] type;
+ protected long timestamp = System.currentTimeMillis();
public CoordinationMessage(XByteBuffer buf) {
this.buf = buf;
Modified: tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/tribes/membership/Membership.java
URL: http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/tribes/membership/Membership.java?rev=408912&r1=408911&r2=408912&view=diff
==============================================================================
--- tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/tribes/membership/Membership.java (original)
+++ tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/tribes/membership/Membership.java Tue May 23 07:48:10 2006
@@ -24,6 +24,7 @@
import java.util.Map;
import org.apache.catalina.tribes.Member;
+import java.util.Comparator;
/**
* A <b>membership</b> implementation using simple multicast.
@@ -58,7 +59,7 @@
/**
* sort members by alive time
*/
- protected MemberComparator memberComparator = new MemberComparator();
+ protected Comparator memberComparator = new MemberComparator();
/**
* Constructs a new membership
@@ -66,6 +67,11 @@
*/
public Membership(MemberImpl local) {
this.local = local;
+ }
+
+ public Membership(MemberImpl local, Comparator comp) {
+ this(local);
+ this.memberComparator = comp;
}
/**
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org