KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > sapia > ubik > rmi > replication > ReplicatedCommand


1 package org.sapia.ubik.rmi.replication;
2
3 import org.sapia.ubik.net.ServerAddress;
4 import org.sapia.ubik.rmi.server.Hub;
5 import org.sapia.ubik.rmi.server.invocation.InvokeCommand;
6
7 import java.io.IOException JavaDoc;
8 import java.io.ObjectInput JavaDoc;
9 import java.io.ObjectOutput JavaDoc;
10
11 import java.rmi.RemoteException JavaDoc;
12
13 import java.util.HashSet JavaDoc;
14 import java.util.Set JavaDoc;
15
16
17 /**
18  * Wraps an <code>InvokeCommand</code> that is intented to be replicated to the different
19  * servers in a domain or cluster.
20  *
21  * @see #getReplicationContext()
22  *
23  * @author Yanick Duchesne
24  * <dl>
25  * <dt><b>Copyright:</b><dd>Copyright &#169; 2002-2004 <a HREF="http://www.sapia-oss.org">Sapia Open Source Software</a>. All Rights Reserved.</dd></dt>
26  * <dt><b>License:</b><dd>Read the license.txt file of the jar or visit the
27  * <a HREF="http://www.sapia-oss.org/license.html">license page</a> at the Sapia OSS web site</dd></dt>
28  * </dl>
29  */

30 public abstract class ReplicatedCommand extends InvokeCommand {
31   private Set JavaDoc _visited = new HashSet JavaDoc();
32   private Set JavaDoc _targets;
33   private ReplicatedInvoker _invoker;
34   private boolean _executed;
35   private boolean _synchronous;
36   private boolean _disabled;
37
38   /** Do not call; used for externalization only. */
39   public ReplicatedCommand() {
40   }
41
42   /**
43    * @param cmd the <code>InvokeCommand</code> to replicate.
44    * @param targets the <code>Set</code> of <code>ServerAddress</code>es that are
45    * targeted by the command. If <code>null</code>, then all siblings will be targeted.
46    * @param invoker the <code>ReplicatedInvoker</code> implementation in charge of
47    * performing replicated method invocations.
48    */

49   public ReplicatedCommand(InvokeCommand cmd, Set JavaDoc targets,
50     ReplicatedInvoker invoker, boolean synchronous) {
51     super(cmd.getOID(), cmd.getMethodName(), cmd.getParams(),
52       cmd.getParameterTypes(), null);
53     _targets = targets;
54     _invoker = invoker;
55     _synchronous = synchronous;
56   }
57
58   /**
59    * This method's implementation internally calls the <code>getReplicationContext()</code>
60    * method. The returned <code>ReplicationContext</code> is used as a hook to the server
61    * in which this command is executed. Internally, the method selects the next server
62    * to which this instance should be dispatched, and executes the command that this
63    * instance wraps.
64    * </p>
65    * If the execution is successful, this instance is dispatched by means of the
66    * <code>ReplicationContext</code>.
67    *
68    * @see #getReplicationContext()
69    *
70    * @see org.sapia.ubik.rmi.server.RMICommand#execute()
71    */

72   public Object JavaDoc execute() throws Throwable JavaDoc {
73     if (_disabled) {
74       return super.execute();
75     }
76
77     Object JavaDoc toReturn;
78     Hub.serverRuntime.dispatchEvent(new ReplicationEvent(this));
79
80     Set JavaDoc siblings = _invoker.getSiblings();
81     ReplicationStrategy strat = new ReplicationStrategy(_visited, _targets,
82         siblings);
83     ServerAddress addr;
84     ServerAddress current = getServerAddress();
85
86     if (_executed) {
87       convertParams(_invoker.getClass().getClassLoader());
88       toReturn = _invoker.invoke(super.getMethodName(),
89           super.getParameterTypes(), super.getParams());
90     } else {
91       if (_targets != null) {
92         if (_targets.contains(current)) {
93           toReturn = super.execute();
94           _executed = true;
95           _targets.remove(current);
96         } else {
97           _executed = true;
98           toReturn = send(strat.selectNextSibling());
99
100           return toReturn;
101         }
102       } else {
103         toReturn = super.execute();
104         _executed = true;
105       }
106
107       if ((addr = strat.selectNextSibling()) != null) {
108         if (!_disabled) {
109           send(addr);
110         }
111       }
112     }
113
114     return toReturn;
115   }
116
117   /**
118    * @return the <code>ReplicatedInvoker</code> that this instance holds.
119    */

120   public ReplicatedInvoker getReplicatedInvoker() {
121     return _invoker;
122   }
123
124   /**
125    * Disables replication behavior (this command will execute as a normal
126    * <code>InvokeCommand</code>).
127    */

128   public void disable() {
129     _disabled = true;
130   }
131
132   /**
133    * @see org.sapia.ubik.rmi.server.invocation.InvokeCommand#readExternal(java.io.ObjectInput)
134    */

135   public void readExternal(ObjectInput JavaDoc in)
136     throws IOException JavaDoc, ClassNotFoundException JavaDoc {
137     super.readExternal(in);
138     _visited = (Set JavaDoc) in.readObject();
139     _targets = (Set JavaDoc) in.readObject();
140     _invoker = (ReplicatedInvoker) in.readObject();
141     _executed = in.readBoolean();
142     _synchronous = in.readBoolean();
143     _disabled = in.readBoolean();
144   }
145
146   /**
147    * @see org.sapia.ubik.rmi.server.invocation.InvokeCommand#writeExternal(java.io.ObjectOutput)
148    */

149   public void writeExternal(ObjectOutput JavaDoc out) throws IOException JavaDoc {
150     super.writeExternal(out);
151     out.writeObject(_visited);
152     out.writeObject(_targets);
153     out.writeObject(_invoker);
154     out.writeBoolean(_executed);
155     out.writeBoolean(_synchronous);
156     out.writeBoolean(_disabled);
157   }
158
159   /**
160    * This method synchronously or asynchronously sends this instance to the server
161    * at the given address.
162    * @param next the <code>ServerAddress</code> of the "next" server to which this
163    * instance should be sent.
164    * @return the result of the invocation.
165    * @throws RemoteException if a problem occurs sending this instance.
166    */

167   protected Object JavaDoc send(ServerAddress next) throws RemoteException JavaDoc {
168     SendHelper helper = new SendHelper(this, next, _synchronous);
169
170     if (_synchronous) {
171       try {
172         return helper.send();
173       } catch (Throwable JavaDoc t) {
174         if (t instanceof RemoteException JavaDoc) {
175           throw (RemoteException JavaDoc) t;
176         }
177
178         throw new RemoteException JavaDoc("Exception caught replicating command", t);
179       }
180     } else {
181       try {
182         helper.send();
183       } catch (Throwable JavaDoc t) {
184         if (t instanceof RemoteException JavaDoc) {
185           throw (RemoteException JavaDoc) t;
186         }
187
188         throw new RemoteException JavaDoc("Exception caught replicating command", t);
189       }
190
191       return null;
192     }
193   }
194 }
195
Popular Tags