~ubuntu-branches/ubuntu/wily/libjboss-remoting-java/wily

« back to all changes in this revision

Viewing changes to src/main/org/jboss/remoting/ConnectionValidator.java

  • Committer: Package Import Robot
  • Author(s): Torsten Werner
  • Date: 2011-09-09 14:01:03 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: package-import@ubuntu.com-20110909140103-hqokx61534tas9rg
Tags: 2.5.3.SP1-1
* Newer but not newest upstream release. Do not build samples.
* Change debian/watch to upstream's svn repo.
* Add patch to fix compile error caused by tomcat update.
  (Closes: #628303)
* Switch to source format 3.0.
* Switch to debhelper level 7.
* Remove useless Depends.
* Update Standards-Version: 3.9.2.
* Update README.source.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
23
package org.jboss.remoting;
 
24
 
 
25
import java.security.AccessController;
 
26
import java.security.PrivilegedAction;
 
27
import java.security.PrivilegedActionException;
 
28
import java.security.PrivilegedExceptionAction;
 
29
import java.util.HashMap;
 
30
import java.util.HashSet;
 
31
import java.util.Iterator;
 
32
import java.util.Map;
 
33
import java.util.Set;
 
34
import java.util.Timer;
 
35
import java.util.TimerTask;
 
36
 
 
37
import org.jboss.logging.Logger;
 
38
import org.jboss.remoting.transport.ClientInvoker;
 
39
import org.jboss.remoting.util.StoppableTimerTask;
 
40
import org.jboss.remoting.util.TimerUtil;
 
41
 
 
42
/**
 
43
 * @author <a href="mailto:tom.elrod@jboss.com">Tom Elrod</a>
 
44
 * @author <a href="mailto:ovidiu@jboss.org">Ovidiu Feodorov</a>
 
45
 * @author <a href="mailto:tlee@redhat.com">Trustin Lee</a>
 
46
 */
 
47
public class ConnectionValidator extends TimerTask implements StoppableTimerTask
 
48
{
 
49
   // Constants ------------------------------------------------------------------------------------
 
50
 
 
51
   private static final Logger log = Logger.getLogger(ConnectionValidator.class.getName());
 
52
 
 
53
   /** Configuration map key for ping period. */
 
54
   public static final String VALIDATOR_PING_PERIOD = "validatorPingPeriod";
 
55
   
 
56
   /** Default ping period. Value is 2 seconds. */
 
57
   public static final long DEFAULT_PING_PERIOD = 2000;
 
58
   
 
59
   /** Configuration map key for ping timeout. */
 
60
   public static final String VALIDATOR_PING_TIMEOUT = "validatorPingTimeout";
 
61
   
 
62
   /** Default ping timeout period.  Value is 1 second. */
 
63
   public static final String DEFAULT_PING_TIMEOUT = "1000";
 
64
 
 
65
   /** Default ping timeout period.  Value is 1 second. */
 
66
   public static final int DEFAULT_PING_TIMEOUT_INT = 1000;
 
67
   
 
68
   /**
 
69
    * Default number of ping retries.  Value is 1.
 
70
    * Currently implemented only on socket transport family.
 
71
    */
 
72
   public static final String DEFAULT_NUMBER_OF_PING_RETRIES = "1";
 
73
 
 
74
   /**
 
75
    * Key to determine if ConnectionValidator should tie failure to presence
 
76
    * of active lease on server side.  Default value is "true".
 
77
    */
 
78
   public static final String TIE_TO_LEASE = "tieToLease";
 
79
   
 
80
   /**
 
81
    * Key to determine whether to stop ConnectionValidator when PING fails.
 
82
    * Default value is "true".
 
83
    */
 
84
   public static final String STOP_LEASE_ON_FAILURE = "stopLeaseOnFailure";
 
85
   
 
86
   /**
 
87
    * Key to determine value of disconnectTimeout upon connection failure.
 
88
    */
 
89
   public static final String FAILURE_DISCONNECT_TIMEOUT = "failureDisconnectTimeout";
 
90
   
 
91
   // Static ---------------------------------------------------------------------------------------
 
92
 
 
93
   private static boolean trace = log.isTraceEnabled();
 
94
 
 
95
   /**
 
96
    * Will make $PING$ invocation on server. If sucessful, will return true. Otherwise, will throw
 
97
    * an exception.
 
98
    *
 
99
    * @param locator - locator for the server to ping
 
100
    * @param config  - any configuration needed for server
 
101
    * @return true if alive, false if not
 
102
    */
 
103
   public static boolean checkConnection(final InvokerLocator locator, Map config) throws Throwable
 
104
   {
 
105
      boolean pingWorked = false;
 
106
      final Map configMap = createPingConfig(config, null);
 
107
      int pingTimeout = Integer.parseInt((String) configMap.get(ServerInvoker.TIMEOUT));
 
108
      ClientInvoker innerClientInvoker = null;
 
109
 
 
110
      try
 
111
      {  
 
112
         try
 
113
         {
 
114
            innerClientInvoker = (ClientInvoker) AccessController.doPrivileged( new PrivilegedExceptionAction()
 
115
            {
 
116
               public Object run() throws Exception
 
117
               {
 
118
                  return InvokerRegistry.createClientInvoker(locator, configMap);
 
119
               }
 
120
            });
 
121
         }
 
122
         catch (PrivilegedActionException pae)
 
123
         {
 
124
            throw pae.getException();
 
125
         }
 
126
 
 
127
         if (!innerClientInvoker.isConnected())
 
128
         {
 
129
            if (trace) { log.trace("inner client invoker not connected, connecting ..."); }
 
130
            innerClientInvoker.connect();
 
131
         }
 
132
 
 
133
         pingWorked = doCheckConnection(innerClientInvoker, pingTimeout);
 
134
      }
 
135
      catch (Throwable throwable)
 
136
      {
 
137
         log.debug("ConnectionValidator unable to connect to server " +
 
138
            innerClientInvoker.getLocator().getProtocol() + "://" +
 
139
            innerClientInvoker.getLocator().getHost() + ":" +
 
140
            innerClientInvoker.getLocator().getPort(), throwable);
 
141
      }
 
142
      finally
 
143
      {
 
144
         if (innerClientInvoker != null)
 
145
         {
 
146
            AccessController.doPrivileged( new PrivilegedAction()
 
147
            {
 
148
               public Object run()
 
149
               {
 
150
                  InvokerRegistry.destroyClientInvoker(locator, configMap);
 
151
                  return null;
 
152
               }
 
153
            });
 
154
         }
 
155
      }
 
156
 
 
157
      return pingWorked;
 
158
   }
 
159
 
 
160
   private static boolean doCheckConnection(ClientInvoker clientInvoker, int pingTimeout) throws Throwable
 
161
   {
 
162
      boolean pingWorked = false;
 
163
 
 
164
      try
 
165
      {
 
166
         // Sending null client id as don't want to trigger lease on server side. This also means
 
167
         // that client connection validator will NOT impact client lease, so can not depend on it
 
168
         // to maintain client lease with the server.
 
169
         InvocationRequest ir;
 
170
         ir = new InvocationRequest(null, Subsystem.SELF, "$PING$", null, null, null);
 
171
         ConnectionCheckThread t = new ConnectionCheckThread(clientInvoker, ir);
 
172
         t.start();
 
173
         Thread.sleep(pingTimeout);
 
174
         pingWorked = t.isValid();
 
175
      }
 
176
      catch (Throwable t)
 
177
      {
 
178
         log.debug("ConnectionValidator failed to ping via " + clientInvoker, t);
 
179
      }
 
180
 
 
181
      return pingWorked;
 
182
   }
 
183
   
 
184
   private static Map createPingConfig(Map config, Map metadata)
 
185
   {
 
186
      Map localConfig = new HashMap();
 
187
      localConfig.put("connection_checker", "true");
 
188
 
 
189
      if (config != null)
 
190
      {
 
191
         Object o = config.get(VALIDATOR_PING_TIMEOUT);
 
192
         log.trace("config timeout: " + o);
 
193
         if (o != null)
 
194
         {
 
195
            try
 
196
            {
 
197
               Integer.parseInt((String) o);
 
198
               localConfig.put(ServerInvoker.TIMEOUT, o);
 
199
            }
 
200
            catch (NumberFormatException e)
 
201
            {
 
202
               log.warn("Need integer for value of parameter " + VALIDATOR_PING_TIMEOUT + 
 
203
                        ". Using default value " + DEFAULT_PING_TIMEOUT);
 
204
            }
 
205
         }
 
206
         
 
207
         o = config.get("NumberOfCallRetries");
 
208
         if (o != null)
 
209
         {
 
210
            localConfig.put("NumberOfCallRetries", o);
 
211
         }
 
212
      }
 
213
      
 
214
      if (metadata != null)
 
215
      {
 
216
         metadata.remove(ServerInvoker.TIMEOUT);
 
217
         localConfig.putAll(metadata);
 
218
         Object o = metadata.get(VALIDATOR_PING_TIMEOUT);
 
219
         if (o != null)
 
220
         {
 
221
            try
 
222
            {
 
223
               Integer.parseInt((String) o);
 
224
               localConfig.put(ServerInvoker.TIMEOUT, o);
 
225
            }
 
226
            catch (NumberFormatException e)
 
227
            {
 
228
               log.warn("Need integer for value of parameter " + VALIDATOR_PING_TIMEOUT +
 
229
                        ". Using default value " + DEFAULT_PING_TIMEOUT);
 
230
            }
 
231
         }
 
232
      }
 
233
      
 
234
      if (localConfig.get(ServerInvoker.TIMEOUT) == null)
 
235
      {
 
236
         localConfig.put(ServerInvoker.TIMEOUT, DEFAULT_PING_TIMEOUT);
 
237
      }
 
238
      
 
239
      if (localConfig.get("NumberOfCallRetries") == null)
 
240
      {
 
241
         localConfig.put("NumberOfCallRetries", DEFAULT_NUMBER_OF_PING_RETRIES);
 
242
      }
 
243
      
 
244
      return localConfig;
 
245
   }
 
246
 
 
247
   // Attributes -----------------------------------------------------------------------------------
 
248
 
 
249
   private Client client;
 
250
   private long pingPeriod;
 
251
   private Map metadata;
 
252
   private InvokerLocator locator;
 
253
   private Map configMap;
 
254
   private Map listeners;
 
255
   private ClientInvoker clientInvoker;
 
256
   private Object lock = new Object();
 
257
   private Object notificationLock = new Object();
 
258
   private boolean started;
 
259
   private volatile boolean stopped;
 
260
   private volatile boolean stopping;
 
261
   private String invokerSessionId;
 
262
   private boolean tieToLease = true;
 
263
   private boolean stopLeaseOnFailure = true;
 
264
   private int pingTimeout;
 
265
   private int failureDisconnectTimeout = -1;
 
266
   private volatile boolean isValid;
 
267
   private Timer timer;
 
268
   private MicroRemoteClientInvoker sharedInvoker;
 
269
   private LeasePinger leasePinger;
 
270
   private boolean useClientConnectionIdentity;
 
271
 
 
272
   // Constructors ---------------------------------------------------------------------------------
 
273
 
 
274
   public ConnectionValidator(Client client)
 
275
   {
 
276
      this(client, DEFAULT_PING_PERIOD);
 
277
   }
 
278
 
 
279
   public ConnectionValidator(Client client, long pingPeriod)
 
280
   {
 
281
      this.client = client;
 
282
      this.locator = client.getInvoker().getLocator();
 
283
      this.pingPeriod = pingPeriod;
 
284
      pingTimeout = DEFAULT_PING_TIMEOUT_INT;
 
285
      listeners = new HashMap();
 
286
      stopped = false;
 
287
      getParameters(client, new HashMap());
 
288
      log.debug(this + " created");
 
289
   }
 
290
   
 
291
   public ConnectionValidator(Client client, Map metadata)
 
292
   {
 
293
      this.client = client;
 
294
      this.locator = client.getInvoker().getLocator();
 
295
      pingPeriod = DEFAULT_PING_PERIOD;
 
296
      pingTimeout = DEFAULT_PING_TIMEOUT_INT;
 
297
      listeners = new HashMap();
 
298
      stopped = false;
 
299
      this.metadata = new HashMap(metadata);
 
300
      getParameters(client, metadata);
 
301
      log.debug(this + " created");
 
302
   }
 
303
 
 
304
   // StoppableTimerTask implementation ------------------------------------------------------------
 
305
 
 
306
   public void stop()
 
307
   {
 
308
      if (stopped)
 
309
      {
 
310
         return;
 
311
      }
 
312
 
 
313
      doStop();
 
314
   }
 
315
 
 
316
   // TimerTask overrides --------------------------------------------------------------------------
 
317
 
 
318
   /**
 
319
    * The action to be performed by this timer task.
 
320
    */
 
321
   public void run()
 
322
   {
 
323
      synchronized (lock)
 
324
      {
 
325
         if (!started)
 
326
         {
 
327
            throw new IllegalStateException(
 
328
                  ConnectionValidator.class.getName() + ".run() should not be " +
 
329
                  "called directly; use " + ConnectionValidator.class.getName() +
 
330
                  ".addConnectionListener() instead.");
 
331
         }
 
332
         
 
333
         if (stopping)
 
334
         {
 
335
            return;
 
336
         }
 
337
         
 
338
         TimerTask tt = new WaitOnConnectionCheckTimerTask();
 
339
 
 
340
         try
 
341
         {
 
342
            timer.schedule(tt, 0);
 
343
         }
 
344
         catch (IllegalStateException e)
 
345
         {
 
346
            log.debug("Unable to schedule TimerTask on existing Timer", e);
 
347
            timer = new Timer(true);
 
348
            timer.schedule(tt, 0);
 
349
         }
 
350
      }
 
351
 
 
352
      try
 
353
      {
 
354
         if(!stopping)
 
355
         {
 
356
            isValid = false;
 
357
 
 
358
            if (tieToLease && client.getLeasePeriod() > 0)
 
359
            {
 
360
               if (trace)
 
361
               {
 
362
                  log.trace(this + " sending PING tied to lease");
 
363
               }
 
364
               isValid = doCheckConnectionWithLease();
 
365
            }
 
366
            else
 
367
            {
 
368
               if (trace) { log.trace(this + " pinging ..."); }
 
369
               isValid = doCheckConnectionWithoutLease();
 
370
            }
 
371
         }
 
372
      }
 
373
      catch (Throwable thr)
 
374
      {
 
375
         log.debug(this + " got throwable while pinging", thr);
 
376
 
 
377
         if (stopLeaseOnFailure)
 
378
         {
 
379
            log.debug(this + " detected connection failure: stopping");
 
380
            cancel();
 
381
         }
 
382
      }
 
383
      finally
 
384
      {
 
385
         synchronized (notificationLock)
 
386
         {
 
387
            notificationLock.notifyAll();
 
388
         }
 
389
      }
 
390
   }
 
391
 
 
392
   public boolean cancel()
 
393
   {
 
394
      return doStop();
 
395
   }
 
396
 
 
397
   // Public ---------------------------------------------------------------------------------------
 
398
 
 
399
   public boolean addConnectionListener(Client client, ConnectionListener listener)
 
400
   {
 
401
      boolean doStart = false;
 
402
      if (listener != null)
 
403
      {
 
404
         synchronized (lock)
 
405
         {
 
406
            if (stopping)
 
407
            {
 
408
               if (trace) log.trace(this + " is stopped. Cannot add ConnectionListener: " + listener + " for " + client);
 
409
               return false;
 
410
            }
 
411
            if (listeners.size() == 0)
 
412
            {
 
413
               doStart = true;
 
414
            }
 
415
            Set s = (Set) listeners.get(listener);
 
416
            if (s == null)
 
417
            {
 
418
               s = new HashSet();
 
419
            }
 
420
            s.add(client);
 
421
            listeners.put(listener, s);
 
422
            log.debug(this + " added ConnectionListener: " + listener + " for " + client);
 
423
         }
 
424
         if (doStart)
 
425
         {
 
426
            start();
 
427
         }
 
428
      }
 
429
      
 
430
      return true;
 
431
   }
 
432
 
 
433
   public boolean removeConnectionListener(Client client, ConnectionListener listener)
 
434
   {
 
435
      if (listener == null)
 
436
      {
 
437
         if (trace) log.trace(this + " ConnectionListener is null");
 
438
         return false;
 
439
      }
 
440
      synchronized (lock)
 
441
      {
 
442
         if (stopping)
 
443
         {
 
444
            if (trace) log.trace(this + " is stopped. It's too late to remove " + listener);
 
445
            return false;
 
446
         }
 
447
         Set s = (Set) listeners.get(listener);
 
448
         if (s == null)
 
449
         {
 
450
            log.debug(this + ": " + listener + " is not registered");
 
451
            return false;
 
452
         }
 
453
         if (s.remove(client))
 
454
         {
 
455
            log.debug(this + " removed ConnectionListener: " + listener + " for " + client);
 
456
         }
 
457
         else
 
458
         {
 
459
            log.debug(this + ": " + listener + " is not registered for " + client);
 
460
            return false;
 
461
         }
 
462
         if (s.size() == 0)
 
463
         {
 
464
            listeners.remove(listener);
 
465
         }
 
466
         if (listeners.size() == 0)
 
467
         {
 
468
            stop();
 
469
         }
 
470
      }
 
471
      return true;
 
472
   }
 
473
 
 
474
   public long getPingPeriod()
 
475
   {
 
476
      if (stopping)
 
477
      {
 
478
         return -1;
 
479
      }
 
480
 
 
481
      return pingPeriod;
 
482
   }
 
483
 
 
484
   public String toString()
 
485
   {
 
486
      return "ConnectionValidator[" + Integer.toHexString(System.identityHashCode(this)) + ":" + clientInvoker + ", pingPeriod=" + pingPeriod + " ms]";
 
487
   }
 
488
   
 
489
   public boolean isStopped()
 
490
   {
 
491
      return stopped;
 
492
   }
 
493
 
 
494
   // Package protected ----------------------------------------------------------------------------
 
495
 
 
496
   void notifyListeners(Throwable thr)
 
497
   {
 
498
      final Throwable t = thr;
 
499
      synchronized (lock)
 
500
      {
 
501
         if (stopping)
 
502
         {
 
503
            return;
 
504
         }
 
505
         stopping = true;
 
506
         if (trace) log.trace(this + " is stopped.  No more listeners will be accepted.");
 
507
         
 
508
         Iterator itr = listeners.keySet().iterator();
 
509
         while (itr.hasNext())
 
510
         {
 
511
            final ConnectionListener listener = (ConnectionListener) itr.next();
 
512
            Set clients = (Set) listeners.get(listener);
 
513
            Iterator itr2 = clients.iterator();
 
514
            while (itr2.hasNext())
 
515
            {
 
516
               final Client client  = (Client) itr2.next();
 
517
               new Thread()
 
518
               {
 
519
                  public void run()
 
520
                  {
 
521
                     log.debug(ConnectionValidator.this + " calling " + listener + ".handleConnectionException() for " + client);
 
522
                     listener.handleConnectionException(t, client);
 
523
                  }
 
524
               }.start();
 
525
            }
 
526
         }
 
527
         
 
528
         listeners.clear();
 
529
      }
 
530
      
 
531
      stop();
 
532
   }
 
533
   
 
534
   // Protected ------------------------------------------------------------------------------------
 
535
 
 
536
   // Private --------------------------------------------------------------------------------------
 
537
 
 
538
   private void getParameters(Client client, Map metadata)
 
539
   {
 
540
      if (checkUseParametersFromLocator(client, metadata))
 
541
      {
 
542
         getParametersFromMap(client.getInvoker().getLocator().getParameters());
 
543
      }
 
544
      getParametersFromMap(client.getConfiguration());
 
545
      getParametersFromMap(metadata);
 
546
      
 
547
      ClientInvoker clientInvoker = client.getInvoker();
 
548
      if (clientInvoker instanceof MicroRemoteClientInvoker)
 
549
      {
 
550
         sharedInvoker = (MicroRemoteClientInvoker) clientInvoker;
 
551
         invokerSessionId = sharedInvoker.getSessionId();
 
552
      }
 
553
      else
 
554
      {
 
555
         throw new RuntimeException("creating a ConnectionValidator on a local connection");
 
556
      }
 
557
      if (stopLeaseOnFailure)
 
558
      {
 
559
         if (sharedInvoker != null)
 
560
         {
 
561
            leasePinger = sharedInvoker.getLeasePinger();
 
562
         }
 
563
      }
 
564
      if (trace) log.trace(this + ": sharedInvoker = " + sharedInvoker + ", leasePinger = " + leasePinger);
 
565
   }
 
566
   
 
567
   private boolean checkUseParametersFromLocator(Client client, Map metadata)
 
568
   {
 
569
      if (client.getInvoker() == null)
 
570
      {
 
571
         return false;
 
572
      }
 
573
      Object o = client.getInvoker().getLocator().getParameters().get(Client.USE_ALL_PARAMS);
 
574
      if (o != null)
 
575
      {
 
576
         if (o instanceof String)
 
577
         {
 
578
            return Boolean.valueOf(((String) o)).booleanValue();
 
579
         }
 
580
         else
 
581
         {
 
582
            log.warn(this + " could not convert " + Client.USE_ALL_PARAMS + " value" +
 
583
            " in InvokerLocator to a boolean: must be a String");
 
584
         }
 
585
      }
 
586
      o = client.getConfiguration().get(Client.USE_ALL_PARAMS);
 
587
      if (o != null)
 
588
      {
 
589
         if (o instanceof String)
 
590
         {
 
591
            return Boolean.valueOf(((String) o)).booleanValue();
 
592
         }
 
593
         else
 
594
         {
 
595
            log.warn(this + " could not convert " + Client.USE_ALL_PARAMS + " value" +
 
596
                     " in Client configuration map to a boolean: must be a String");
 
597
         }
 
598
      }
 
599
      o = metadata.get(Client.USE_ALL_PARAMS);
 
600
      if (o != null)
 
601
      {
 
602
         if (o instanceof String)
 
603
         {
 
604
            return Boolean.valueOf(((String) o)).booleanValue();
 
605
         }
 
606
         else
 
607
         {
 
608
            log.warn(this + " could not convert " + Client.USE_ALL_PARAMS + " value" +
 
609
                     " in metadata map to a boolean: must be a String");
 
610
         }
 
611
      }
 
612
      return false;
 
613
   }
 
614
   
 
615
   private void getParametersFromMap(Map config)
 
616
   {
 
617
      if (config != null)
 
618
      {  
 
619
         Object o = config.get(VALIDATOR_PING_PERIOD);
 
620
         if (o != null)
 
621
         {
 
622
            if (o instanceof String)
 
623
            {
 
624
               try 
 
625
               {
 
626
                  pingPeriod = Long.parseLong((String)o);
 
627
               }
 
628
               catch (Exception e)
 
629
               {
 
630
                  log.warn(this + " could not convert " + VALIDATOR_PING_PERIOD +
 
631
                           " value of " + o + " to a long value");
 
632
               }
 
633
            }
 
634
            else
 
635
            {
 
636
               log.warn(this + " could not convert " + VALIDATOR_PING_PERIOD +
 
637
                        " value of " + o + " to a long value: must be a String");
 
638
            }
 
639
         }
 
640
 
 
641
         o = config.get(VALIDATOR_PING_TIMEOUT);
 
642
         if (o != null)
 
643
         {
 
644
            if (o instanceof String)
 
645
            {
 
646
               try 
 
647
               {
 
648
                  pingTimeout = Integer.parseInt((String)o);
 
649
               }
 
650
               catch (Exception e)
 
651
               {
 
652
                  log.warn(this + " could not convert " + VALIDATOR_PING_TIMEOUT +
 
653
                           " value of " + o + " to a long value");
 
654
               }
 
655
            }
 
656
            else
 
657
            {
 
658
               log.warn(this + " could not convert " + VALIDATOR_PING_TIMEOUT +
 
659
                        " value of " + o + " to a long value: must be a String");
 
660
            }
 
661
         }
 
662
         
 
663
         o = config.get(TIE_TO_LEASE);
 
664
         if (o != null)
 
665
         {
 
666
            if (o instanceof String)
 
667
            {
 
668
               try
 
669
               {
 
670
                  tieToLease = Boolean.valueOf(((String) o)).booleanValue();
 
671
               }
 
672
               catch (Exception e)
 
673
               {
 
674
                  log.warn(this + " could not convert " + TIE_TO_LEASE + " value" +
 
675
                        " to a boolean: " + o);
 
676
               }
 
677
            }
 
678
            else
 
679
            {
 
680
               log.warn(this + " could not convert " + TIE_TO_LEASE + " value" +
 
681
               " to a boolean: must be a String");
 
682
            }
 
683
         }
 
684
 
 
685
         o = config.get(STOP_LEASE_ON_FAILURE);
 
686
         if (o != null)
 
687
         {
 
688
            if (o instanceof String)
 
689
            {
 
690
               try
 
691
               {
 
692
                  stopLeaseOnFailure = Boolean.valueOf(((String) o)).booleanValue();
 
693
               }
 
694
               catch (Exception e)
 
695
               {
 
696
                  log.warn(this + " could not convert " + STOP_LEASE_ON_FAILURE + " value" +
 
697
                        " to a boolean: " + o);
 
698
               }
 
699
            }
 
700
            else
 
701
            {
 
702
               log.warn(this + " could not convert " + STOP_LEASE_ON_FAILURE + " value" +
 
703
               " to a boolean: must be a String");
 
704
            }
 
705
         }
 
706
         
 
707
         o = config.get(FAILURE_DISCONNECT_TIMEOUT);
 
708
         if (trace) log.trace(this + " \"failureDisconnectTimeout\" set to " + o);
 
709
         if (o != null)
 
710
         {
 
711
            if (o instanceof String)
 
712
            {
 
713
               try
 
714
               {
 
715
                  failureDisconnectTimeout = Integer.valueOf(((String) o)).intValue();
 
716
                  if (trace) log.trace(this + " setting failureDisconnectTimeout to " + failureDisconnectTimeout);
 
717
               }
 
718
               catch (Exception e)
 
719
               {
 
720
                  log.warn(this + " could not convert " + FAILURE_DISCONNECT_TIMEOUT + " value" +
 
721
                        " to an int: " + o);
 
722
               }
 
723
            }
 
724
            else
 
725
            {
 
726
               log.warn(this + " could not convert " + FAILURE_DISCONNECT_TIMEOUT + " value" +
 
727
               " to an int: must be a String");
 
728
            }
 
729
         }
 
730
         o = config.get(Remoting.USE_CLIENT_CONNECTION_IDENTITY);
 
731
         if (o != null)
 
732
         {
 
733
            if (o instanceof String)
 
734
            {
 
735
               try
 
736
               {
 
737
                  useClientConnectionIdentity = Boolean.valueOf(((String) o)).booleanValue();
 
738
               }
 
739
               catch (Exception e)
 
740
               {
 
741
                  log.warn(this + " could not convert " + Remoting.USE_CLIENT_CONNECTION_IDENTITY + " value" +
 
742
                           " to a boolean: " + o);
 
743
               }
 
744
            }
 
745
            else
 
746
            {
 
747
               log.warn(this + " could not convert " + Remoting.USE_CLIENT_CONNECTION_IDENTITY + " value" +
 
748
                        " to a boolean: must be a String");
 
749
            }
 
750
         }
 
751
      }
 
752
   }
 
753
   
 
754
   private void start()
 
755
   {
 
756
      metadata.put(ServerInvoker.TIMEOUT, Integer.toString(pingTimeout));
 
757
      configMap = createPingConfig(client.getConfiguration(), metadata);
 
758
      log.debug(this + ": pingPeriod:  " + this.pingPeriod);
 
759
      log.debug(this + ": pingTimeout: " + this.pingTimeout);
 
760
      log.debug(this + ": ping retries: " + configMap.get("NumberOfCallRetries"));
 
761
 
 
762
      try
 
763
      {
 
764
         try
 
765
         {
 
766
            clientInvoker = (ClientInvoker) AccessController.doPrivileged( new PrivilegedExceptionAction()
 
767
            {
 
768
               public Object run() throws Exception
 
769
               {
 
770
                  return InvokerRegistry.createClientInvoker(locator, configMap);
 
771
               }
 
772
            });
 
773
         }
 
774
         catch (PrivilegedActionException pae)
 
775
         {
 
776
            throw pae.getException();
 
777
         }
 
778
      }
 
779
      catch (Exception e)
 
780
      {
 
781
         log.debug("Unable to create client invoker for locator: " + locator);
 
782
         throw new RuntimeException("Unable to create client invoker for locator: " + locator, e);
 
783
      }
 
784
 
 
785
      if (!clientInvoker.isConnected())
 
786
      {
 
787
         if (trace) { log.trace("inner client invoker not connected, connecting ..."); }
 
788
         clientInvoker.connect();
 
789
      }
 
790
      
 
791
      started = true;
 
792
      timer = new Timer(true);
 
793
      
 
794
      try
 
795
      {
 
796
          TimerUtil.schedule(this, pingPeriod);
 
797
      }
 
798
      catch (Exception e)
 
799
      {
 
800
         log.error(this + " unable to schedule on TimerUtil", e);
 
801
         started = false;
 
802
         timer = null;
 
803
         return;
 
804
      }
 
805
      log.debug(this + " started");
 
806
   }
 
807
   
 
808
   private boolean doCheckConnectionWithLease() throws Throwable
 
809
   {
 
810
      boolean pingWorked = false;
 
811
 
 
812
      try
 
813
      {
 
814
         Map metadata = new HashMap();
 
815
         metadata.put(ServerInvoker.INVOKER_SESSION_ID, invokerSessionId);
 
816
         InvocationRequest ir =
 
817
            new InvocationRequest(null, Subsystem.SELF, "$PING$", metadata, null, null);
 
818
 
 
819
         if (trace) { log.trace("pinging, sending " + ir + " over " + clientInvoker); }
 
820
 
 
821
         Object o = clientInvoker.invoke(ir);
 
822
         if (o instanceof Boolean && !((Boolean) o).booleanValue())
 
823
         {
 
824
            // Server indicates lease has stopped.
 
825
            throw new Exception();
 
826
         }
 
827
 
 
828
         if (trace) { log.trace("ConnectionValidator got successful ping using " + clientInvoker);}
 
829
 
 
830
         pingWorked = true;
 
831
      }
 
832
      catch (Throwable t)
 
833
      {
 
834
         log.debug("ConnectionValidator failed to ping via " + clientInvoker, t);
 
835
      }
 
836
 
 
837
      return pingWorked;
 
838
   }
 
839
   
 
840
   private boolean doCheckConnectionWithoutLease() throws Throwable
 
841
   {
 
842
      boolean pingWorked = false;
 
843
 
 
844
      try
 
845
      {
 
846
         // Sending null client id as don't want to trigger lease on server side. This also means
 
847
         // that client connection validator will NOT impact client lease, so can not depend on it
 
848
         // to maintain client lease with the server.
 
849
         InvocationRequest ir =
 
850
            new InvocationRequest(null, Subsystem.SELF, "$PING$", null, null, null);
 
851
 
 
852
         if (trace) { log.trace("pinging, sending " + ir + " over " + clientInvoker); }
 
853
 
 
854
         clientInvoker.invoke(ir);
 
855
 
 
856
         if (trace) { log.trace("ConnectionValidator got successful ping using " + clientInvoker);}
 
857
 
 
858
         pingWorked = true;
 
859
      }
 
860
      catch (Throwable t)
 
861
      {
 
862
         log.debug("ConnectionValidator failed to ping via " + clientInvoker, t);
 
863
      }
 
864
 
 
865
      return pingWorked;
 
866
   }
 
867
 
 
868
   private boolean doStop()
 
869
   {
 
870
      if (trace) log.trace("entering doStop()");
 
871
      synchronized(lock)
 
872
      {
 
873
         if (stopped)
 
874
         {
 
875
            return false;
 
876
         }
 
877
         
 
878
         if (!listeners.isEmpty())
 
879
         {
 
880
            listeners.clear();
 
881
         }
 
882
         stopping = true;
 
883
         stopped = true;
 
884
         timer = null;
 
885
      }
 
886
 
 
887
      if (clientInvoker != null)
 
888
      {
 
889
         AccessController.doPrivileged( new PrivilegedAction()
 
890
         {
 
891
            public Object run()
 
892
            {
 
893
               InvokerRegistry.destroyClientInvoker(locator, configMap);
 
894
               return null;
 
895
            }
 
896
         });
 
897
      }
 
898
 
 
899
      TimerUtil.unschedule(this);
 
900
 
 
901
      boolean result = super.cancel();
 
902
      log.debug(this + " stopped, returning " + result);
 
903
      return result;
 
904
   }
 
905
   
 
906
   // Inner classes --------------------------------------------------------------------------------
 
907
 
 
908
   private class WaitOnConnectionCheckTimerTask extends TimerTask
 
909
   {
 
910
      public void run()
 
911
      {
 
912
         long start = System.currentTimeMillis();
 
913
         synchronized (notificationLock)
 
914
         {
 
915
            while (true)
 
916
            {
 
917
               int elapsed = (int) (System.currentTimeMillis() - start);
 
918
               int wait = pingTimeout - elapsed;
 
919
               if (wait <= 0)
 
920
               {
 
921
                  break;
 
922
               }
 
923
               
 
924
               try
 
925
               {
 
926
                  notificationLock.wait(wait);
 
927
                  break;
 
928
               }
 
929
               catch (InterruptedException e)
 
930
               {
 
931
                  continue;
 
932
               }
 
933
            }
 
934
         }
 
935
         
 
936
         if (!isValid)
 
937
         {
 
938
            log.debug(ConnectionValidator.this + "'s connection is invalid");
 
939
            ConnectionValidator.super.cancel();
 
940
            
 
941
            if (stopLeaseOnFailure)
 
942
            {
 
943
               if (trace) log.trace(ConnectionValidator.this + " detected connection failure: stopping LeasePinger");
 
944
               if (leasePinger != null)
 
945
               {
 
946
                  log.debug(ConnectionValidator.this + " shutting down lease pinger: " + leasePinger);
 
947
                  int disconnectTimeout = (failureDisconnectTimeout == -1) ? client.getDisconnectTimeout() : failureDisconnectTimeout;
 
948
                  if (trace) log.trace(ConnectionValidator.this + " disconnectTimeout: " + disconnectTimeout);
 
949
                  sharedInvoker.terminateLease(null, disconnectTimeout, leasePinger);
 
950
               }
 
951
               else
 
952
               {
 
953
                  if (trace) log.trace(ConnectionValidator.this + ": lease pinger == null: perhaps leasing is not enabled for this connection");
 
954
                  notifyListeners(new Exception("Could not connect to server!"));
 
955
               }
 
956
               
 
957
               cancel();
 
958
            }
 
959
            if (!useClientConnectionIdentity)
 
960
            {
 
961
                notifyListeners(new Exception("Could not connect to server!"));
 
962
            }
 
963
         }
 
964
      }
 
965
   }
 
966
   
 
967
   private static class ConnectionCheckThread extends Thread
 
968
   {
 
969
      private InvocationRequest ir;
 
970
      private ClientInvoker clientInvoker;
 
971
      private boolean isValid;
 
972
 
 
973
      public ConnectionCheckThread(ClientInvoker clientInvoker, InvocationRequest ir)
 
974
      {
 
975
         this.clientInvoker = clientInvoker;
 
976
         this.ir = ir;
 
977
         setDaemon(true);
 
978
      }
 
979
      
 
980
      public void run()
 
981
      {
 
982
         try
 
983
         {
 
984
            if (trace) { log.trace("pinging, sending " + ir + " over " + clientInvoker); }
 
985
            clientInvoker.invoke(ir);
 
986
            isValid = true;
 
987
            if (trace) { log.trace("ConnectionValidator got successful ping using " + clientInvoker);}
 
988
         }
 
989
         catch (Throwable t)
 
990
         {
 
991
            log.debug("ConnectionValidator failed to ping via " + clientInvoker, t);
 
992
         }
 
993
      }
 
994
      
 
995
      public boolean isValid()
 
996
      {
 
997
         return isValid;
 
998
      }
 
999
   }
 
1000
}
 
 
b'\\ No newline at end of file'