summaryrefslogtreecommitdiff
path: root/java/src/IceInternal/RouterInfo.java
blob: 2adae792f56825fb48b369c43e790d4244f17061 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
// **********************************************************************
//
// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************

package IceInternal;

public final class RouterInfo
{
    interface GetClientEndpointsCallback
    {
        void setEndpoints(EndpointI[] endpoints);
        void setException(Ice.LocalException ex);
    }

    interface AddProxyCallback
    {
        void addedProxy();
        void setException(Ice.LocalException ex);
    }

    RouterInfo(Ice.RouterPrx router)
    {
        _router = router;

        assert(_router != null);
    }

    synchronized public void
    destroy()
    {
        _clientEndpoints = new EndpointI[0];
        _serverEndpoints = new EndpointI[0];
        _adapter = null;
        _identities.clear();
    }

    public boolean
    equals(java.lang.Object obj)
    {
        if(this == obj)
        {
            return true;
        }

        if(obj instanceof RouterInfo)
        {
            return _router.equals(((RouterInfo)obj)._router);
        }

        return false;
    }

    public Ice.RouterPrx
    getRouter()
    {
        //
        // No mutex lock necessary, _router is immutable.
        //
        return _router;
    }

    public EndpointI[]
    getClientEndpoints()
    {
        synchronized(this)
        {
            if(_clientEndpoints != null) // Lazy initialization.
            {
                return _clientEndpoints;
            }
        }

        return setClientEndpoints(_router.getClientProxy());
    }

    public void
    getClientEndpoints(final GetClientEndpointsCallback callback)
    {
        EndpointI[] clientEndpoints = null;
        synchronized(this)
        {
            clientEndpoints = _clientEndpoints;
        }
        
        if(clientEndpoints != null)
        {
            callback.setEndpoints(clientEndpoints);
            return;
        }
        
        final RouterInfo self = this;
        _router.getClientProxy_async(new Ice.AMI_Router_getClientProxy()
            {
                public void
                ice_response(Ice.ObjectPrx clientProxy)
                {
                    callback.setEndpoints(setClientEndpoints(clientProxy));
                }
                
                public void
                ice_exception(Ice.LocalException ex)
                {
                    if(ex instanceof Ice.CollocationOptimizationException)
                    {
                        try
                        {
                            callback.setEndpoints(getClientEndpoints());
                        }
                        catch(Ice.LocalException e)
                        {
                            callback.setException(e);
                        }
                    }
                    else
                    {
                        callback.setException(ex);
                    }
                }
            });
    }

    public EndpointI[]
    getServerEndpoints()
    {
        synchronized(this)
        {
            if(_serverEndpoints != null) // Lazy initialization.
            {
                return _serverEndpoints;
            }
        }
        
        return setServerEndpoints(_router.getServerProxy());
    }

    public void
    addProxy(Ice.ObjectPrx proxy)
    {
        assert(proxy != null);
        synchronized(this)
        {
            if(_identities.contains(proxy.ice_getIdentity()))
            {
                //
                // Only add the proxy to the router if it's not already in our local map.
                //
                return;
            }
        }

        addAndEvictProxies(proxy, _router.addProxies(new Ice.ObjectPrx[] { proxy }));
    }

    public boolean
    addProxy(final Ice.ObjectPrx proxy, final AddProxyCallback callback)
    {
        assert(proxy != null);
        synchronized(this)
        {
            if(_identities.contains(proxy.ice_getIdentity()))
            {
                //
                // Only add the proxy to the router if it's not already in our local map.
                //
                return true;
            }
        }

        _router.addProxies_async(new Ice.AMI_Router_addProxies()
            {
                public void
                ice_response(Ice.ObjectPrx[] evictedProxies)
                {
                    addAndEvictProxies(proxy, evictedProxies);
                    callback.addedProxy();
                }
                
                public void
                ice_exception(Ice.LocalException ex)
                {
                    if(ex instanceof Ice.CollocationOptimizationException)
                    {
                        try
                        {
                            addProxy(proxy);
                            callback.addedProxy();
                        }
                        catch(Ice.LocalException e)
                        {
                            callback.setException(ex);
                        }
                    }
                    else
                    {
                        callback.setException(ex);
                    }
                }
            },
            new Ice.ObjectPrx[] { proxy });

        return false;
    }

    public synchronized void
    setAdapter(Ice.ObjectAdapter adapter)
    {
        _adapter = adapter;
    }

    public synchronized Ice.ObjectAdapter
    getAdapter()
    {
        return _adapter;
    }

    private synchronized EndpointI[]
    setClientEndpoints(Ice.ObjectPrx clientProxy)
    {
        if(_clientEndpoints == null)
        {
            if(clientProxy == null)
            {
                //
                // If getClientProxy() return nil, use router endpoints.
                //
                _clientEndpoints = ((Ice.ObjectPrxHelperBase)_router).__reference().getEndpoints();
            }
            else
            {
                clientProxy = clientProxy.ice_router(null); // The client proxy cannot be routed.
            
                //
                // In order to avoid creating a new connection to the
                // router, we must use the same timeout as the already
                // existing connection.
                //
                try
                {
                    clientProxy = clientProxy.ice_timeout(_router.ice_getConnection().timeout());
                }
                catch(Ice.CollocationOptimizationException ex)
                {
                    // Ignore - collocated router.
                }
            
                _clientEndpoints = ((Ice.ObjectPrxHelperBase)clientProxy).__reference().getEndpoints();
            }
        }
        return _clientEndpoints;
    }

    private synchronized EndpointI[]
    setServerEndpoints(Ice.ObjectPrx serverProxy)
    {
        if(serverProxy == null)
        {
            throw new Ice.NoEndpointException();
        }
        
        serverProxy = serverProxy.ice_router(null); // The server proxy cannot be routed.
        _serverEndpoints = ((Ice.ObjectPrxHelperBase)serverProxy).__reference().getEndpoints();
        return _serverEndpoints;
    }

    private synchronized void
    addAndEvictProxies(Ice.ObjectPrx proxy, Ice.ObjectPrx[] evictedProxies)
    {
        //
        // Check if the proxy hasn't already been evicted by a
        // concurrent addProxies call. If it's the case, don't
        // add it to our local map.
        //
        int index = _evictedIdentities.indexOf(proxy.ice_getIdentity());
        if(index >= 0)
        {
            _evictedIdentities.remove(index);
        }
        else
        {
            //
            // If we successfully added the proxy to the router,
            // we add it to our local map.
            //
            _identities.add(proxy.ice_getIdentity());
        }

        //
        // We also must remove whatever proxies the router evicted.
        //
        for(int i = 0; i < evictedProxies.length; ++i)
        {
            if(!_identities.remove(evictedProxies[i].ice_getIdentity()))
            {
                //
                // It's possible for the proxy to not have been
                // added yet in the local map if two threads
                // concurrently call addProxies.
                //
                _evictedIdentities.add(evictedProxies[i].ice_getIdentity());
            }
        }
    }

    private final Ice.RouterPrx _router;
    private EndpointI[] _clientEndpoints;
    private EndpointI[] _serverEndpoints;
    private Ice.ObjectAdapter _adapter;
    private java.util.Set<Ice.Identity> _identities = new java.util.HashSet<Ice.Identity>();
    private java.util.List<Ice.Identity> _evictedIdentities = new java.util.ArrayList<Ice.Identity>();
}