@Override public int execute(final long r, final long c) { if (r == 0) { // by worker init process NginxResponse resp = handleRequest(makeRequest(0, 0)); if (resp != null && resp.type() == NginxResponse.TYPE_FAKE_ASYNC_TAG && resp.fetchStatus(200) != 200) { log.error("initialize error %s", resp); return NGX_HTTP_INTERNAL_SERVER_ERROR; } return NGX_HTTP_OK; } final NginxRequest req = makeRequest(r, c); int phase = req.phase(); if (workers == null) { NginxResponse resp = handleRequest(req); if (resp.type() == NginxResponse.TYPE_FAKE_ASYNC_TAG) { if (!req.isReleased() && !req.isHijacked() && (phase == -1 || phase == NGX_HTTP_HEADER_FILTER_PHASE)) { // from content handler invoking ngx_http_clojure_mem_inc_req_count(r); } return NGX_DONE; } return handleResponse(req, resp); } // for safe access with another thread req.prefetchAll(); if (phase == -1 || phase == NGX_HTTP_HEADER_FILTER_PHASE) { // -1 means from content handler invoking ngx_http_clojure_mem_inc_req_count(r); } workers.submit( new Callable<NginxClojureRT.WorkerResponseContext>() { @Override public WorkerResponseContext call() throws Exception { NginxResponse resp = handleRequest(req); // let output chain built before entering the main thread return new WorkerResponseContext(resp, req); } }); return NGX_DONE; }
@SuppressWarnings("rawtypes") @Override public void run() throws SuspendExecution { try { response = request.handler().process(request); } catch (Throwable e) { response = buildUnhandledExceptionResponse(request, e); log.error("unhandled exception in coroutine", e); } if (Coroutine.getActiveCoroutine().getResumeCounter() != 1) { request.handler().completeAsyncResponse(request, response); } }
public NginxUnhandledExceptionResponse(NginxRequest r, Throwable e) { this.err = e; this.r = r; if (r.isReleased()) { this.type = TYPE_FATAL; } else { this.type = TYPE_ERROR; } }
@Override public <K, V> long prepareHeaders( NginxRequest req, long status, Collection<Map.Entry<K, V>> headers) { long r = req.nativeRequest(); long pool = UNSAFE.getAddress(r + NGX_HTTP_CLOJURE_REQ_POOL_OFFSET); long headers_out = r + NGX_HTTP_CLOJURE_REQ_HEADERS_OUT_OFFSET; String contentType = null; String server = null; if (headers != null) { for (Map.Entry<?, ?> hen : headers) { Object nameObj = hen.getKey(); Object val = hen.getValue(); if (nameObj == null || val == null) { continue; } String name = normalizeHeaderName(nameObj); if (name == null || name.length() == 0) { continue; } NginxHeaderHolder pusher = fetchResponseHeaderPusher(name); if (pusher == RESP_CONTENT_TYPE_HOLDER) { if (val instanceof String) { contentType = (String) val; } else { // TODO:support another types } } pusher.push(headers_out, pool, val); } } if (contentType == null && status != NGX_HTTP_SWITCHING_PROTOCOLS) { ngx_http_set_content_type(r); } else { int contentTypeLen = pushNGXString( headers_out + NGX_HTTP_CLOJURE_HEADERSO_CONTENT_TYPE_OFFSET, contentType, DEFAULT_ENCODING, pool); // be friendly to gzip module pushNGXSizet(headers_out + NGX_HTTP_CLOJURE_HEADERSO_CONTENT_TYPE_LEN_OFFSET, contentTypeLen); } pushNGXInt(headers_out + NGX_HTTP_CLOJURE_HEADERSO_STATUS_OFFSET, (int) status); return r; }
public static NginxResponse handleRequest(final NginxRequest req) { try { if (coroutineEnabled) { CoroutineRunner coroutineRunner = new CoroutineRunner(req); Coroutine coroutine = new Coroutine(coroutineRunner); coroutine.resume(); if (coroutine.getState() == Coroutine.State.FINISHED) { return coroutineRunner.response; } else { return new NginxJavaResponse(req, Constants.ASYNC_TAG); } } else { return req.handler().process(req); } } catch (Throwable e) { log.error("server unhandled exception!", e); return buildUnhandledExceptionResponse(req, e); } }