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.landlord.LeasedResource;
21 import org.apache.river.norm.event.EventFactory;
22 import org.apache.river.norm.event.EventType;
23 import org.apache.river.norm.event.EventTypeGenerator;
24 import org.apache.river.norm.event.SendMonitor;
25 import org.apache.river.norm.proxy.*;
26 import java.io.IOException;
27 import java.io.InvalidObjectException;
28 import java.io.ObjectInputStream;
29 import java.io.Serializable;
30 import java.rmi.MarshalledObject;
31 import java.security.AccessControlContext;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.HashSet;
35 import java.util.Iterator;
36 import java.util.List;
37 import java.util.Set;
38 import net.jini.core.event.EventRegistration;
39 import net.jini.core.event.RemoteEvent;
40 import net.jini.core.event.RemoteEventListener;
41 import net.jini.core.lease.Lease;
42 import net.jini.export.ProxyAccessor;
43 import net.jini.id.Uuid;
44 import net.jini.io.MarshalledInstance;
45 import net.jini.lease.ExpirationWarningEvent;
46 import net.jini.lease.LeaseRenewalSet;
47 import net.jini.security.ProxyPreparer;
48 import org.apache.river.api.io.AtomicSerial;
49 import org.apache.river.api.io.AtomicSerial.GetArg;
50
51
52
53
54
55
56
57
58 @AtomicSerial
59 class LeaseSet implements Serializable, LeasedResource {
60 private static final long serialVersionUID = 2;
61
62
63
64
65
66 private long expiration;
67
68
69
70
71
72
73 private transient ExpirationTime expiration2;
74
75
76
77
78
79 private final Uuid ID;
80
81
82
83
84
85 private final Set<ClientLeaseWrapper> leases;
86
87
88
89
90 private volatile transient LeaseTable leaseTable;
91
92
93
94
95
96 private volatile long minWarning = NormServer.NO_LISTENER;
97
98
99
100
101
102 private EventType warningEventType;
103
104
105
106
107
108 private volatile long warningSeqNum;
109
110
111
112
113
114 private EventType failureEventType;
115
116
117
118
119 private transient PersistentStore store;
120
121
122
123
124 private transient NormServerBaseImpl normServerBaseImpl;
125
126
127
128
129
130
131
132
133
134
135
136
137 LeaseSet(Uuid ID,
138 EventTypeGenerator generator,
139 PersistentStore store,
140 NormServerBaseImpl normServerBaseImpl,
141 AccessControlContext context)
142 {
143 this.leases = new HashSet<ClientLeaseWrapper>();
144 this.store = store;
145 this.normServerBaseImpl = normServerBaseImpl;
146 this.ID = ID;
147
148
149 expiration = 0;
150 expiration2 = new ExpirationTime(expiration);
151 leaseTable = new LeaseTable();
152
153 final SendMonitor sendMonitor =
154 normServerBaseImpl.newSendMonitor(this);
155
156 try {
157 warningEventType =
158 generator.newEventType(sendMonitor,
159 LeaseRenewalSet.EXPIRATION_WARNING_EVENT_ID, context);
160 failureEventType =
161 generator.newEventType(sendMonitor,
162 LeaseRenewalSet.RENEWAL_FAILURE_EVENT_ID, context);
163 } catch (IOException e) {
164
165
166 throw new AssertionError();
167 }
168 }
169
170 LeaseSet(GetArg arg) throws IOException {
171 this( arg.get("expiration", 0L),
172 (Uuid) arg.get("ID", null),
173 check((Set<ClientLeaseWrapper>) arg.get("leases", null)),
174 arg.get("minWarning", 0L),
175 (EventType) arg.get("warningEventType", null),
176 arg.get("warningSeqNum", 0L),
177 (EventType) arg.get("failureEventType", null)
178 );
179
180 expiration2 = new ExpirationTime(expiration);
181
182
183
184 leaseTable = new LeaseTable();
185 }
186
187 LeaseSet(long expiration,
188 Uuid ID,
189 Set leases,
190 long minWarning,
191 EventType warningEventType,
192 long warningSeqNum,
193 EventType failureEventType)
194 {
195 this.expiration = expiration;
196 this.ID = ID;
197 this.leases = new HashSet<ClientLeaseWrapper>(leases);
198 this.minWarning = minWarning;
199 this.warningEventType = warningEventType;
200 this.warningSeqNum = warningSeqNum;
201 this.failureEventType = failureEventType;
202 }
203
204 private static Set<ClientLeaseWrapper> check(Set<ClientLeaseWrapper> leases)
205 throws InvalidObjectException
206 {
207 try {
208 Set<ClientLeaseWrapper> checkLeases = Collections.checkedSet(
209 new HashSet<ClientLeaseWrapper>(leases.size()), ClientLeaseWrapper.class);
210 checkLeases.addAll(leases);
211 return checkLeases;
212 } catch (ClassCastException e){
213 InvalidObjectException ex = new InvalidObjectException(
214 "leases must only contain instances of ClientLeaseWrapper");
215 ex.initCause(e);
216 throw ex;
217 }
218 }
219
220
221
222
223 private void readObject(ObjectInputStream in)
224 throws IOException, ClassNotFoundException
225 {
226 in.defaultReadObject();
227 synchronized (this){
228
229 expiration2 = new ExpirationTime(expiration);
230
231
232
233 leaseTable = new LeaseTable();
234 }
235 }
236
237
238
239
240
241
242
243
244
245
246
247
248
249 Iterator restoreTransientState(EventTypeGenerator generator,
250 PersistentStore store,
251 NormServerBaseImpl normServerBaseImpl,
252 ProxyPreparer recoveredListenerPreparer,
253 AccessControlContext context)
254 {
255 this.normServerBaseImpl = normServerBaseImpl;
256 this.store = store;
257
258 final SendMonitor sendMonitor =
259 normServerBaseImpl.newSendMonitor(this);
260 warningEventType.restoreTransientState(
261 generator, sendMonitor, recoveredListenerPreparer, context);
262 failureEventType.restoreTransientState(
263 generator, sendMonitor, recoveredListenerPreparer, context);
264
265
266
267
268
269
270
271 warningEventType.setLastSequenceNumber(warningSeqNum +
272 Integer.MAX_VALUE);
273 normServerBaseImpl.updateLeaseCount(leases.size());
274 return leases.iterator();
275 }
276
277
278
279
280
281 ClientLeaseWrapper getClientLeaseWrapper(Lease clientLease) {
282 return leaseTable.get(clientLease);
283 }
284
285
286
287
288
289
290 private boolean replace(ClientLeaseWrapper clw) {
291 boolean found = leases.remove(clw);
292 leases.add(clw);
293 return !found;
294 }
295
296
297
298
299
300 void update(ClientLeaseWrapper clw) {
301 boolean added = replace(clw);
302 leaseTable.put(clw);
303 final Object u = new UpdateClientLease(this, clw);
304 store.update(u);
305 if (added) {
306 normServerBaseImpl.updateLeaseCount(1);
307 }
308 }
309
310
311
312
313
314
315
316 void addToLeaseTable(ClientLeaseWrapper clw) {
317 leaseTable.put(clw);
318 }
319
320
321
322
323 boolean doesContainWrapper(ClientLeaseWrapper clw) {
324 return leases.contains(clw);
325 }
326
327
328
329
330
331 private boolean removeInternal(ClientLeaseWrapper clw) {
332 if (leases.remove(clw)) {
333 leaseTable.remove(clw);
334 return true;
335 }
336 return false;
337 }
338
339
340
341
342
343
344
345
346 boolean remove(ClientLeaseWrapper clw) {
347 if (!removeInternal(clw)) {
348
349
350 return false;
351 }
352
353
354
355 final Object u = new RemoveClientLease(this, clw);
356 store.update(u);
357 normServerBaseImpl.updateLeaseCount(-1);
358
359 return (clw.getMembershipExpiration() > System.currentTimeMillis());
360 }
361
362
363
364
365
366 Set destroy() {
367 setExpiration(-1);
368 final Object u = new CancelLeaseSet(getUuid());
369 store.update(u);
370 normServerBaseImpl.updateLeaseCount(-leases.size());
371 return leases;
372 }
373
374
375
376
377
378
379
380 MarshalledInstance[] getLeases() {
381 final long now = System.currentTimeMillis();
382 final Iterator i = leases.iterator();
383 final List l = new ArrayList(leases.size());
384
385 while (i.hasNext()) {
386 final ClientLeaseWrapper clw = (ClientLeaseWrapper) i.next();
387
388
389
390 if (now > clw.getMembershipExpiration())
391 continue;
392
393 l.add(clw.getMarshalledClientLease());
394 }
395
396 if (l.isEmpty()) {
397 return null;
398 } else {
399 return (MarshalledInstance[]) l.toArray(
400 new MarshalledInstance[l.size()]);
401 }
402 }
403
404
405
406
407
408
409
410
411
412
413
414 EventRegistration setExpirationWarningListener(
415 RemoteEventListener listener,
416 long minWarning,
417 MarshalledObject handback)
418 throws IOException
419 {
420 synchronized (this){
421 this.minWarning = minWarning;
422 }
423 warningEventType.setListener(listener, handback);
424
425 final Object u = new WarningEventRegistration(this);
426 store.update(u);
427
428 if (listener == null)
429 return null;
430
431 final SetProxy proxy = newSetProxy();
432
433 return new EventRegistration(
434 warningEventType.getEventID(),
435 proxy,
436 proxy.getRenewalSetLease(),
437 warningEventType.getLastSequenceNumber());
438 }
439
440
441
442
443
444
445
446
447
448 EventRegistration setRenewalFailureListener(
449 RemoteEventListener listener,
450 MarshalledObject handback)
451 throws IOException
452 {
453 failureEventType.setListener(listener, handback);
454
455 final Object u = new FailureEventRegistration(this);
456 store.update(u);
457
458 if (listener == null)
459 return null;
460
461 final SetProxy proxy = newSetProxy();
462
463 return new EventRegistration(
464 failureEventType.getEventID(),
465 proxy,
466 proxy.getRenewalSetLease(),
467 failureEventType.getLastSequenceNumber());
468 }
469
470
471
472
473
474
475
476 void renewalFailure(ClientLeaseWrapper clw) {
477 if (!removeInternal(clw)) {
478
479
480
481 return;
482 }
483
484 Object u;
485 EventFactory factory;
486 long seqNum;
487
488 try {
489 factory = clw.newFailureFactory(newSetProxy());
490 seqNum = failureEventType.sendEvent(factory);
491 } catch (IOException e) {
492
493
494
495
496
497
498
499 seqNum = failureEventType.bumpSequenceNumber();
500 }
501
502 u = new RenewalFailure(this, clw, seqNum);
503 store.update(u);
504 }
505
506
507
508
509 void sendWarningEvent() {
510 warningSeqNum = warningEventType.sendEvent(new WarningFactory(this));
511 }
512
513
514
515
516
517 private static class WarningFactory implements EventFactory {
518 private static final long serialVersionUID = 1L;
519
520
521 final private SetProxy proxy;
522
523
524
525
526
527 WarningFactory(LeaseSet set) {
528 proxy = set.newSetProxy();
529 }
530
531
532 public RemoteEvent createEvent(long eventID,
533 long seqNum,
534 MarshalledObject handback)
535 {
536 return new ExpirationWarningEvent(proxy, seqNum, handback);
537 }
538 }
539
540
541
542
543
544 private SetProxy newSetProxy() {
545 return normServerBaseImpl.newSetProxy(this);
546 }
547
548
549
550
551
552
553
554
555 boolean haveWarningRegistration() {
556 return warningEventType.haveListener();
557 }
558
559
560
561
562 long getWarningTime() {
563 return expiration - minWarning;
564 }
565
566
567
568
569
570 void logRenewal(ClientLeaseWrapper clw) {
571 if (!leases.contains(clw)) {
572
573
574 return;
575 }
576
577 final Object u = new UpdateClientLease(this, clw);
578 store.update(u);
579 }
580
581
582
583 public synchronized void setExpiration(long newExpiration) {
584 expiration = newExpiration;
585
586 expiration2.set(expiration);
587 }
588
589
590 public synchronized long getExpiration() {
591 return expiration;
592 }
593
594
595
596
597
598
599
600
601
602 boolean ensureCurrent(long now) {
603 return expiration2.ensureCurrent(now);
604 }
605
606
607 public Uuid getCookie() {
608 return ID;
609 }
610
611
612
613 Uuid getUuid() {
614 return ID;
615 }
616
617
618
619
620
621
622 void definiteException(EventType type, RemoteEvent ev,
623 long registrationNumber)
624 {
625 final boolean changed =
626 type.clearListenerIfSequenceMatch(registrationNumber);
627 if (changed) {
628
629 Object u;
630 if (ev instanceof ExpirationWarningEvent) {
631 u = new WarningEventRegistration(LeaseSet.this);
632 } else {
633 u = new FailureEventRegistration(LeaseSet.this);
634 }
635 store.update(u);
636 }
637 }
638
639
640
641
642
643 protected boolean isolateSets() {
644 return normServerBaseImpl.isolateSets();
645 }
646
647
648
649
650 public String toString() {
651 return "LeaseSet" + ID;
652 }
653
654
655
656
657
658
659 private static class ExpirationTime {
660 private static final long serialVersionUID = 1L;
661
662
663
664
665
666 private long expirationTime;
667
668
669 private ExpirationTime(long initVal) {
670 expirationTime = initVal;
671 }
672
673
674 private synchronized void set(long newTime) {
675 expirationTime = newTime;
676 }
677
678
679
680
681
682
683 private synchronized boolean ensureCurrent(long now) {
684 return now <= expirationTime;
685 }
686 }
687
688
689
690
691
692
693 static class ChangeSetExpiration extends LeaseSetOperation {
694 private static final long serialVersionUID = 1L;
695
696
697
698
699
700 private final long expiration;
701
702
703
704
705
706
707 ChangeSetExpiration(LeaseSet set, long expiration) {
708 super(set.getUuid());
709 this.expiration = expiration;
710 }
711
712
713 void apply(LeaseSet set) {
714 set.setExpiration(expiration);
715 }
716 }
717
718
719
720
721 private static class UpdateClientLease extends LeaseSetOperation {
722 private static final long serialVersionUID = 1L;
723
724
725
726
727
728 private final ClientLeaseWrapper clw;
729
730
731
732
733
734
735 private UpdateClientLease(LeaseSet set, ClientLeaseWrapper clw) {
736 super(set.getUuid());
737 this.clw = clw;
738 }
739
740
741 void apply(LeaseSet set) {
742 set.replace(clw);
743 }
744 }
745
746
747
748
749 private static class RemoveClientLease extends LeaseSetOperation {
750 private static final long serialVersionUID = 1L;
751
752
753
754
755
756 private final ClientLeaseWrapper clw;
757
758
759
760
761
762
763 private RemoveClientLease(LeaseSet set, ClientLeaseWrapper clw) {
764 super(set.getUuid());
765 this.clw = clw;
766 }
767
768
769
770 void apply(LeaseSet set) {
771 set.leases.remove(clw);
772 }
773 }
774
775
776
777
778 private static class RenewalFailure extends RemoveClientLease {
779 private static final long serialVersionUID = 1L;
780
781
782
783
784
785 private long evID;
786
787
788
789
790
791
792
793
794 private RenewalFailure(LeaseSet set, ClientLeaseWrapper clw,
795 long evID)
796 {
797 super(set, clw);
798 this.evID = evID;
799 }
800
801
802 void apply(LeaseSet set) {
803 super.apply(set);
804 set.failureEventType.setLastSequenceNumber(evID);
805 }
806 }
807
808
809
810
811 private static class WarningEventRegistration extends LeaseSetOperation {
812 private static final long serialVersionUID = 1L;
813
814
815
816
817
818 private final long warningTime;
819
820
821
822
823
824 private final EventType registration;
825
826
827
828
829
830 private WarningEventRegistration(LeaseSet set) {
831 super(set.getUuid());
832 synchronized (set){
833 warningTime = set.minWarning;
834 registration = set.warningEventType;
835 }
836 }
837
838
839
840 void apply(LeaseSet set) throws StoreException {
841 synchronized (set){
842 set.minWarning = warningTime;
843 set.warningEventType = registration;
844 }
845 }
846 }
847
848
849
850
851 private static class FailureEventRegistration extends LeaseSetOperation {
852 private static final long serialVersionUID = 1L;
853
854
855
856
857
858 private final EventType registration;
859
860
861
862
863
864 private FailureEventRegistration(LeaseSet set) {
865 super(set.getUuid());
866 registration = set.failureEventType;
867 }
868
869
870
871 void apply(LeaseSet set) throws StoreException {
872 set.failureEventType = registration;
873 }
874 }
875 }