1 /*
2 * Copyright (c) 1998-2002 The Jgroup Team.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 *
17 */
18
19 package jgroup.relacs.rmi;
20
21 import java.rmi.RemoteException;
22 import java.rmi.server.ExportException;
23 import java.util.HashSet;
24 import java.util.Iterator;
25
26 import jgroup.core.Callback;
27 import jgroup.core.MemberId;
28 import jgroup.core.View;
29 import jgroup.core.multicast.AckListener;
30 import net.jini.export.Exporter;
31 import net.jini.jeri.BasicILFactory;
32 import net.jini.jeri.BasicJeriExporter;
33 import net.jini.jeri.tcp.TcpServerEndpoint;
34
35
36 /**
37 * Acknowledgement listener for asynchronous invocations, that is
38 * invocations for which the client does not wait for the reply.
39 *
40 * @author Alberto Montresor
41 * @author Hein Meling
42 * @since Jgroup 0.9
43 */
44 public final class AsynchAckListener
45 implements AckListener
46 {
47
48 ////////////////////////////////////////////////////////////////////////////////////////////
49 // Fields
50 ////////////////////////////////////////////////////////////////////////////////////////////
51
52 /** Callback to be notified at the end. */
53 private Callback cb;
54
55 /** Members from which we are waiting a result or an exception. */
56 private HashSet waiting;
57
58 /** The BasicJeriExporter used by this AckListener */
59 private Exporter exporter;
60
61
62 ////////////////////////////////////////////////////////////////////////////////////////////
63 // Constructor
64 ////////////////////////////////////////////////////////////////////////////////////////////
65
66 public AsynchAckListener(Callback cb)
67 throws RemoteException
68 {
69 this.cb = cb;
70 }
71
72 /**
73 * Get a reference for the remote AckListener.
74 *
75 * @return
76 * A remote proxy for the <code>AsynchAckListener</code>.
77 * @throws ExportException
78 * Raised if the <code>AsyncAckListener</code> could not be exported.
79 */
80 public AckListener getRemoteAckListener()
81 throws ExportException
82 {
83 exporter =
84 new BasicJeriExporter(TcpServerEndpoint.getInstance(0), new BasicILFactory());
85 return (AckListener) exporter.export(this);
86 }
87
88
89 ////////////////////////////////////////////////////////////////////////////////////////////
90 // Methods from the AckListener interface
91 ////////////////////////////////////////////////////////////////////////////////////////////
92
93 public void notifyView(View view)
94 throws RemoteException
95 {
96 MemberId[] members = view.getMembers();
97 for (int i = 0; i < members.length; i++)
98 waiting.add(members[i]);
99 /*
100 * Do nothing; we don't need to collect results since we are
101 * asynchronous.
102 */
103 }
104
105
106 public void ack(MemberId id, int vpos, Object obj)
107 throws RemoteException
108 {
109 waiting.remove(id);
110 if (obj instanceof Exception)
111 cb.exception(id, (Exception) obj);
112 else
113 cb.result(id, obj);
114 }
115
116
117 public void viewChange()
118 throws RemoteException
119 {
120 if (!waiting.isEmpty()) {
121 RemoteException remoteException = new RemoteException("Member unreachable.");
122 for (Iterator iter = waiting.iterator(); iter.hasNext(); )
123 cb.exception((MemberId) iter.next(), remoteException);
124 }
125 // Unexport this remote AckListener; no more remote calls should occur
126 exporter.unexport(false);
127 }
128
129 } // END AsynchAckListener