1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.river.norm;
19
20 import org.apache.river.lease.BasicRenewalFailureEvent;
21 import org.apache.river.logging.Levels;
22 import org.apache.river.norm.event.EventFactory;
23 import org.apache.river.proxy.ConstrainableProxyUtil;
24 import java.io.IOException;
25 import java.io.Serializable;
26 import java.lang.reflect.Method;
27 import java.rmi.MarshalledObject;
28 import java.rmi.RemoteException;
29 import java.rmi.UnmarshalException;
30 import java.util.List;
31 import java.util.logging.Level;
32 import java.util.logging.Logger;
33 import net.jini.core.constraint.RemoteMethodControl;
34 import net.jini.core.event.RemoteEvent;
35 import net.jini.core.lease.Lease;
36 import net.jini.core.lease.LeaseDeniedException;
37 import net.jini.core.lease.LeaseMap;
38 import net.jini.core.lease.UnknownLeaseException;
39 import net.jini.io.MarshalledInstance;
40 import net.jini.lease.LeaseRenewalSet;
41 import net.jini.security.ProxyPreparer;
42 import org.apache.river.api.io.AtomicMarshalledInstance;
43 import org.apache.river.api.io.AtomicSerial;
44 import org.apache.river.api.io.AtomicSerial.GetArg;
45
46
47
48
49
50
51
52
53
54
55
56
57
58 @AtomicSerial
59 class ClientLeaseWrapper implements Lease, Serializable {
60 private static final long serialVersionUID = 2;
61
62
63 private static final Logger logger = Logger.getLogger("org.apache.river.norm");
64
65
66 private static final Method[] leaseToLeaseMethods;
67 static {
68 try {
69 Method cancelMethod =
70 Lease.class.getMethod("cancel", new Class[] { });
71 Method renewMethod =
72 Lease.class.getMethod("renew", new Class[] { long.class });
73 leaseToLeaseMethods = new Method[] {
74 cancelMethod, cancelMethod, renewMethod, renewMethod };
75 } catch (NoSuchMethodException e) {
76 throw new NoSuchMethodError(e.getMessage());
77 }
78 }
79
80
81
82
83
84
85
86 private Throwable lastFailure = null;
87
88
89
90
91
92 private MarshalledInstance marshalledClientLease;
93
94
95
96
97
98 private long clientLeaseExpiration;
99
100
101
102
103
104 private final long UID;
105
106
107
108
109
110 private long membershipExpiration;
111
112
113
114
115
116 private long renewDuration;
117
118
119
120
121 private transient LeaseSet set;
122
123
124
125
126
127 private transient Lease clientLease;
128
129
130
131
132
133
134 private transient ProxyPreparer recoveredLeasePreparer;
135
136
137
138
139
140 private transient boolean renewalPending = false;
141
142
143
144
145
146 private transient List renewedList;
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162 ClientLeaseWrapper(Lease clientLease, long UID, List renewedList,
163 LeaseSet leaseSet, long membershipDuration,
164 long renewDuration, long now)
165 throws IOException
166 {
167 this.renewedList = renewedList;
168 this.UID = UID;
169 this.clientLease = clientLease;
170
171 set = leaseSet;
172
173 clientLeaseExpiration = clientLease.getExpiration();
174 clientLease.setSerialFormat(Lease.ABSOLUTE);
175 marshalledClientLease = new AtomicMarshalledInstance(clientLease);
176
177 this.renewDuration = renewDuration;
178 membershipExpiration = calcMembershipExpiration(membershipDuration, now);
179 }
180
181 ClientLeaseWrapper(GetArg arg) throws IOException {
182 this((Throwable) arg.get("lastFailure", null),
183 (MarshalledInstance) arg.get("marshalledClientLease", null),
184 arg.get("clientLeaseExpiration", 0L),
185 arg.get("UID", 0L),
186 arg.get("membershipExpiration", 0L),
187 arg.get("renewDuration", 0L));
188 }
189
190 ClientLeaseWrapper(Throwable lastFailure,
191 MarshalledInstance marshalledClientLease,
192 long clientLeaseExpiration,
193 long UID,
194 long membershipExpiration,
195 long renewDuration)
196 {
197 this.lastFailure = lastFailure;
198 this.marshalledClientLease = marshalledClientLease;
199 this.clientLeaseExpiration = clientLeaseExpiration;
200 this.UID = UID;
201 this.membershipExpiration = membershipExpiration;
202 this.renewDuration = renewDuration;
203 }
204
205
206
207
208
209 private static long calcMembershipExpiration(long membershipDuration, long now) {
210 long membershipExpiration;
211 if (membershipDuration == Lease.FOREVER) {
212 membershipExpiration = Lease.FOREVER;
213 } else {
214 membershipExpiration = membershipDuration + now;
215
216 if (membershipExpiration < 0)
217 membershipExpiration = Long.MAX_VALUE;
218 }
219 return membershipExpiration;
220 }
221
222
223
224
225
226 void update(long membershipDuration, long renewDuration, long now) {
227 this.renewDuration = renewDuration;
228 membershipExpiration = calcMembershipExpiration(membershipDuration, now);
229 }
230
231
232
233
234 long getMembershipExpiration() {
235 return membershipExpiration;
236 }
237
238
239
240
241 long getRenewDuration() {
242 return renewDuration;
243 }
244
245
246
247
248 synchronized void clearRenewed() {
249 renewalPending = false;
250 }
251
252
253
254
255
256
257 Lease getClientLease() {
258 if (clientLease == null) {
259 Lease unmarshalledLease = null;
260 try {
261 unmarshalledLease = (Lease) marshalledClientLease.get(false);
262 } catch (IOException e) {
263 logger.log(Levels.HANDLED,
264 "Problem unmarshalling lease -- will retry later",
265 e);
266 } catch (ClassNotFoundException e) {
267 logger.log(Levels.HANDLED,
268 "Problem unmarshalling lease -- will retry later",
269 e);
270 }
271 if (unmarshalledLease != null) {
272 try {
273 clientLease = (Lease) recoveredLeasePreparer.prepareProxy(
274 unmarshalledLease);
275 } catch (RemoteException e) {
276 logger.log(Levels.HANDLED,
277 "Problem preparing lease -- will retry later",
278 e);
279 } catch (SecurityException e) {
280 logger.log(Levels.HANDLED,
281 "Problem preparing lease -- will retry later",
282 e);
283 }
284 }
285 }
286 return clientLease;
287 }
288
289
290
291
292
293
294
295
296 MarshalledInstance getMarshalledClientLease() {
297 final Lease cl = getClientLease();
298
299 if (cl == null) {
300
301
302 return marshalledClientLease;
303 } else {
304 try {
305 cl.setSerialFormat(Lease.DURATION);
306 return new MarshalledInstance(cl);
307 } catch (IOException e) {
308
309 return marshalledClientLease;
310 } finally {
311 cl.setSerialFormat(Lease.ABSOLUTE);
312 }
313 }
314 }
315
316
317 public boolean equals(Object that) {
318 if (that instanceof ClientLeaseWrapper) {
319 return UID == ((ClientLeaseWrapper) that).UID;
320 } else {
321 return false;
322 }
323 }
324
325
326 public int hashCode() {
327 return (int) UID;
328 }
329
330
331 public String toString() {
332 return "CLW:" + UID + " exp:" + clientLeaseExpiration + " dexp:" +
333 membershipExpiration + " dur:" + renewDuration + " failure:" +
334 lastFailure;
335 }
336
337
338
339 public long getExpiration() {
340 final Lease cl = getClientLease();
341 if (cl == null) {
342
343 synchronized (this) {
344 return clientLeaseExpiration;
345 }
346 } else {
347 return cl.getExpiration();
348 }
349 }
350
351
352
353
354
355 public void cancel() {
356 throw new UnsupportedOperationException("ClientLeaseWrapper.cancel:" +
357 "LRS should not being canceling client leases ");
358 }
359
360
361
362
363 Throwable getLastFailure() {
364 return lastFailure;
365 }
366
367
368
369
370
371 private synchronized boolean testAndSetRenewalPending() {
372 final boolean result = renewalPending;
373 renewalPending = true;
374 return result;
375 }
376
377
378
379
380
381
382 private void changed() {
383 if (!testAndSetRenewalPending()) {
384 synchronized (renewedList) {
385 renewedList.add(this);
386 renewedList.notifyAll();
387 }
388 }
389 }
390
391
392
393
394
395 boolean ensureCurrent(long now) {
396 return set.ensureCurrent(now);
397 }
398
399
400
401
402
403
404
405
406 void failedRenewal(Throwable t) {
407 lastFailure = t;
408 changed();
409 }
410
411
412
413
414
415
416
417 void successfulRenewal() {
418 lastFailure = null;
419
420
421
422
423
424
425
426
427
428 try {
429 marshalledClientLease = new MarshalledInstance(clientLease);
430 } catch (IOException e) {
431
432
433
434
435
436
437
438
439
440 logger.log(Level.WARNING,
441 "IOException while marshalling client lease " +
442 "after renewal",
443 e);
444 }
445
446
447 synchronized (this) {
448 clientLeaseExpiration = clientLease.getExpiration();
449 }
450
451
452
453 changed();
454 }
455
456
457
458 public void renew(long duration)
459 throws LeaseDeniedException, UnknownLeaseException, RemoteException
460 {
461
462 if (!set.ensureCurrent(System.currentTimeMillis())) {
463
464
465 throw LRMEventListener.EXPIRED_SET_EXCEPTION;
466
467
468
469
470 }
471
472
473 if (clientLease == null) {
474
475 Lease unmarshalledLease;
476 try {
477 unmarshalledLease = (Lease) marshalledClientLease.get(false);
478 } catch (IOException e) {
479 UnmarshalException t = new UnmarshalException(
480 "ClientLeaseWrapper.renew:Could not unmarshal client " +
481 "lease for renewal", e);
482 failedRenewal(t);
483 throw t;
484 } catch (ClassNotFoundException e) {
485 UnmarshalException t = new UnmarshalException(
486 "ClientLeaseWrapper.renew:Could not unmarshal client " +
487 "lease for renewal", e);
488 failedRenewal(t);
489 throw t;
490 }
491
492 try {
493 clientLease = (Lease) recoveredLeasePreparer.prepareProxy(
494 unmarshalledLease);
495 } catch (RemoteException e) {
496 failedRenewal(e);
497 throw e;
498 } catch (SecurityException e) {
499 failedRenewal(e);
500 throw e;
501 }
502 }
503
504
505
506
507
508 try {
509 clientLease.renew(duration);
510 } catch (LeaseDeniedException e) {
511 failedRenewal(e);
512 throw e;
513 } catch (UnknownLeaseException e) {
514 failedRenewal(e);
515 throw e;
516 } catch (RemoteException e) {
517 failedRenewal(e);
518 throw e;
519 } catch (RuntimeException e) {
520 failedRenewal(e);
521 throw e;
522 } catch (Error e) {
523 failedRenewal(e);
524 throw e;
525 }
526
527
528 successfulRenewal();
529 }
530
531
532
533
534
535
536 public void setSerialFormat(int format) {
537 throw new UnsupportedOperationException(
538 "ClientLeaseWrapper.setSerialFormat:" +
539 "LRS should not be setting serial format through the wrapper");
540 }
541
542
543
544
545
546
547
548 public int getSerialFormat() {
549 throw new UnsupportedOperationException(
550 "ClientLeaseWrapper.setSerialFormat:" +
551 "LRS should not be setting serial format through the wrapper");
552 }
553
554
555 public LeaseMap<Lease, Long> createLeaseMap(long duration) {
556 if (isDeformed()) {
557 return new DeformedClientLeaseMapWrapper(this, duration);
558 } else {
559 return new ClientLeaseMapWrapper(this, duration);
560 }
561 }
562
563
564
565
566
567
568
569
570
571 public boolean canBatch(Lease lease) {
572 if (!(lease instanceof ClientLeaseWrapper))
573 return false;
574
575 final ClientLeaseWrapper clw = (ClientLeaseWrapper) lease;
576
577 if (set.isolateSets() && !set.equals(clw.set))
578 return false;
579
580 if (isDeformed() || clw.isDeformed())
581 return false;
582
583 Lease clientLease = getClientLease();
584 Lease otherClientLease = clw.getClientLease();
585 return sameConstraints(clientLease, otherClientLease) &&
586 clientLease.canBatch(otherClientLease);
587 }
588
589
590
591
592
593
594 private static boolean sameConstraints(Lease l1, Lease l2) {
595 if (!(l1 instanceof RemoteMethodControl)) {
596 return !(l2 instanceof RemoteMethodControl);
597 } else if (!(l2 instanceof RemoteMethodControl)) {
598 return false;
599 } else {
600 return ConstrainableProxyUtil.equivalentConstraints(
601 ((RemoteMethodControl) l1).getConstraints(),
602 ((RemoteMethodControl) l2).getConstraints(),
603 leaseToLeaseMethods);
604 }
605 }
606
607
608
609
610
611
612
613
614
615
616
617
618
619 void recoverTransient(List renewedList, UIDGenerator generator,
620 LeaseSet leaseSet,
621 ProxyPreparer recoveredLeasePreparer)
622 {
623 this.renewedList = renewedList;
624 set = leaseSet;
625 generator.inUse(UID);
626 this.recoveredLeasePreparer = recoveredLeasePreparer;
627
628 getClientLease();
629
630
631 set.addToLeaseTable(this);
632 }
633
634
635
636
637 boolean isDeformed() {
638 return getClientLease() == null;
639 }
640
641
642
643
644 LeaseSet getLeaseSet() {
645 return set;
646 }
647
648
649
650
651
652
653
654
655
656
657
658 EventFactory newFailureFactory(LeaseRenewalSet source) throws IOException {
659 final MarshalledInstance ml = getMarshalledClientLease();
660
661 MarshalledInstance mt = null;
662 if (lastFailure != null)
663 mt = new MarshalledInstance(lastFailure);
664
665 return new FailureFactory(source, ml, mt);
666 }
667
668
669
670
671
672
673
674
675
676 private static class FailureFactory implements EventFactory {
677
678 private final LeaseRenewalSet source;
679
680
681 final private MarshalledInstance marshalledLease;
682
683
684
685
686
687 final private MarshalledInstance marshalledThrowable;
688
689
690
691
692
693
694
695
696
697 private FailureFactory(LeaseRenewalSet source,
698 MarshalledInstance marshalledLease,
699 MarshalledInstance marshalledThrowable)
700 {
701 this.source = source;
702 this.marshalledLease = marshalledLease;
703 this.marshalledThrowable = marshalledThrowable;
704 }
705
706
707 public RemoteEvent createEvent(long eventID,
708 long seqNum,
709 MarshalledObject handback)
710 {
711 return new BasicRenewalFailureEvent(source, seqNum,
712 handback, marshalledLease, marshalledThrowable);
713 }
714 }
715 }