public void start() throws Exception { log.info("Starting Gravity..."); synchronized (this) { if (!started) { adapterFactory = new AdapterFactory(this); internalStart(); serverChannel = new ServerChannel(this, ServerChannel.class.getName(), null, null); if (gravityConfig.isUseUdp()) { ServiceLoader<UdpReceiverFactory> loader = ServiceLoader.load(UdpReceiverFactory.class); Iterator<UdpReceiverFactory> factories = loader.iterator(); if (factories.hasNext()) { udpReceiverFactory = factories.next(); udpReceiverFactory.setPort(gravityConfig.getUdpPort()); udpReceiverFactory.setNio(gravityConfig.isUdpNio()); udpReceiverFactory.setConnected(gravityConfig.isUdpConnected()); udpReceiverFactory.setSendBufferSize(gravityConfig.getUdpSendBufferSize()); udpReceiverFactory.start(); } else log.warn("UDP receiver factory not found"); } started = true; } } log.info("Gravity successfully started."); }
public void stop(boolean now) throws Exception { log.info("Stopping Gravity (now=%s)...", now); synchronized (this) { if (adapterFactory != null) { try { adapterFactory.stopAll(); } catch (Exception e) { log.error(e, "Error while stopping adapter factory"); } adapterFactory = null; } if (serverChannel != null) { try { removeChannel(serverChannel.getId(), false); } catch (Exception e) { log.error(e, "Error while removing server channel: %s", serverChannel); } serverChannel = null; } if (channelsTimer != null) { try { channelsTimer.cancel(); } catch (Exception e) { log.error(e, "Error while cancelling channels timer"); } channelsTimer = null; } if (gravityPool != null) { try { if (now) gravityPool.shutdownNow(); else gravityPool.shutdown(); } catch (Exception e) { log.error(e, "Error while stopping thread pool"); } gravityPool = null; } if (udpReceiverFactory != null) { try { udpReceiverFactory.stop(); } catch (Exception e) { log.error(e, "Error while stopping udp receiver factory"); } udpReceiverFactory = null; } started = false; } log.info("Gravity sucessfully stopped."); }
protected void createUdpReceiver(UdpReceiverFactory factory, AsyncHttpContext asyncHttpContext) { OutputStream os = null; try { Message connectMessage = asyncHttpContext.getConnectMessage(); if (udpReceiver == null || udpReceiver.isClosed()) udpReceiver = factory.newReceiver(this, asyncHttpContext.getRequest(), connectMessage); AsyncMessage reply = udpReceiver.acknowledge(connectMessage); HttpServletRequest request = asyncHttpContext.getRequest(); HttpServletResponse response = asyncHttpContext.getResponse(); GraniteContext context = HttpGraniteContext.createThreadIntance( gravity.getGraniteConfig(), gravity.getServicesConfig(), null, request, response); ((AMFContextImpl) context.getAMFContext()) .setCurrentAmf3Message(asyncHttpContext.getConnectMessage()); GravityServletUtil.serialize( gravity, response, new AsyncMessage[] {reply}, ContentType.forMimeType(request.getContentType())); } catch (ServletException e) { log.error(e, "Could not send UDP connect acknowledgement to channel: %s", this); } catch (IOException e) { log.error(e, "Could not send UDP connect acknowledgement to channel: %s", this); } finally { try { GraniteContext.release(); } catch (Exception e) { // should never happen... } // Close output stream. try { if (os != null) { try { os.close(); } catch (IOException e) { log.warn(e, "Could not close output stream (ignored)"); } } } finally { releaseAsyncHttpContext(asyncHttpContext); } } }
public boolean runReceived(AsyncHttpContext asyncHttpContext) { GravityInternal gravity = getGravity(); if (asyncHttpContext != null && gravity.hasUdpReceiverFactory()) { UdpReceiverFactory factory = gravity.getUdpReceiverFactory(); if (factory.isUdpConnectRequest(asyncHttpContext.getConnectMessage())) { createUdpReceiver(factory, asyncHttpContext); return true; } if (udpReceiver != null) { if (!udpReceiver.isClosed()) udpReceiver.close(false); udpReceiver = null; } } boolean httpAsParam = (asyncHttpContext != null); LinkedList<AsyncMessage> messages = null; OutputStream os = null; try { receivedQueueLock.lock(); try { // Do we have any pending messages? if (receivedQueue.isEmpty()) return false; // Do we have a valid http context? if (asyncHttpContext == null) { asyncHttpContext = acquireAsyncHttpContext(); if (asyncHttpContext == null) return false; } // Both conditions are ok, get all pending messages. messages = receivedQueue; receivedQueue = new LinkedList<AsyncMessage>(); } finally { receivedQueueLock.unlock(); } HttpServletRequest request = asyncHttpContext.getRequest(); HttpServletResponse response = asyncHttpContext.getResponse(); // Set response messages correlation ids to connect request message id. String correlationId = asyncHttpContext.getConnectMessage().getMessageId(); AsyncMessage[] messagesArray = new AsyncMessage[messages.size()]; int i = 0; for (AsyncMessage message : messages) { message.setCorrelationId(correlationId); messagesArray[i++] = message; } // Setup serialization context (thread local) GraniteContext context = HttpGraniteContext.createThreadIntance( gravity.getGraniteConfig(), gravity.getServicesConfig(), null, request, response); ((AMFContextImpl) context.getAMFContext()) .setCurrentAmf3Message(asyncHttpContext.getConnectMessage()); // Write messages to response output stream. GravityServletUtil.serialize( gravity, response, messagesArray, ContentType.forMimeType(request.getContentType())); return true; // Messages were delivered, http context isn't valid anymore. } catch (ServletException e) { log.error(e, "Configuration error for channel: %s", getId()); return true; } catch (IOException e) { log.warn(e, "Could not send messages to channel: %s (retrying later)", getId()); GravityConfig gravityConfig = getGravity().getGravityConfig(); if (gravityConfig.isRetryOnError()) { receivedQueueLock.lock(); try { if (receivedQueue.size() + messages.size() > gravityConfig.getMaxMessagesQueuedPerChannel()) { log.warn( "Channel %s has reached its maximum queue capacity %s (throwing %s messages)", getId(), gravityConfig.getMaxMessagesQueuedPerChannel(), messages.size()); } else receivedQueue.addAll(0, messages); } finally { receivedQueueLock.unlock(); } } return true; // Messages weren't delivered, but http context isn't valid anymore. } finally { // Cleanup serialization context (thread local) try { GraniteContext.release(); } catch (Exception e) { // should never happen... } // Close output stream. try { if (os != null) { try { os.close(); } catch (IOException e) { log.warn(e, "Could not close output stream (ignored)"); } } } finally { // Cleanup http context (only if this method wasn't explicitly called with a non null // AsyncHttpContext from the servlet). if (!httpAsParam) releaseAsyncHttpContext(asyncHttpContext); } } }