PageRenderTime 26ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Core/org/objectweb/proactive/core/component/collectiveitfs/GatherRequestsQueue.java

https://bitbucket.org/lp/programming-multiactivities
Java | 315 lines | 206 code | 34 blank | 75 comment | 35 complexity | 77d2eea1b558775c87c2ce5924764e78 MD5 | raw file
  1. /*
  2. * ################################################################
  3. *
  4. * ProActive Parallel Suite(TM): The Java(TM) library for
  5. * Parallel, Distributed, Multi-Core Computing for
  6. * Enterprise Grids & Clouds
  7. *
  8. * Copyright (C) 1997-2012 INRIA/University of
  9. * Nice-Sophia Antipolis/ActiveEon
  10. * Contact: proactive@ow2.org or contact@activeeon.com
  11. *
  12. * This library is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU Affero General Public License
  14. * as published by the Free Software Foundation; version 3 of
  15. * the License.
  16. *
  17. * This library is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  20. * Affero General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU Affero General Public License
  23. * along with this library; if not, write to the Free Software
  24. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  25. * USA
  26. *
  27. * If needed, contact us to obtain a release under GPL Version 2 or 3
  28. * or a different license than the AGPL.
  29. *
  30. * Initial developer(s): The ProActive Team
  31. * http://proactive.inria.fr/team_members.htm
  32. * Contributor(s):
  33. *
  34. * ################################################################
  35. * $$PROACTIVE_INITIAL_DEV$$
  36. */
  37. package org.objectweb.proactive.core.component.collectiveitfs;
  38. import java.io.Serializable;
  39. import java.lang.reflect.Method;
  40. import java.util.ArrayList;
  41. import java.util.HashMap;
  42. import java.util.List;
  43. import java.util.Map;
  44. import java.util.Timer;
  45. import org.apache.log4j.Logger;
  46. import org.objectweb.proactive.core.ProActiveRuntimeException;
  47. import org.objectweb.proactive.core.body.future.MethodCallResult;
  48. import org.objectweb.proactive.core.body.migration.MigrationException;
  49. import org.objectweb.proactive.core.component.exceptions.GathercastTimeoutException;
  50. import org.objectweb.proactive.core.component.identity.PAComponent;
  51. import org.objectweb.proactive.core.component.representative.ItfID;
  52. import org.objectweb.proactive.core.component.request.ComponentRequest;
  53. import org.objectweb.proactive.core.component.type.annotations.gathercast.MethodSynchro;
  54. import org.objectweb.proactive.core.node.Node;
  55. import org.objectweb.proactive.core.util.SerializableMethod;
  56. import org.objectweb.proactive.core.util.log.Loggers;
  57. import org.objectweb.proactive.core.util.log.ProActiveLogger;
  58. import org.objectweb.proactive.utils.SafeTimerTask;
  59. /**
  60. * <p>This class manages a queue of requests on a gather interface: a list of reified invocations from connected client interfaces.</p>
  61. *
  62. * <p>Asynchronicity is provided with a third-party active object and automatic continuations.</p>
  63. *
  64. * <p>A timeout exception is thrown if some of the connected client interfaces fail to send a request before the timeout; the countdown
  65. * is triggered right after serving the first invocation on the gathercast interface.</p>
  66. *
  67. * @author The ProActive Team
  68. *
  69. */
  70. public class GatherRequestsQueue implements Serializable {
  71. private GatherFuturesHandler futuresHandler; // primitive pooling
  72. private List<Object> connectedClientItfs; // consistency?
  73. private Map<ItfID, ComponentRequest> requests;
  74. private String serverItfName;
  75. private SerializableMethod itfTypeInvokedMethod;
  76. private boolean waitForAll = true;
  77. transient long creationTime = System.currentTimeMillis(); // TODO do not reinitialize after deserialization
  78. public static final long DEFAULT_TIMEOUT = 1000000; // TODO use a proactive default property
  79. private Timer timeoutTimer = null;
  80. boolean timedout = false;
  81. boolean thrownTimeoutException = false;
  82. long timeout = DEFAULT_TIMEOUT;
  83. private static Logger logger = ProActiveLogger.getLogger(Loggers.COMPONENTS_GATHERCAST);
  84. GatherFuturesHandlerPool gatherFuturesHandlerPool;
  85. boolean resultsReturned = false;
  86. boolean oneWayCall = true;
  87. public GatherRequestsQueue(PAComponent owner, String serverItfName, Method itfTypeMethod,
  88. List<Object> connectedClientItfs, GatherFuturesHandlerPool gatherFuturesHandlerPool) {
  89. //this.owner = owner;
  90. this.serverItfName = serverItfName;
  91. // this.conditionChecker = gatherConditionChecker;
  92. // this.invokedMethodSignature = methodSignature;
  93. itfTypeInvokedMethod = new SerializableMethod(itfTypeMethod);
  94. this.gatherFuturesHandlerPool = gatherFuturesHandlerPool;
  95. this.connectedClientItfs = connectedClientItfs;
  96. MethodSynchro sc = itfTypeInvokedMethod.getMethod().getAnnotation(MethodSynchro.class);
  97. if (sc != null) {
  98. this.waitForAll = sc.waitForAll();
  99. } else {
  100. this.waitForAll = true;
  101. }
  102. requests = new HashMap<ItfID, ComponentRequest>();
  103. // add first request
  104. // requests.put(r.getMethodCall().getComponentMetadata().getSenderItfID(), r);
  105. }
  106. public boolean containsRequestFrom(ItfID clientItfID) {
  107. return requests.containsKey(clientItfID);
  108. }
  109. public synchronized Object put(ItfID clientItfID, ComponentRequest request) {
  110. if (isFull()) {
  111. throw new ProActiveRuntimeException("gather requests queue is full");
  112. }
  113. requests.put(clientItfID, request);
  114. // evaluate waitForAll
  115. if (!waitForAll) {
  116. // Non synchronized method, we should not expect other request
  117. connectedClientItfs = new ArrayList<Object>();
  118. connectedClientItfs.add(clientItfID);
  119. }
  120. //use a pool!
  121. if ((futuresHandler == null) && (!Void.TYPE.equals(itfTypeInvokedMethod.getMethod().getReturnType()))) {
  122. oneWayCall = false;
  123. try {
  124. if (logger.isDebugEnabled()) {
  125. logger.debug("adding futures handler for requests on " + serverItfName + "." +
  126. itfTypeInvokedMethod.getMethod().getName());
  127. }
  128. futuresHandler = GatherFuturesHandlerPool.instance().borrowFuturesHandler();
  129. futuresHandler.setConnectedClientItfs(connectedClientItfs);
  130. } catch (Exception e) {
  131. throw new ProActiveRuntimeException("cannot create futures handler for gather interface", e);
  132. }
  133. }
  134. if (!oneWayCall) {
  135. // evaluate timeout
  136. if (timeoutTimer == null) {
  137. timeoutTimer = new Timer();
  138. MethodSynchro sc = itfTypeInvokedMethod.getMethod().getAnnotation(MethodSynchro.class);
  139. if (waitForAll && (sc != null)) {
  140. timeout = sc.timeout();
  141. } else {
  142. timeout = DEFAULT_TIMEOUT;
  143. }
  144. if (logger.isDebugEnabled()) {
  145. logger.debug("gather request queue timer starting with timeout = " + timeout);
  146. }
  147. timeoutTimer.schedule(new TimeoutTask(this), timeout);
  148. }
  149. if (isFull()) {
  150. timeoutTimer.cancel();
  151. }
  152. if ((System.currentTimeMillis() - creationTime) >= timeout) {
  153. // we need to check this for small timeouts because timer runs concurrently
  154. timedout = true;
  155. addFutureForGatheredRequest(null);
  156. }
  157. Object reply = futuresHandler.distribute(clientItfID);
  158. // return future result (will be computed when gather request is processed)
  159. return reply;
  160. } else {
  161. return null;
  162. }
  163. }
  164. public ComponentRequest get() {
  165. // return the first one
  166. if (requests.isEmpty()) {
  167. return null;
  168. }
  169. return requests.get(requests.keySet().iterator().next());
  170. }
  171. public ComponentRequest get(ItfID id) {
  172. return requests.get(id);
  173. }
  174. public boolean waitForAll() {
  175. return waitForAll;
  176. }
  177. public boolean isFull() {
  178. return (requests.size() == connectedClientItfs.size());
  179. }
  180. public int size() {
  181. return requests.size();
  182. }
  183. public Method getInvokedMethod() {
  184. // return the first one
  185. if (requests.isEmpty()) {
  186. return null;
  187. }
  188. return requests.get(requests.keySet().iterator().next()).getMethodCall().getReifiedMethod();
  189. }
  190. public boolean oneWayMethods() {
  191. if (requests.isEmpty()) {
  192. return false;
  193. }
  194. return requests.get(requests.keySet().iterator().next()).isOneWay();
  195. }
  196. public void addFutureForGatheredRequest(MethodCallResult futureResult) {
  197. if (timedout && !resultsReturned) {
  198. // avoids race condition with small timeouts (result is replaced with a timeout exception)
  199. if (!thrownTimeoutException) {
  200. if (logger.isDebugEnabled()) {
  201. logger.debug("timeout reached at " + timeout + "for gather request on [" +
  202. itfTypeInvokedMethod.getMethod().getName() + "]");
  203. }
  204. thrownTimeoutException = true;
  205. futuresHandler
  206. .setFutureOfGatheredInvocation(new MethodCallResult(
  207. null,
  208. new GathercastTimeoutException(
  209. "timeout of " +
  210. timeout +
  211. " reached before invocations from all clients were received for gather invocation (method " +
  212. itfTypeInvokedMethod.getMethod().toGenericString() +
  213. " on gather interface " + serverItfName)));
  214. }
  215. // else ignore
  216. } else {
  217. if (!resultsReturned) {
  218. // this will trigger automatically the distribution of result for clients of the gather itf
  219. resultsReturned = true;
  220. futuresHandler.setFutureOfGatheredInvocation(futureResult);
  221. } else {
  222. // ignore
  223. }
  224. try {
  225. GatherFuturesHandlerPool.instance().returnFuturesHandler(futuresHandler);
  226. } catch (Exception e) {
  227. e.printStackTrace();
  228. }
  229. }
  230. timeoutTimer.cancel();
  231. }
  232. /**
  233. * @return the creationTime.
  234. */
  235. public long getCreationTime() {
  236. return creationTime;
  237. }
  238. public void returnFuturesHandlerToPool() {
  239. if (futuresHandler != null) {
  240. futuresHandler.passivate();
  241. }
  242. }
  243. /**
  244. * @return Returns the requests.
  245. */
  246. public Map<ItfID, ComponentRequest> getRequests() {
  247. return requests;
  248. }
  249. /**
  250. * @return Returns the connectedClientItfs.
  251. */
  252. public List<Object> getConnectedClientItfs() {
  253. return connectedClientItfs;
  254. }
  255. private class TimeoutTask extends SafeTimerTask {
  256. GatherRequestsQueue requestsQueue;
  257. public TimeoutTask(GatherRequestsQueue requestsQueue) {
  258. this.requestsQueue = requestsQueue;
  259. }
  260. @Override
  261. public void safeRun() {
  262. requestsQueue.timedout = true;
  263. if (!resultsReturned) {
  264. if (!thrownTimeoutException) {
  265. requestsQueue.addFutureForGatheredRequest(null);
  266. }
  267. }
  268. }
  269. }
  270. public void migrateFuturesHandlerTo(Node node) throws MigrationException {
  271. futuresHandler.migrateTo(node);
  272. }
  273. private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
  274. // System.out.println("writing gather requests queue");
  275. out.defaultWriteObject();
  276. }
  277. private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
  278. // System.out.println("reading gather requests queue");
  279. in.defaultReadObject();
  280. }
  281. }