From ddf73077b37cb014aa0a895f8d12b496fdc216bf Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 20 Mar 2015 15:48:54 +0100 Subject: [PATCH] Support for concurrencies: none, thread and SCOOP --- .../ewsgi/connectors/httpd/httpd-safe.ecf | 6 ++ .../none/httpd_connection_handler.e | 39 ++++------- .../concurrency/none/httpd_request_handler.e | 7 +- .../scoop/httpd_connection_handler.e | 2 +- .../concurrency/scoop/httpd_request_handler.e | 43 ++---------- .../thread/httpd_connection_handler.e | 43 +++++------- .../thread/httpd_request_handler.e | 12 ++-- .../httpd/src/httpd/httpd_request_handler_i.e | 65 +++++++++++++------ 8 files changed, 93 insertions(+), 124 deletions(-) diff --git a/library/server/ewsgi/connectors/httpd/httpd-safe.ecf b/library/server/ewsgi/connectors/httpd/httpd-safe.ecf index 51f30ddd..c308c705 100644 --- a/library/server/ewsgi/connectors/httpd/httpd-safe.ecf +++ b/library/server/ewsgi/connectors/httpd/httpd-safe.ecf @@ -80,4 +80,10 @@ + + + + + + diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e index 79ae936a..f420c4d7 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e @@ -31,42 +31,25 @@ feature -- Access feature -- Execution - process_incoming_connection (a_socket: HTTPD_STREAM_SOCKET) - -- Process incoming connection - -- note that the precondition matters for scoop synchronization. + accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET) + local + cl: HTTPD_STREAM_SOCKET do is_shutdown_requested := is_shutdown_requested or shutdown_requested (server) if is_shutdown_requested then - a_socket.cleanup - elseif attached server.factory.new_handler as h then - process_connection_handler (h, a_socket) + -- Cancel + elseif attached factory.new_handler as h then + cl := h.client_socket + a_listening_socket.accept_to (cl) + if h.is_connected then + h.execute + end else check is_not_full: False end - a_socket.cleanup end update_is_shutdown_requested end - process_connection_handler (hdl: HTTPD_REQUEST_HANDLER; a_socket: HTTPD_STREAM_SOCKET) - require - not hdl.has_error - do - --| FIXME jfiat [2011/11/03] : should use a Pool of Threads/Handler to process this connection - --| also handle permanent connection...? - - hdl.set_client_socket (a_socket) - if not hdl.has_error then --- hdl.set_logger (server) - hdl.execute - else - log ("Internal error (set_client_socket failed)") - end - rescue - log ("Releasing handler after exception!") - hdl.release - a_socket.cleanup - end - update_is_shutdown_requested do is_shutdown_requested := shutdown_requested (server) @@ -89,7 +72,7 @@ feature {HTTPD_SERVER_I} -- Status report end note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler.e index 1e607c5e..535255c4 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler.e @@ -10,15 +10,10 @@ deferred class inherit HTTPD_REQUEST_HANDLER_I -feature -- Change - set_client_socket (a_socket: HTTPD_STREAM_SOCKET) - do - client_socket := a_socket - end note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e index 1bd658cc..e90c89d4 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e @@ -96,7 +96,7 @@ feature {HTTPD_SERVER_I} -- Execution require hdl.is_connected do - hdl.separate_execute + hdl.safe_execute end feature {HTTPD_SERVER_I} -- Status report diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e index 9f20e627..4055f7e2 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e @@ -20,56 +20,21 @@ inherit release as release_pool_item end -feature -- Status report - - is_connected: BOOLEAN - -- Is handler connected to incoming request via `client_socket'? - do - Result := client_socket.descriptor_available - end - -feature -- Execution - - separate_execute - local - retried: BOOLEAN - do - if retried then - release (client_socket) - else - if - not has_error and then - is_connected - then - execute (client_socket) - end - separate_release - end - rescue - retried := True - retry - end - feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation - separate_release - do - release (client_socket) - end - - release (a_socket: detachable HTTPD_STREAM_SOCKET) + release local d: STRING do - if a_socket /= Void then - d := a_socket.descriptor.out + if attached internal_client_socket as l_socket then + d := l_socket.descriptor.out else d := "N/A" end debug ("dbglog") dbglog (generator + ".release: ENTER {" + d + "}") end - Precursor {HTTPD_REQUEST_HANDLER_I} (a_socket) + Precursor {HTTPD_REQUEST_HANDLER_I} release_pool_item debug ("dbglog") dbglog (generator + ".release: LEAVE {" + d + "}") diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_connection_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_connection_handler.e index d3d1354e..d6bebdc1 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_connection_handler.e @@ -50,36 +50,27 @@ feature {HTTPD_SERVER_I} -- Execution p.terminate end - process_incoming_connection (a_socket: HTTPD_STREAM_SOCKET) + accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET) + local + cl: separate HTTPD_STREAM_SOCKET do - if is_shutdown_requested then - a_socket.cleanup - else - process_connection_handler (factory.new_handler, a_socket) + debug ("dbglog") + dbglog (generator + ".ENTER accept_connection {"+ a_listening_socket.descriptor.out +"}") + end + + if is_shutdown_requested then + -- cancel + elseif attached factory.new_handler as h then + cl := h.client_socket + a_listening_socket.accept_to (cl) + if h.is_connected then + pool.add_work (agent h.safe_execute) + end end - end - process_connection_handler (hdl: separate HTTPD_REQUEST_HANDLER; a_socket: HTTPD_STREAM_SOCKET) - require - not hdl.has_error - do debug ("dbglog") - dbglog (generator + ".ENTER process_connection_handler {"+ a_socket.descriptor.out +"}") + dbglog (generator + ".LEAVE accept_incoming_connection {"+ a_listening_socket.descriptor.out +"}") end - if not hdl.has_error then --- hdl.set_logger (server) --- hdl.set_client_socket (a_socket) - pool.add_work (agent hdl.execute (a_socket)) - else - log ("Internal error (set_client_socket failed)") - end - debug ("dbglog") - dbglog (generator + ".LEAVE process_connection_handler {"+ a_socket.descriptor.out +"}") - end - rescue - log ("Releasing handler after exception!") - hdl.release (a_socket) --- hdl.client_socket.cleanup end feature {HTTPD_SERVER_I} -- Status report @@ -99,7 +90,7 @@ invariant pool_attached: pool /= Void note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler.e index a119e283..e053bfe7 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler.e @@ -17,23 +17,27 @@ inherit feature {HTTPD_CONNECTION_HANDLER_I} -- Basic operation - release (a_socket: HTTPD_STREAM_SOCKET) + release local d: STRING do -- FIXME: for log purpose - d := a_socket.descriptor.out + if attached internal_client_socket as l_socket then + d := l_socket.descriptor.out + else + d := "N/A" + end debug ("dbglog") dbglog (generator + ".release: ENTER {" + d + "}") end - Precursor {HTTPD_REQUEST_HANDLER_I} (a_socket) + Precursor {HTTPD_REQUEST_HANDLER_I} debug ("dbglog") dbglog (generator + ".release: LEAVE {" + d + "}") end end note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e index 2411d637..8d85e5f0 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e @@ -34,7 +34,14 @@ feature {NONE} -- Initialization create request_header.make_empty create request_header_map.make (10) - is_waiting := False + end + +feature -- Status report + + is_connected: BOOLEAN + -- Is handler connected to incoming request via `client_socket'? + do + Result := client_socket.descriptor_available end feature -- Access @@ -78,8 +85,6 @@ feature -- Settings feature -- Status report - is_waiting: BOOLEAN - has_error: BOOLEAN -- Error occurred during `analyze_request_message' @@ -92,36 +97,60 @@ feature -- Change feature -- Execution - execute (a_socket: HTTPD_STREAM_SOCKET) + safe_execute + local + retried: BOOLEAN + do + if retried then + release + else + if + not has_error and then + is_connected + then + execute + end + release + end + rescue + retried := True + retry + end + + execute require - socket_attached: a_socket /= Void - socket_valid: a_socket.is_open_read and then a_socket.is_open_write - a_http_socket: not a_socket.is_closed + is_connected: is_connected local l_remote_info: detachable like remote_info l_continue: BOOLEAN + l_socket: like client_socket do - if a_socket.is_closed then + l_socket := client_socket + check + socket_attached: l_socket /= Void + socket_valid: l_socket.is_open_read and then l_socket.is_open_write + end + if l_socket.is_closed then debug ("dbglog") dbglog (generator + ".execute {socket is Closed!}") end else debug ("dbglog") - dbglog (generator + ".execute {" + a_socket.descriptor.out + "} ENTER") + dbglog (generator + ".execute socket=" + l_socket.descriptor.out + " ENTER") end from until l_continue loop - if a_socket.ready_for_reading then + if l_socket.ready_for_reading then l_continue := True create l_remote_info - if attached a_socket.peer_address as l_addr then + if attached l_socket.peer_address as l_addr then l_remote_info.addr := l_addr.host_address.host_address l_remote_info.hostname := l_addr.host_address.host_name l_remote_info.port := l_addr.port remote_info := l_remote_info end - analyze_request_message (a_socket) + analyze_request_message (l_socket) else - log (generator + ".execute {" + a_socket.descriptor.out + "} WAITING") + log (generator + ".execute socket=" + l_socket.descriptor.out + "} WAITING") end end @@ -132,20 +161,16 @@ feature -- Execution log ("ERROR: invalid HTTP incoming request") end else - process_request (a_socket) + process_request (l_socket) end debug ("dbglog") - dbglog (generator + ".execute {" + a_socket.descriptor.out + "} LEAVE") + dbglog (generator + ".execute {" + l_socket.descriptor.out + "} LEAVE") end end --- release (a_socket) end - release (a_socket: detachable HTTPD_STREAM_SOCKET) + release do - if a_socket /= Void then - a_socket.cleanup - end reset end