From 3da80fce0dccc4b77d600f28b2fa4dda5f7adfdf Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 20 Mar 2015 13:37:54 +0100 Subject: [PATCH] Finally SCOOP supported. --- .../connectors/httpd/dev/app_wsf_execution.e | 12 ++++ .../httpd/dev/httpd_connector_dev.e | 7 +- .../ewsgi/connectors/httpd/httpd-safe.ecf | 19 ++++-- .../scoop/httpd_connection_handler.e | 46 +++++-------- .../concurrency/scoop/httpd_request_handler.e | 67 ++++++------------- .../scoop/httpd_request_handler_factory.e | 9 ++- .../concurrency/scoop/pool/concurrent_pool.e | 7 +- .../scoop/pool/concurrent_pool_factory.e | 15 ++++- .../httpd/src/httpd/httpd_debug_facilities.e | 15 ++++- .../httpd/src/httpd/httpd_request_handler_i.e | 35 +++++++--- .../httpd/src/httpd/httpd_server_i.e | 10 +-- .../src/httpd/network/httpd_stream_socket.e | 8 +++ 12 files changed, 143 insertions(+), 107 deletions(-) diff --git a/library/server/ewsgi/connectors/httpd/dev/app_wsf_execution.e b/library/server/ewsgi/connectors/httpd/dev/app_wsf_execution.e index b4e817a5..2a87ee9c 100644 --- a/library/server/ewsgi/connectors/httpd/dev/app_wsf_execution.e +++ b/library/server/ewsgi/connectors/httpd/dev/app_wsf_execution.e @@ -10,6 +10,8 @@ class inherit WSF_EXECUTION + SHARED_EXECUTION_ENVIRONMENT + create make @@ -18,12 +20,22 @@ feature -- Execution execute local s: STRING + i64: INTEGER_64 do s := "Hello Concurrent EWF" s.append (" (counter=") s.append_integer (next_cell_counter_item (counter_cell)) s.append (")%N") + if attached {WSF_STRING} request.query_parameter ("sleep") as p_sleep then + if attached p_sleep.value.is_integer then + s.append ("sleep for ") + i64 := p_sleep.value.to_integer_64 * {INTEGER_64} 1_000_000_000 + s.append_integer_64 (i64) + execution_environment.sleep (i64) + end + end + response.set_status_code (200) response.put_header_line ("X-EWF-Dev: v1.0") response.header.put_content_type_text_plain diff --git a/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e b/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e index 80dfcd4e..a12bc301 100644 --- a/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e +++ b/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e @@ -17,12 +17,17 @@ feature {NONE} -- Initialization make -- Initialize `Current'. local - server: HTTPD_SERVER + server: separate HTTPD_SERVER fac: separate WSF_HTTPD_REQUEST_HANDLER_FACTORY [APP_WSF_EXECUTION] do print ("Hello%N") create fac create server.make (fac) + launch_server (server) + end + + launch_server (server: separate HTTPD_SERVER) + do server.configuration.set_max_concurrent_connections (100) server.configuration.set_http_server_port (9090) server.launch diff --git a/library/server/ewsgi/connectors/httpd/httpd-safe.ecf b/library/server/ewsgi/connectors/httpd/httpd-safe.ecf index 38f010d3..51f30ddd 100644 --- a/library/server/ewsgi/connectors/httpd/httpd-safe.ecf +++ b/library/server/ewsgi/connectors/httpd/httpd-safe.ecf @@ -7,15 +7,19 @@ /\.git$ /\.svn$ - - - + + + @@ -27,12 +31,13 @@ + - /ssl$ + /concurrency$ /EIFGENs$ /no_ssl$ - /concurrency$ + /ssl$ @@ -68,6 +73,10 @@ + 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 60141ef7..1bd658cc 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 @@ -59,14 +59,16 @@ feature {HTTPD_SERVER_I} -- Execution accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET) do - accept_connection_on_pool (a_listening_socket, pool) -- Wait on not pool.is_full or is_stop_requested + accept_connection_on_pool (pool, a_listening_socket) -- Wait on not pool.is_full or is_stop_requested end - accept_connection_on_pool (a_listening_socket: HTTPD_STREAM_SOCKET; a_pool: like pool) + accept_connection_on_pool (a_pool: like pool; a_listening_socket: HTTPD_STREAM_SOCKET) -- Process accept connection -- note that the precondition matters for scoop synchronization. require concurrency: not a_pool.is_full or is_shutdown_requested or a_pool.stop_requested + local + cl: separate HTTPD_STREAM_SOCKET do debug ("dbglog") dbglog (generator + ".ENTER accept_connection_on_pool") @@ -74,7 +76,9 @@ feature {HTTPD_SERVER_I} -- Execution if is_shutdown_requested then -- Cancel elseif attached a_pool.separate_item (factory) as h then - process_request_handler_on_accept (h, a_listening_socket) + cl := separate_client_socket (h) + a_listening_socket.accept_to (cl) + process_handler (h) else check is_not_full: False end end @@ -83,36 +87,16 @@ feature {HTTPD_SERVER_I} -- Execution end end - process_request_handler_on_accept (hdl: separate HTTPD_REQUEST_HANDLER; a_listening_socket: HTTPD_STREAM_SOCKET) - require - not hdl.has_error + separate_client_socket (hdl: separate HTTPD_REQUEST_HANDLER): separate HTTPD_STREAM_SOCKET do - --| FIXME jfiat [2011/11/03] : should use a Pool of Threads/Handler to process this connection - --| also handle permanent connection...? + Result := hdl.client_socket + end - debug ("dbglog") - dbglog (generator + ".ENTER process_request_handler_on_accept") - end - - hdl.set_listening_socket (a_listening_socket) - --- hdl.accept_from_listening_socket (a_listening_socket) - if hdl.has_error then - log ("Internal error (accept_from_listening_socket failed)") - else --- hdl.set_logger (server) - if attached hdl.separate_execution as l_result then - - end - hdl.separate_release - end - debug ("dbglog") - dbglog (generator + ".LEAVE process_request_handler_on_accept") - end - rescue - log ("Releasing handler after exception!") - hdl.separate_release --- a_socket.cleanup + process_handler (hdl: separate HTTPD_REQUEST_HANDLER) + require + hdl.is_connected + do + hdl.separate_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 638d41fc..9f20e627 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,77 +20,52 @@ inherit release as release_pool_item end -feature -- Change +feature -- Status report - set_listening_socket (a_listening_socket: separate HTTPD_STREAM_SOCKET) + is_connected: BOOLEAN + -- Is handler connected to incoming request via `client_socket'? do - listening_socket := a_listening_socket + Result := client_socket.descriptor_available end - accept_from_listening_socket (a_listening_socket: separate HTTPD_STREAM_SOCKET) +feature -- Execution + + separate_execute local retried: BOOLEAN - s: like client_socket do if retried then - has_error := True + release (client_socket) else - create s.make_empty - client_socket := s - debug ("dbglog") - dbglog ("before accept_to") - end - print ("[EWF/DBG] <#" + processor_id_from_object (Current).out + "> accept_to%N") - a_listening_socket.accept_to (s) - - if s.is_created then - debug ("dbglog") - dbglog ("after accept_to " + s.descriptor.out) - end - else - debug ("dbglog") - dbglog ("after accept_to ERROR") - end - - has_error := True - client_socket := Void + if + not has_error and then + is_connected + then + execute (client_socket) end + separate_release end rescue retried := True retry end -feature -- Execution - - separate_execution: BOOLEAN - do - Result := False - if attached listening_socket as l_listening_socket then - accept_from_listening_socket (l_listening_socket) - if not has_error then - if attached client_socket as s then - execute (s) - Result := True - end - end - end - end - feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation separate_release do - if attached client_socket as s then - release (s) - end + release (client_socket) end - release (a_socket: HTTPD_STREAM_SOCKET) + release (a_socket: detachable HTTPD_STREAM_SOCKET) local d: STRING do - d := a_socket.descriptor.out + if a_socket /= Void then + d := a_socket.descriptor.out + else + d := "N/A" + end debug ("dbglog") dbglog (generator + ".release: ENTER {" + d + "}") end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler_factory.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler_factory.e index 843fc8e3..56fa78d6 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler_factory.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler_factory.e @@ -16,6 +16,13 @@ inherit end note - copyright: "2011-2013, Javier Velilla, Jocelyn Fiat 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 + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool.e index 0bead25a..a26156da 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool.e @@ -88,6 +88,7 @@ feature -- Access count := count + 1 busy_items [pos] := True Result := l_item + a_factory.update_item (l_item) end end end @@ -159,17 +160,13 @@ feature -- Change feature {NONE} -- Implementation --- new_separate_item: separate G --- deferred --- end - register_item (a_item: separate G) do a_item.set_pool (Current) 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/pool/concurrent_pool_factory.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e index 497fbb69..51205fb3 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e @@ -9,11 +9,24 @@ deferred class feature -- Access + update_item (a_item: separate G) + -- Update `a_item' for optionally purpose. + do + end + new_separate_item: separate G + -- New separated object of type {G}. deferred end note - copyright: "2011-2013, Javier Velilla, Jocelyn Fiat 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 + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_debug_facilities.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_debug_facilities.e index ac1b0051..77704e5b 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_debug_facilities.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_debug_facilities.e @@ -12,9 +12,20 @@ feature {NONE} -- Output dbglog (m: READABLE_STRING_8) require not m.ends_with_general ("%N") + local + s: STRING do debug ("dbglog") - print ("[EWF/DBG] <#" + processor_id_from_object (Current).out + "> " + m + "%N") + create s.make (24) + s.append ("[EWF/DBG] <#") + s.append_integer (processor_id_from_object (Current)) + s.append ("> ") + s.append (generator) + s.append (create {STRING}.make_filled (' ', (46 - s.count).max (0))) + s.append (" | ") + s.append (m) + s.append ("%N") + print (s) end end @@ -28,7 +39,7 @@ feature -- runtime 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 e1d376cd..2411d637 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 @@ -23,12 +23,10 @@ feature {NONE} -- Initialization version := Void remote_info := Void - if attached client_socket as l_sock then + if attached internal_client_socket as l_sock then l_sock.cleanup end - client_socket := Void - - listening_socket := Void + internal_client_socket := Void -- FIXME: optimize to just wipe_out if needed create method.make_empty @@ -36,13 +34,24 @@ feature {NONE} -- Initialization create request_header.make_empty create request_header_map.make (10) + is_waiting := False end feature -- Access - client_socket: detachable HTTPD_STREAM_SOCKET + internal_client_socket: detachable HTTPD_STREAM_SOCKET - listening_socket: detachable separate HTTPD_STREAM_SOCKET + client_socket: HTTPD_STREAM_SOCKET + local + s: like internal_client_socket + do + s := internal_client_socket + if s = Void then + create s.make_empty + internal_client_socket := s + end + Result := s + end request_header: STRING -- Header' source @@ -69,6 +78,8 @@ feature -- Settings feature -- Status report + is_waiting: BOOLEAN + has_error: BOOLEAN -- Error occurred during `analyze_request_message' @@ -96,7 +107,7 @@ feature -- Execution end else debug ("dbglog") - dbglog (generator + ".ENTER execute {" + a_socket.descriptor.out + "}") + dbglog (generator + ".execute {" + a_socket.descriptor.out + "} ENTER") end from until l_continue loop if a_socket.ready_for_reading then @@ -110,7 +121,7 @@ feature -- Execution end analyze_request_message (a_socket) else - log (generator + ".WAITING execute {" + a_socket.descriptor.out + "}") + log (generator + ".execute {" + a_socket.descriptor.out + "} WAITING") end end @@ -124,15 +135,17 @@ feature -- Execution process_request (a_socket) end debug ("dbglog") - dbglog (generator + ".LEAVE execute {" + a_socket.descriptor.out + "}") + dbglog (generator + ".execute {" + a_socket.descriptor.out + "} LEAVE") end end -- release (a_socket) end - release (a_socket: HTTPD_STREAM_SOCKET) + release (a_socket: detachable HTTPD_STREAM_SOCKET) do - a_socket.cleanup + if a_socket /= Void then + a_socket.cleanup + end reset end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e index ff9adcb9..c8b0f494 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e @@ -154,10 +154,12 @@ feature -- Listening create l_connection_handler.make (Current) from l_listening_socket.listen (configuration.max_tcp_clients) - if is_verbose and then configuration.is_secure then - log ("%NHTTP Connection Server ready on port " + l_http_port.out +" : https://localhost:" + l_http_port.out + "/") - elseif is_verbose then - log ("%NHTTP Connection Server ready on port " + l_http_port.out +" : http://localhost:" + l_http_port.out + "/") + if is_verbose then + if configuration.is_secure then + log ("%NHTTP Connection Server ready on port " + l_http_port.out +" : https://localhost:" + l_http_port.out + "/") + else + log ("%NHTTP Connection Server ready on port " + l_http_port.out +" : http://localhost:" + l_http_port.out + "/") + end end on_launched (l_http_port) until diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e b/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e index 4cf3f162..e9221910 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e @@ -46,6 +46,14 @@ feature {NONE} -- Initialization do Result := s.socket.descriptor end +feature -- Change + + set_accept_timeout (n: INTEGER) + do + if attached {NETWORK_STREAM_SOCKET} socket as l_socket then + l_socket.set_accept_timeout (500_000) + end + end feature -- Access