blob: 5c881ee364423e362c2aab0c44bbb41609ad5340 [file] [log] [blame]
Andrew Browndb457052015-02-21 15:41:58 -08001/*
2 * File name: FuturePacket.java
3 *
4 * Purpose: Reference to a Packet that has yet to be returned from the network.
5 *
6 * © Copyright Intel Corporation. All rights reserved.
7 * Intel Corporation, 2200 Mission College Boulevard,
8 * Santa Clara, CA 95052-8119, USA
9 */
10package com.intel.jndn.utils;
11
12import java.io.IOException;
13import java.util.concurrent.ExecutionException;
14import java.util.concurrent.Future;
15import java.util.concurrent.TimeUnit;
16import java.util.concurrent.TimeoutException;
17import net.named_data.jndn.Data;
18import net.named_data.jndn.Face;
19import net.named_data.jndn.Name;
20import net.named_data.jndn.encoding.EncodingException;
21
22/**
23 * Reference to a Packet that has yet to be returned from the network; see use
24 * in WindowBuffer.java. Usage:
25 * <pre><code>
26 * FuturePacket futurePacket = new FuturePacket(face);
27 * face.expressInterest(interest, new OnData(){
28 * ... futurePacket.resolve(data); ...
29 * }, new OnTimeout(){
30 * ... futurePacket.reject(new TimeoutException());
31 * });
32 * Packet resolvedPacket = futurePacket.get(); // will block and call face.processEvents() until complete
33 * </code></pre>
34 *
35 * @author Andrew Brown <andrew.brown@intel.com>
36 */
37public class FutureData implements Future<Data> {
38
39 private final Face face;
40 private final Name name;
41 private Data data;
42 private boolean cancelled = false;
43 private Throwable error;
44
45 /**
46 * Constructor
47 *
48 * @param face
49 * @param name
50 */
51 public FutureData(Face face, Name name) {
52 this.face = face;
53 this.name = new Name(name);
54 }
55
56 /**
57 * Get the packet interest name
58 *
59 * @return
60 */
61 public Name getName() {
62 return name;
63 }
64
65 /**
66 * Cancel the current request.
67 *
68 * @param mayInterruptIfRunning
69 * @return
70 */
71 @Override
72 public boolean cancel(boolean mayInterruptIfRunning) {
73 cancelled = true;
74 return cancelled;
75 }
76
77 /**
78 * Determine if this request is cancelled.
79 *
80 * @return
81 */
82 @Override
83 public boolean isCancelled() {
84 return cancelled;
85 }
86
87 /**
88 * Determine if the request has completed (successfully or not).
89 *
90 * @return
91 */
92 @Override
93 public boolean isDone() {
94 return data != null || error != null;
95 }
96
97 /**
98 * Set the packet when successfully retrieved; unblocks get().
99 *
100 * @param d
101 */
102 public void resolve(Data d) {
103 data = d;
104 }
105
106 /**
107 * Set the exception when request failed; unblocks get().
108 *
109 * @param e
110 */
111 public void reject(Throwable e) {
112 error = e;
113 }
114
115 /**
116 * Block until packet is retrieved.
117 *
118 * @return
119 * @throws InterruptedException
120 * @throws ExecutionException
121 */
122 @Override
123 public Data get() throws InterruptedException, ExecutionException {
124 while (!isDone() && !isCancelled()) {
125 try {
126 synchronized (face) {
127 face.processEvents();
128 }
129 } catch (EncodingException | IOException e) {
130 throw new ExecutionException("Failed to retrieve packet.", e);
131 }
132 }
133 // case: cancelled
134 if (cancelled) {
135 throw new InterruptedException("Interrupted by user.");
136 }
137 // case: error
138 if (error != null) {
139 throw new ExecutionException("Future rejected with error.", error);
140 }
141 // case: packet
142 return data;
143 }
144
145 /**
146 * Block until packet is retrieved or timeout is reached.
147 *
148 * @param timeout
149 * @param unit
150 * @return
151 * @throws InterruptedException
152 * @throws ExecutionException
153 * @throws TimeoutException
154 */
155 @Override
156 public Data get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
157 long interval = TimeUnit.MILLISECONDS.convert(timeout, unit);
158 long endTime = System.currentTimeMillis() + interval;
159 while (!isDone() && !isCancelled() && System.currentTimeMillis() < endTime) {
160 try {
161 synchronized (face) {
162 face.processEvents();
163 }
164 } catch (EncodingException | IOException e) {
165 throw new ExecutionException("Failed to retrieve packet.", e);
166 }
167 }
168 // case: timed out
169 if (System.currentTimeMillis() < endTime) {
170 throw new TimeoutException("Timed out");
171 }
172 // case: cancelled
173 if (cancelled) {
174 throw new InterruptedException("Interrupted by user.");
175 }
176 // case: error
177 if (error != null) {
178 throw new ExecutionException("Future rejected.", error);
179 }
180 // case: packet
181 return data;
182 }
183}