22
22
import java .lang .Long ;
23
23
import java .util .AbstractMap ;
24
24
import java .util .HashMap ;
25
+ import java .util .Iterator ;
25
26
import java .util .Map ;
26
27
import java .util .concurrent .Future ;
27
28
import java .util .concurrent .TimeUnit ;
@@ -52,7 +53,25 @@ public class ClientImpl<T extends ServiceDefinition> implements Client<T> {
52
53
private final WeakReference <Node > nodeReference ;
53
54
private long handle ;
54
55
private final String serviceName ;
55
- private Map <Long , Map .Entry <Consumer , ResponseFuture >> pendingRequests ;
56
+
57
+ private class PendingRequest
58
+ {
59
+ public Consumer callback ;
60
+ public ResponseFuture future ;
61
+ public long requestTimestamp ;
62
+
63
+ public PendingRequest (
64
+ final Consumer callback ,
65
+ final ResponseFuture future ,
66
+ final long requestTimestamp )
67
+ {
68
+ this .callback = callback ;
69
+ this .future = future ;
70
+ this .requestTimestamp = requestTimestamp ;
71
+ }
72
+ }
73
+
74
+ private Map <Long , PendingRequest > pendingRequests ;
56
75
57
76
private final ServiceDefinition serviceDefinition ;
58
77
@@ -66,7 +85,7 @@ public ClientImpl(
66
85
this .handle = handle ;
67
86
this .serviceName = serviceName ;
68
87
this .serviceDefinition = serviceDefinition ;
69
- this .pendingRequests = new HashMap <Long , Map . Entry < Consumer , ResponseFuture > >();
88
+ this .pendingRequests = new HashMap <Long , PendingRequest >();
70
89
}
71
90
72
91
public ServiceDefinition getServiceDefinition () {
@@ -88,8 +107,7 @@ public void accept(Future<V> input) {}
88
107
request .getDestructorInstance (), request );
89
108
ResponseFuture <V > future = new ResponseFuture <V >(sequenceNumber );
90
109
91
- Map .Entry <Consumer , ResponseFuture > entry =
92
- new AbstractMap .SimpleEntry <Consumer , ResponseFuture >(callback , future );
110
+ PendingRequest entry = new PendingRequest (callback , future , System .nanoTime ());
93
111
pendingRequests .put (sequenceNumber , entry );
94
112
return future ;
95
113
}
@@ -98,20 +116,44 @@ public void accept(Future<V> input) {}
98
116
public final <V extends MessageDefinition > boolean
99
117
removePendingRequest (ResponseFuture <V > future ) {
100
118
synchronized (pendingRequests ) {
101
- Map . Entry < Consumer , ResponseFuture > entry = pendingRequests .remove (
119
+ PendingRequest entry = pendingRequests .remove (
102
120
future .getRequestSequenceNumber ());
103
121
return entry != null ;
104
122
}
105
123
}
106
124
125
+ public final long
126
+ prunePendingRequests () {
127
+ synchronized (pendingRequests ) {
128
+ long size = pendingRequests .size ();
129
+ pendingRequests .clear ();
130
+ return size ;
131
+ }
132
+ }
133
+
134
+ public final long
135
+ prunePendingRequestsOlderThan (long nanoTime ) {
136
+ synchronized (pendingRequests ) {
137
+ Iterator <Map .Entry <Long , PendingRequest >> iter = pendingRequests .entrySet ().iterator ();
138
+ long removed = 0 ;
139
+ while (iter .hasNext ()) {
140
+ if (iter .next ().getValue ().requestTimestamp < nanoTime ) {
141
+ iter .remove ();
142
+ ++removed ;
143
+ }
144
+ }
145
+ return removed ;
146
+ }
147
+ }
148
+
107
149
public final <U extends MessageDefinition > void handleResponse (
108
150
final RMWRequestId header , final U response ) {
109
151
synchronized (pendingRequests ) {
110
152
long sequenceNumber = header .sequenceNumber ;
111
- Map . Entry < Consumer , ResponseFuture > entry = pendingRequests .remove (sequenceNumber );
153
+ PendingRequest entry = pendingRequests .remove (sequenceNumber );
112
154
if (entry != null ) {
113
- Consumer <Future > callback = entry .getKey () ;
114
- ResponseFuture <U > future = entry .getValue () ;
155
+ Consumer <Future > callback = entry .callback ;
156
+ ResponseFuture <U > future = entry .future ;
115
157
future .set (response );
116
158
callback .accept (future );
117
159
return ;
0 commit comments