package geniusweb.partiesserver; import java.io.IOException; import java.util.logging.Level; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import geniusweb.partiesserver.repository.AvailablePartiesRepo; import geniusweb.partiesserver.repository.AvailableParty; import geniusweb.partiesserver.repository.RunningPartiesRepo; import geniusweb.partiesserver.repository.RunningParty; import tudelft.utilities.logging.ReportToLogger; import tudelft.utilities.logging.Reporter; import tudelft.utilities.repository.NoResourcesNowException; /** * Servlet implementation class RunParty. It's behind the url * partiesserver/run/NAME where NAME is the name of the party that needs to be * run. */ public class RunParty extends HttpServlet { private static final int DEFAULT_TIMEOUT = 3000; // ms private static final long serialVersionUID = 1L; private final Reporter log; /** * @see HttpServlet#HttpServlet() */ public RunParty() { this(new ReportToLogger("partiesserver")); } /** * * @param reporter the reporter where we log issues to. */ public RunParty(Reporter reporter) { this.log = reporter; } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse * response). Returns * */ @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = request.getPathInfo().substring(1); log.log(Level.INFO, "request to run " + name); AvailableParty party = AvailablePartiesRepo.instance().get(name); if (party == null) { log.log(Level.INFO, "party " + name + " does not exist"); response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } // try to avoid needless creation of the party. if (RunningPartiesRepo.instance().availableSlots() <= 0) { tryLater(response, name); return; } RunningParty running; try { running = RunningParty.create(party, DEFAULT_TIMEOUT); } catch (Throwable e1) { log.log(Level.WARNING, "Failed to instantiate party " + name, e1); response.sendError(HttpServletResponse.SC_EXPECTATION_FAILED, "Failed to instantiate party " + name + ":" + e1.getMessage() + ". See partiesserver log for stack trace"); return; } // in the mean time, another party may have taken the slot anyway... // the chances that this happens is small though. try { RunningPartiesRepo.instance().put(running); } catch (NoResourcesNowException e) { running.getParty().terminate(); tryLater(response, name); return; } log.log(Level.INFO, "started " + name); String url = "ws://" + request.getLocalName() + ":" + request.getLocalPort() + request.getContextPath() + "/party/" + running.getID(); response.getWriter().append(url); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */ @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } /** * Reply with 503 plus message that the caller should try later * * @param response the response container * @param name the name of the party that was attempted to launch * @throws IOException */ private void tryLater(HttpServletResponse response, String name) throws IOException { long time = RunningPartiesRepo.instance().estimateCleanupTime() .getTime(); log.log(Level.INFO, "There are no free slots to run the party " + name + ". suggesting " + time); // sendError does not always work as expected, avoid it. response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE); response.getWriter().append("retry later at " + time); } }