1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package jgroup.relacs.gmi;
19
20 import java.io.IOException;
21 import java.io.ObjectInputStream;
22 import java.lang.reflect.Method;
23 import java.lang.reflect.Proxy;
24 import java.rmi.Remote;
25 import java.util.Collection;
26 import java.util.concurrent.locks.Condition;
27 import java.util.concurrent.locks.Lock;
28 import java.util.concurrent.locks.ReentrantLock;
29
30 import jgroup.core.ExternalGMIListener;
31 import jgroup.core.GroupManager;
32 import jgroup.core.View;
33 import net.jini.jeri.InboundRequest;
34 import net.jini.jeri.InvocationDispatcher;
35
36 import org.apache.log4j.Logger;
37
38
39
40
41
42
43
44
45 public class GroupInvocationDispatcher
46 implements InvocationDispatcher
47 {
48
49
50
51
52
53
54 private static final Logger log = Logger.getLogger(GroupInvocationDispatcher.class);
55
56
57
58
59
60
61
62 private final MethodTable methodTable;
63
64
65 private final GroupManager groupManager;
66
67
68 private View serverView;
69
70
71
72
73
74 private volatile boolean blockInvocation = true;
75
76
77 private final Lock lock = new ReentrantLock();
78 private final Condition notDispatching = lock.newCondition();
79
80
81
82
83
84
85
86
87
88
89 public GroupInvocationDispatcher(GroupManager gm, MethodTable methodTable)
90 {
91 this.groupManager = gm;
92 this.methodTable = methodTable;
93 }
94
95
96
97
98
99
100
101
102
103
104
105
106
107 public InvocationResult dispatch(ObjectInputStream in)
108 {
109
110 long hash;
111 long clientView;
112 try {
113 clientView = in.readLong();
114 hash = in.readLong();
115 } catch (IOException ioex) {
116
117 log.warn("Could not read method hash from stream, aborting request!", ioex);
118 return null;
119 }
120
121
122 MethodDetails m = methodTable.get(hash);
123 Method method = m.getMethod();
124 if (m == null) {
125 log.warn("The provided hash does not correspond to a known server-side method: " + hash);
126 return null;
127 }
128
129
130 Class[] paramTypes = method.getParameterTypes();
131 Object[] params = new Object[paramTypes.length];
132 try {
133
134 for (int i = 0; i < params.length; ++i) {
135 params[i] = in.readObject();
136 if (params[i] instanceof ExternalGMIListener) {
137
138
139
140
141 GroupInvocationHandler handler =
142 (GroupInvocationHandler) Proxy.getInvocationHandler(params[i]);
143 handler.setGroupManager(groupManager);
144 }
145 }
146 } catch (ClassNotFoundException cnfex) {
147 log.warn("ClassNotFoundException caught when unmarshalling arguments", cnfex);
148 return null;
149 } catch (IOException ioex) {
150
151 log.warn("Could not read arguments from stream, aborting request!", ioex);
152 return null;
153 }
154
155
156 Object server = m.getServer();
157
158
159
160
161 if (log.isDebugEnabled())
162 log.debug("Invoking " + m + " on server " + server.getClass().getSimpleName());
163 try {
164 return new InvocationResult(method, params, server, serverView, clientView);
165 } catch (IllegalAccessException e) {
166 log.warn("Tried to invoke the non-public method: " + m, e);
167 return null;
168 } catch (IllegalArgumentException e) {
169 log.warn("An IllegalArgumentException occured while invoking method: " + m, e);
170 return null;
171 }
172 }
173
174
175
176
177
178
179 private void doBlock(MethodDetails m)
180 {
181 lock.lock();
182 try {
183 while (blockInvocation) {
184 if (log.isDebugEnabled())
185 log.debug("Blocking invocation " + m);
186
187 notDispatching.awaitUninterruptibly();
188 if (!blockInvocation && log.isDebugEnabled())
189 log.debug("Unblocking invocation " + m);
190 }
191 } finally {
192 lock.unlock();
193 }
194 }
195
196
197
198
199 void enableDispatching()
200 {
201 if (log.isDebugEnabled())
202 log.debug("Enable invocation dispatching");
203 lock.lock();
204 try {
205
206 blockInvocation = false;
207 notDispatching.signalAll();
208 } finally {
209 lock.unlock();
210 }
211 }
212
213
214
215
216 void disableDispatching()
217 {
218 if (log.isDebugEnabled())
219 log.debug("Disable invocation dispatching");
220 lock.lock();
221 try {
222
223 blockInvocation = true;
224 } finally {
225 lock.unlock();
226 }
227 }
228
229
230
231
232 void setView(View serverView)
233 {
234 this.serverView = serverView;
235 }
236
237
238
239
240
241 public void dispatch(Remote impl, InboundRequest request, Collection context)
242 {
243 throw new UnsupportedOperationException("Should not be called.");
244 }
245
246 }