diff options
author | Florian Dold <florian.dold@gmail.com> | 2014-03-11 01:24:03 +0000 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2014-03-11 01:24:03 +0000 |
commit | e2eecb019105d48e4afebe1bf57355b3450c8219 (patch) | |
tree | 74d8aee60cc6d336a3bb0445af8e091cc2351ecd /src/main/java/org/gnunet/requests | |
parent | 651cfb94264b0d12e8ed9afafab05f84d2201933 (diff) | |
download | gnunet-java-e2eecb019105d48e4afebe1bf57355b3450c8219.tar.gz gnunet-java-e2eecb019105d48e4afebe1bf57355b3450c8219.zip |
- simplify request containers
- statistics bugs
- fix missing annotation in consensus api
- work on voting
Diffstat (limited to 'src/main/java/org/gnunet/requests')
4 files changed, 200 insertions, 172 deletions
diff --git a/src/main/java/org/gnunet/requests/MatchingRequestContainer.java b/src/main/java/org/gnunet/requests/MatchingRequestContainer.java index b2c671e..04b17fd 100644 --- a/src/main/java/org/gnunet/requests/MatchingRequestContainer.java +++ b/src/main/java/org/gnunet/requests/MatchingRequestContainer.java | |||
@@ -1,3 +1,24 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2014 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | |||
1 | package org.gnunet.requests; | 22 | package org.gnunet.requests; |
2 | 23 | ||
3 | import com.google.common.collect.Maps; | 24 | import com.google.common.collect.Maps; |
@@ -8,13 +29,13 @@ import java.util.Map; | |||
8 | 29 | ||
9 | 30 | ||
10 | /** | 31 | /** |
11 | * Container for requests that are responded to with a matching request identification | 32 | * Container for requests that are responded to with a matching getRequestIdentifier identification |
12 | */ | 33 | */ |
13 | public class MatchingRequestContainer<K, T extends RequestContainer.Request> extends RequestContainer { | 34 | public class MatchingRequestContainer<K, T extends Request> extends RequestContainer { |
14 | /** | 35 | /** |
15 | * All queued requests. | 36 | * All queued requests. |
16 | */ | 37 | */ |
17 | private Map<K,T> requests = Maps.newHashMap(); | 38 | private Map<K,Identifier> requests = Maps.newHashMap(); |
18 | 39 | ||
19 | /** | 40 | /** |
20 | * Message queue to send to requests over. | 41 | * Message queue to send to requests over. |
@@ -25,48 +46,48 @@ public class MatchingRequestContainer<K, T extends RequestContainer.Request> ext | |||
25 | this.mq = mq; | 46 | this.mq = mq; |
26 | } | 47 | } |
27 | 48 | ||
49 | private class Identifier extends SimpleRequestIdentifier<T> { | ||
50 | final K key; | ||
51 | |||
52 | public Identifier(T request, K key) { | ||
53 | super(request); | ||
54 | this.key = key; | ||
55 | } | ||
56 | |||
57 | @Override | ||
58 | public void retire() { | ||
59 | super.retire(); | ||
60 | requests.remove(key); | ||
61 | } | ||
62 | } | ||
63 | |||
28 | public Cancelable addRequest(K key, final T request) { | 64 | public Cancelable addRequest(K key, final T request) { |
29 | if (requests.containsKey(key)) | 65 | if (requests.containsKey(key)) |
30 | throw new AssertionError("key already present in request container"); | 66 | throw new AssertionError("key already present in getRequestIdentifier container"); |
31 | requests.put(key, request); | 67 | Identifier identifier = new Identifier(request, key); |
32 | mq.send(request.assembleRequest()); | 68 | requests.put(key, identifier); |
33 | return new Cancelable() { | 69 | identifier.send(mq); |
34 | @Override | 70 | return identifier; |
35 | public void cancel() { | ||
36 | setRequestCancelled(request); | ||
37 | if (isRequestTransmitting(request)) { | ||
38 | cancelRequestTransmission(request); | ||
39 | } else { | ||
40 | request.cancel(); | ||
41 | } | ||
42 | } | ||
43 | }; | ||
44 | } | 71 | } |
45 | 72 | ||
46 | @Override | 73 | @Override |
47 | public void restart() { | 74 | public void restart() { |
48 | Map<K,T> requestsOld = requests; | 75 | Map<K, Identifier> requestsOld = requests; |
49 | requests = Maps.newHashMap(); | 76 | requests = Maps.newHashMap(); |
50 | for (Map.Entry<K,T> e : requestsOld.entrySet()) { | 77 | for (Map.Entry<K,Identifier> e : requestsOld.entrySet()) { |
51 | if (!isRequestCancelled(e.getValue())) { | 78 | addRequest(e.getKey(), e.getValue().getRequest()); |
52 | setRequestTransmitting(e.getValue(), false); | ||
53 | addRequest(e.getKey(), e.getValue()); | ||
54 | } | ||
55 | } | 79 | } |
56 | } | 80 | } |
57 | 81 | ||
58 | public T getRequest(K key) { | 82 | public RequestIdentifier<T> getRequestIdentifier(K key) { |
59 | return requests.get(key); | 83 | return requests.get(key); |
60 | } | 84 | } |
61 | 85 | ||
62 | /** | 86 | public T getAndRetireRequest(K key) { |
63 | * Retrieve the request matching the given key, and remove it. | 87 | RequestIdentifier<T> i = getRequestIdentifier(key); |
64 | * Return null if there is no matching request. | 88 | if (null == i) |
65 | * | 89 | return null; |
66 | * @param key key to look for | 90 | i.retire(); |
67 | * @return request, or null | 91 | return i.getRequest(); |
68 | */ | ||
69 | public T pollRequest(K key) { | ||
70 | return requests.remove(key); | ||
71 | } | 92 | } |
72 | } | 93 | } |
diff --git a/src/main/java/org/gnunet/requests/RequestContainer.java b/src/main/java/org/gnunet/requests/RequestContainer.java index 8fc631e..9c7fb48 100644 --- a/src/main/java/org/gnunet/requests/RequestContainer.java +++ b/src/main/java/org/gnunet/requests/RequestContainer.java | |||
@@ -1,90 +1,31 @@ | |||
1 | package org.gnunet.requests; | 1 | /* |
2 | 2 | This file is part of GNUnet. | |
3 | (C) 2014 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
3 | 20 | ||
4 | import org.gnunet.mq.Envelope; | 21 | package org.gnunet.requests; |
5 | import org.gnunet.util.Cancelable; | ||
6 | 22 | ||
7 | /** | 23 | /** |
8 | * Container for requests to a service. | 24 | * Container for requests to a service. |
9 | */ | 25 | */ |
10 | public abstract class RequestContainer { | 26 | public abstract class RequestContainer { |
11 | /** | 27 | /** |
12 | * Do we allow sending pending requests while | 28 | * Re-send all active and pending requests. |
13 | * other requests are still active (true), or do we send | ||
14 | * requests one-by-one (false)? | ||
15 | */ | ||
16 | protected boolean overlap = true; | ||
17 | |||
18 | /** | ||
19 | * A request that can be put in a request container. | ||
20 | */ | ||
21 | public abstract static class Request { | ||
22 | private boolean transmitting; | ||
23 | private boolean canceled; | ||
24 | private Cancelable cancelRequest; | ||
25 | |||
26 | /** | ||
27 | * Create an envelope for executing the request. | ||
28 | * | ||
29 | * @return Envelope to be sent to the service with the request message. | ||
30 | */ | ||
31 | public abstract Envelope assembleRequest(); | ||
32 | |||
33 | /** | ||
34 | * Implement cancellation logic for requests. | ||
35 | * Only called when the request has already been sent to the service. | ||
36 | * | ||
37 | * By default, canceling a request throws an exception. | ||
38 | */ | ||
39 | public void cancel() { | ||
40 | throw new AssertionError("request of type " + this.getClass() + " can not be canceled (not implemented)"); | ||
41 | } | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * Re-send all requests in the queue that have not been canceled. | ||
46 | */ | 29 | */ |
47 | public abstract void restart(); | 30 | public abstract void restart(); |
48 | |||
49 | /** | ||
50 | * Allow or disallow requests to be send while other requests in the queue have not been completed. | ||
51 | * | ||
52 | * @param overlap true to allow overlapped requests, false to disallow them | ||
53 | */ | ||
54 | public void setOverlap(boolean overlap) { | ||
55 | this.overlap = overlap; | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * Check if the given request is transmitting, that is, the request | ||
60 | * is waiting to be sent to the service. | ||
61 | * | ||
62 | * @param r request | ||
63 | * @return whether the request is still being transmitted | ||
64 | */ | ||
65 | protected boolean isRequestTransmitting(Request r) { | ||
66 | return r.transmitting; | ||
67 | } | ||
68 | |||
69 | protected void setRequestTransmitting(Request r, boolean transmitting) { | ||
70 | r.transmitting = transmitting; | ||
71 | } | ||
72 | |||
73 | protected void setRequestTransmissionCancel(Request request, Cancelable cancel) { | ||
74 | request.cancelRequest = cancel; | ||
75 | } | ||
76 | |||
77 | protected void cancelRequestTransmission(Request r) { | ||
78 | r.cancelRequest.cancel(); | ||
79 | r.cancelRequest = null; | ||
80 | } | ||
81 | |||
82 | protected void setRequestCancelled(Request r) { | ||
83 | r.canceled = true; | ||
84 | } | ||
85 | |||
86 | protected boolean isRequestCancelled(Request r) { | ||
87 | return r.canceled; | ||
88 | } | ||
89 | |||
90 | } | 31 | } |
diff --git a/src/main/java/org/gnunet/requests/SequentialRequestContainer.java b/src/main/java/org/gnunet/requests/SequentialRequestContainer.java index 037055f..c343812 100644 --- a/src/main/java/org/gnunet/requests/SequentialRequestContainer.java +++ b/src/main/java/org/gnunet/requests/SequentialRequestContainer.java | |||
@@ -1,86 +1,153 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2014 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
1 | package org.gnunet.requests; | 21 | package org.gnunet.requests; |
2 | 22 | ||
3 | import org.gnunet.mq.Envelope; | ||
4 | import org.gnunet.mq.MessageQueue; | 23 | import org.gnunet.mq.MessageQueue; |
5 | import org.gnunet.mq.NotifySentHandler; | ||
6 | import org.gnunet.util.Cancelable; | ||
7 | 24 | ||
8 | import java.util.LinkedList; | 25 | import java.util.LinkedList; |
9 | 26 | ||
10 | /** | 27 | /** |
11 | * Container for requests that are responded to in sequential order. | 28 | * Container for requests that are responded to in sequential order. |
12 | */ | 29 | */ |
13 | public class SequentialRequestContainer<T extends RequestContainer.Request> extends RequestContainer { | 30 | public class SequentialRequestContainer<T extends Request> extends RequestContainer { |
14 | private LinkedList<T> requests = new LinkedList<T>(); | 31 | /** |
15 | private MessageQueue mq; | 32 | * Allow overlapping requests. |
33 | */ | ||
34 | private boolean overlap; | ||
35 | /** | ||
36 | * Request in our queue with information about them. | ||
37 | */ | ||
38 | private LinkedList<Identifier> requests = new LinkedList<Identifier>(); | ||
39 | /** | ||
40 | * Message queue that is used to send envelopes. | ||
41 | */ | ||
42 | private final MessageQueue mq; | ||
16 | 43 | ||
17 | int requestsActive = 0; | 44 | /** |
45 | * Number of active requests. | ||
46 | */ | ||
47 | private int requestsActive = 0; | ||
18 | 48 | ||
19 | public SequentialRequestContainer(MessageQueue mq) { | 49 | /** |
50 | * Create a sequential request container that sends messages with the given | ||
51 | * message queue. | ||
52 | * | ||
53 | * @param mq message queue to send messages with | ||
54 | * @param overlap allow sending requests while other request have not yet completed | ||
55 | */ | ||
56 | public SequentialRequestContainer(MessageQueue mq, boolean overlap) { | ||
20 | this.mq = mq; | 57 | this.mq = mq; |
58 | this.overlap = overlap; | ||
59 | } | ||
60 | /** | ||
61 | * Create a sequential request container that sends messages with the given | ||
62 | * message queue. Do not allow other requests to be send while the current request | ||
63 | * is still active. | ||
64 | * | ||
65 | * @param mq message queue to send messages with | ||
66 | */ | ||
67 | public SequentialRequestContainer(MessageQueue mq) { | ||
68 | this(mq, false); | ||
69 | } | ||
70 | /** | ||
71 | * Get the current request's identifier. | ||
72 | * | ||
73 | * @return current request | ||
74 | */ | ||
75 | public RequestIdentifier<T> getRequestIdentifier() { | ||
76 | return requests.peekFirst(); | ||
21 | } | 77 | } |
22 | 78 | ||
79 | /** | ||
80 | * Get the current request and retire it. | ||
81 | * If there is no current request, null will be returned. | ||
82 | * | ||
83 | * @return current request | ||
84 | */ | ||
85 | public T getAndRetireRequest() { | ||
86 | RequestIdentifier<T> i = getRequestIdentifier(); | ||
87 | if (null == i) | ||
88 | return null; | ||
89 | i.retire(); | ||
90 | return i.getRequest(); | ||
91 | } | ||
92 | |||
93 | public Iterable<RequestIdentifier<T>> iter() { | ||
94 | return (Iterable) requests; | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * Get the current request. | ||
99 | * | ||
100 | * @return the current request. | ||
101 | */ | ||
23 | public T getRequest() { | 102 | public T getRequest() { |
24 | return requests.getFirst(); | 103 | RequestIdentifier<T> i = getRequestIdentifier(); |
104 | if (null == i) | ||
105 | return null; | ||
106 | return i.getRequest(); | ||
25 | } | 107 | } |
26 | 108 | ||
27 | public void next() { | 109 | /** |
28 | if (requestsActive == 0 || requests.isEmpty()) | 110 | * A request identifier in a sequential request container. |
29 | throw new AssertionError(); | 111 | */ |
30 | requestsActive--; | 112 | private class Identifier extends SimpleRequestIdentifier<T> { |
31 | requests.removeFirst(); | 113 | public Identifier(T request) { |
32 | if (requestsActive == 0 && !requests.isEmpty()) { | 114 | super(request); |
33 | Request r = requests.getFirst(); | 115 | } |
34 | setRequestTransmitting(r, true); | 116 | |
35 | Envelope ev = r.assembleRequest(); | 117 | @Override |
36 | setRequestTransmissionCancel(r, ev); | 118 | public void retire() { |
37 | mq.send(r.assembleRequest()); | 119 | super.retire(); |
38 | requestsActive++; | 120 | if (requestsActive == 0 || requests.isEmpty()) |
121 | throw new AssertionError(); | ||
122 | boolean found = requests.remove(this); | ||
123 | if (!found) | ||
124 | throw new AssertionError("request not in queue"); | ||
125 | requestsActive--; | ||
126 | Identifier next = requests.peekFirst(); | ||
127 | if (null == next || next.queued) | ||
128 | return; | ||
129 | if (requestsActive == 0 || overlap) | ||
130 | next.send(mq); | ||
39 | } | 131 | } |
40 | } | 132 | } |
41 | 133 | ||
42 | public Cancelable addRequest(final T request) { | 134 | public RequestIdentifier<T> addRequest(final T request) { |
43 | requests.addLast(request); | 135 | final Identifier identifier = new Identifier(request); |
136 | requests.addLast(identifier); | ||
137 | // only send immediately if we are allowed to | ||
44 | if (overlap || requestsActive == 0) { | 138 | if (overlap || requestsActive == 0) { |
45 | requestsActive++; | 139 | identifier.send(mq); |
46 | setRequestTransmitting(request, true); | 140 | requestsActive += 1; |
47 | Envelope ev = request.assembleRequest(); | ||
48 | ev.notifySent(new NotifySentHandler() { | ||
49 | @Override | ||
50 | public void onSent() { | ||
51 | setRequestTransmitting(request, false); | ||
52 | } | ||
53 | }); | ||
54 | setRequestTransmissionCancel(request, ev); | ||
55 | mq.send(request.assembleRequest()); | ||
56 | } | 141 | } |
57 | return new Cancelable() { | 142 | return identifier; |
58 | @Override | ||
59 | public void cancel() { | ||
60 | setRequestCancelled(request); | ||
61 | if (isRequestTransmitting(request)) { | ||
62 | cancelRequestTransmission(request); | ||
63 | } else { | ||
64 | request.cancel(); | ||
65 | } | ||
66 | } | ||
67 | }; | ||
68 | } | 143 | } |
69 | 144 | ||
70 | @Override | 145 | @Override |
71 | public void restart() { | 146 | public void restart() { |
72 | LinkedList<T> requestsOld = requests; | 147 | LinkedList<Identifier> requestsOld = requests; |
73 | requests = new LinkedList<T>(); | 148 | requests = new LinkedList<Identifier>(); |
74 | for (T r : requestsOld) { | 149 | for (Identifier r : requestsOld) { |
75 | if (!isRequestCancelled(r)) { | 150 | addRequest(r.getRequest()); |
76 | setRequestTransmitting(r, false); | ||
77 | addRequest(r); | ||
78 | } | ||
79 | } | 151 | } |
80 | } | 152 | } |
81 | |||
82 | |||
83 | public Iterable<T> iter() { | ||
84 | return requests; | ||
85 | } | ||
86 | } | 153 | } |
diff --git a/src/main/java/org/gnunet/requests/package-info.java b/src/main/java/org/gnunet/requests/package-info.java index 892a606..b4fd674 100644 --- a/src/main/java/org/gnunet/requests/package-info.java +++ b/src/main/java/org/gnunet/requests/package-info.java | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2011, 2012 Christian Grothoff (and other contributing authors) | 3 | (C) 2014 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -18,7 +18,6 @@ | |||
18 | Boston, MA 02111-1307, USA. | 18 | Boston, MA 02111-1307, USA. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | |||
22 | /** | 21 | /** |
23 | * General mechanism for queueing requests to a service. | 22 | * General mechanism for queueing requests to a service. |
24 | */ | 23 | */ |