KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ha > framework > interfaces > HARMIClient


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22 package org.jboss.ha.framework.interfaces;
23
24
25 import java.io.IOException JavaDoc;
26 import java.io.ObjectInputStream JavaDoc;
27 import java.io.ObjectOutputStream JavaDoc;
28 import java.lang.reflect.Method JavaDoc;
29 import java.util.ArrayList JavaDoc;
30 import java.util.List JavaDoc;
31
32 import org.jboss.invocation.MarshalledInvocation;
33 import org.jboss.logging.Logger;
34
35 /**
36  *
37  *
38  * @author <a HREF="mailto:sacha.labourey@cogito-info.ch">Sacha Labourey</a>
39  * @author <a HREF="mailto:bill@burkecentral.com">Bill Burke</a>
40  * @version $Revision: 56228 $
41  */

42 public class HARMIClient
43    implements HARMIProxy, java.lang.reflect.InvocationHandler JavaDoc, java.io.Serializable JavaDoc
44 {
45    // Constants -----------------------------------------------------
46
/** The serialVersionUID
47     * @since
48     */

49    private static final long serialVersionUID = -1227816478666532463L;
50    private static final Logger log = Logger.getLogger(HARMIClient.class);
51
52    /** {@link Object#toString} method reference. */
53    protected static final Method JavaDoc TO_STRING;
54
55    /** {@link Object#hashCode} method reference. */
56    protected static final Method JavaDoc HASH_CODE;
57
58    /** {@link Object#equals} method reference. */
59    protected static final Method JavaDoc EQUALS;
60
61    static
62    {
63       try
64       {
65          final Class JavaDoc[] empty = {};
66          final Class JavaDoc type = Object JavaDoc.class;
67
68          TO_STRING = type.getMethod("toString", empty);
69          HASH_CODE = type.getMethod("hashCode", empty);
70          EQUALS = type.getMethod("equals", new Class JavaDoc[] { type });
71       }
72       catch (Exception JavaDoc e)
73       {
74          e.printStackTrace();
75          throw new ExceptionInInitializerError JavaDoc(e);
76       }
77    }
78
79    // Attributes ----------------------------------------------------
80

81    protected String JavaDoc key = null;
82    //protected ArrayList targets = null;
83
protected LoadBalancePolicy loadBalancePolicy;
84    //protected transient long currentViewId = 0;
85
protected transient Object JavaDoc local = null;
86    protected transient boolean trace;
87    FamilyClusterInfo familyClusterInfo = null;
88
89    // Static --------------------------------------------------------
90

91    // Constructors --------------------------------------------------
92

93    public HARMIClient() {}
94
95    public HARMIClient(List JavaDoc targets, LoadBalancePolicy policy, String JavaDoc key)
96    {
97       this(targets, 0, policy, key, null);
98    }
99
100    public HARMIClient(List JavaDoc targets,
101                        long initViewId,
102                        LoadBalancePolicy policy,
103                        String JavaDoc key,
104                        Object JavaDoc local)
105    {
106       this.familyClusterInfo = ClusteringTargetsRepository.initTarget (key, targets, initViewId);
107
108       //this.targets = targets;
109
this.loadBalancePolicy = policy;
110       this.loadBalancePolicy.init(this);
111       this.key = key;
112       this.local = local;
113       this.trace = log.isTraceEnabled();
114       if( trace )
115          log.trace("Init, cluterInfo: "+familyClusterInfo+", policy="+loadBalancePolicy);
116    }
117
118    // Public --------------------------------------------------------
119
/*
120    public ArrayList getTargets()
121    {
122       return targets;
123    }
124    
125    public void setTargets(ArrayList newTargets)
126    {
127       synchronized(targets)
128       {
129          targets.clear();
130          targets.addAll(newTargets);
131       }
132    }
133    */

134    public void updateClusterInfo (ArrayList JavaDoc targets, long viewId)
135    {
136       if (familyClusterInfo != null)
137          this.familyClusterInfo.updateClusterInfo (targets, viewId);
138    }
139
140    public Object JavaDoc getRemoteTarget()
141    {
142       // System.out.println("number of targets: " + targets.size());
143
return loadBalancePolicy.chooseTarget(this.familyClusterInfo, null); // legacy, no Invocation object in raw HA-RMI
144
}
145
146    public void remoteTargetHasFailed(Object JavaDoc target)
147    {
148       removeDeadTarget(target);
149    }
150
151
152    public Method JavaDoc findLocalMethod(Method JavaDoc method, Object JavaDoc[] args) throws Exception JavaDoc
153    {
154       return method;
155    }
156
157
158    public Object JavaDoc invokeRemote(Object JavaDoc proxy, Method JavaDoc method, Object JavaDoc[] args) throws Throwable JavaDoc
159    {
160       boolean trace = log.isTraceEnabled();
161       HARMIServer target = (HARMIServer)getRemoteTarget();
162       while (target != null)
163       {
164          Exception JavaDoc lastException = null;
165          try
166          {
167             if( trace )
168                log.trace("Invoking on target="+target);
169             MarshalledInvocation mi = new MarshalledInvocation(null, method, args, null, null, null);
170             mi.setObjectName (""); //FIXME: Fake value! Bill's optimisations regarding MI make the hypothesis
171
// that ObjectName is always here otherwise the writeExternal code of MI
172
// "out.writeInt(payload.size() - 3);" is wrong
173
HARMIResponse rsp = target.invoke(this.familyClusterInfo.getCurrentViewId (), mi);
174             if (rsp.newReplicants != null)
175             {
176                if( trace )
177                {
178                   log.trace("newReplicants: "+rsp.newReplicants);
179                }
180                updateClusterInfo (rsp.newReplicants, rsp.currentViewId);
181                //setTargets(rsp.newReplicants);
182
//currentViewId = rsp.currentViewId;
183
}
184
185             return rsp.response;
186          }
187          catch (java.rmi.ConnectException JavaDoc e)
188          {
189             lastException = e;
190          }
191          catch (java.rmi.ConnectIOException JavaDoc e)
192          {
193             lastException = e;
194          }
195          catch (java.rmi.NoSuchObjectException JavaDoc e)
196          {
197             lastException = e;
198          }
199          catch (java.rmi.UnmarshalException JavaDoc e)
200          {
201             lastException = e;
202          }
203          catch (java.rmi.UnknownHostException JavaDoc e)
204          {
205             lastException = e;
206          }
207          if( trace )
208             log.trace("Invoke failed, target="+target, lastException);
209          // If we reach here, this means that we must fail-over
210
remoteTargetHasFailed(target);
211          target = (HARMIServer)getRemoteTarget();
212       }
213       // if we get here this means list was exhausted
214
throw new java.rmi.RemoteException JavaDoc("Service unavailable.");
215
216    }
217
218    // HARMIProxy implementation ----------------------------------------------
219

220    public boolean isLocal()
221    {
222       return local != null;
223    }
224
225    // InvocationHandler implementation ----------------------------------------------
226

227    public Object JavaDoc invoke(Object JavaDoc proxy, Method JavaDoc method, Object JavaDoc[] args) throws Throwable JavaDoc
228    {
229       // The isLocal call is handled by the proxy
230
String JavaDoc name = method.getName();
231       if (method.equals(TO_STRING))
232       {
233          StringBuffer JavaDoc tmp = new StringBuffer JavaDoc(super.toString());
234          tmp.append('(');
235          tmp.append(familyClusterInfo);
236          tmp.append(')');
237          return tmp.toString();
238       }
239       else if (name.equals("equals"))
240       {
241          return method.invoke(this, args);
242       }
243       else if (name.equals("hashCode"))
244       {
245          return method.invoke(this, args);
246       }
247       else if (name.equals("isLocal") && (args == null || args.length == 0))
248       {
249          return method.invoke(this, args);
250       }
251
252       // we try to optimize the call locally first
253
//
254
if (local != null)
255       {
256          try
257          {
258             Method JavaDoc localMethod = findLocalMethod(method, args);
259             return localMethod.invoke(local, args);
260          }
261          catch (java.lang.reflect.InvocationTargetException JavaDoc ite)
262          {
263             throw ite.getTargetException();
264          }
265       }
266       else
267       {
268          return invokeRemote(null, method, args);
269       }
270    }
271
272    // Package protected ---------------------------------------------
273

274    // Protected -----------------------------------------------------
275

276    protected void removeDeadTarget(Object JavaDoc target)
277    {
278       //System.out.println("Size before : " + Integer.toString(targets.length));
279
if (this.familyClusterInfo != null)
280          this.familyClusterInfo.removeDeadTarget (target);
281    }
282
283    // Private -------------------------------------------------------
284

285    private void readObject (ObjectInputStream JavaDoc stream)
286       throws IOException JavaDoc, ClassNotFoundException JavaDoc
287    {
288       this.key = stream.readUTF();
289       List JavaDoc targets = (List JavaDoc)stream.readObject();
290       long vid = stream.readLong ();
291       this.loadBalancePolicy = (LoadBalancePolicy)stream.readObject();
292       HARMIServer server = (HARMIServer)HARMIServer.rmiServers.get(key);
293
294       // keep a reference on our family object
295
//
296
this.familyClusterInfo = ClusteringTargetsRepository.initTarget (this.key, targets, vid);
297
298       this.loadBalancePolicy.init(this);
299
300       if (server != null)
301       {
302          synchronized (targets)
303          {
304             try
305             {
306                targets = (List JavaDoc)server.getReplicants();
307                local = server.getLocal();
308             }
309             catch (Exception JavaDoc ignored)
310             {}
311          }
312       }
313       this.trace = log.isTraceEnabled();
314       if( trace )
315          log.trace("Init, clusterInfo: "+familyClusterInfo+", policy="+loadBalancePolicy);
316    }
317    private void writeObject (ObjectOutputStream JavaDoc stream)
318       throws IOException JavaDoc
319    {
320       // JBAS-2071 - sync on FCI to ensure targets and vid are consistent
321
List JavaDoc currentTargets = null;
322       long vid = 0;
323       synchronized (this.familyClusterInfo)
324       {
325          currentTargets = this.familyClusterInfo.getTargets ();
326          vid = this.familyClusterInfo.getCurrentViewId ();
327       }
328       stream.writeUTF(key);
329       stream.writeObject(currentTargets);
330       stream.writeLong(vid);
331       stream.writeObject(loadBalancePolicy);
332
333    }
334
335 }
Popular Tags