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