Finally SCOOP supported.

This commit is contained in:
2015-03-20 13:37:54 +01:00
parent 0970de5dc6
commit 3da80fce0d
12 changed files with 143 additions and 107 deletions

View File

@@ -10,6 +10,8 @@ class
inherit inherit
WSF_EXECUTION WSF_EXECUTION
SHARED_EXECUTION_ENVIRONMENT
create create
make make
@@ -18,12 +20,22 @@ feature -- Execution
execute execute
local local
s: STRING s: STRING
i64: INTEGER_64
do do
s := "Hello Concurrent EWF" s := "Hello Concurrent EWF"
s.append (" (counter=") s.append (" (counter=")
s.append_integer (next_cell_counter_item (counter_cell)) s.append_integer (next_cell_counter_item (counter_cell))
s.append (")%N") 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.set_status_code (200)
response.put_header_line ("X-EWF-Dev: v1.0") response.put_header_line ("X-EWF-Dev: v1.0")
response.header.put_content_type_text_plain response.header.put_content_type_text_plain

View File

@@ -17,12 +17,17 @@ feature {NONE} -- Initialization
make make
-- Initialize `Current'. -- Initialize `Current'.
local local
server: HTTPD_SERVER server: separate HTTPD_SERVER
fac: separate WSF_HTTPD_REQUEST_HANDLER_FACTORY [APP_WSF_EXECUTION] fac: separate WSF_HTTPD_REQUEST_HANDLER_FACTORY [APP_WSF_EXECUTION]
do do
print ("Hello%N") print ("Hello%N")
create fac create fac
create server.make (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_max_concurrent_connections (100)
server.configuration.set_http_server_port (9090) server.configuration.set_http_server_port (9090)
server.launch server.launch

View File

@@ -7,15 +7,19 @@
<exclude>/\.git$</exclude> <exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude> <exclude>/\.svn$</exclude>
</file_rule> </file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="transitional"> <option debug="true" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
<debug name="dbglog" enabled="true"/>
</option> </option>
<setting name="concurrency" value="scoop"/> <setting name="concurrency" value="scoop"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/> <library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="encoder" location="..\..\..\..\text\encoder\encoder-safe.ecf"/> <library name="encoder" location="..\..\..\..\text\encoder\encoder-safe.ecf"/>
<library name="ewsgi" location="..\..\ewsgi-safe.ecf" readonly="false"/> <library name="ewsgi" location="..\..\ewsgi-safe.ecf" readonly="false"/>
<library name="wsf" location="..\..\..\wsf\wsf-safe.ecf" readonly="false"/>
<library name="http" location="..\..\..\..\network\protocol\http\http-safe.ecf"/> <library name="http" location="..\..\..\..\network\protocol\http\http-safe.ecf"/>
<library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf"/> <library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf">
<option>
<assertions precondition="true" postcondition="true" check="true"/>
</option>
</library>
<library name="net_ssl" location="$ISE_LIBRARY\unstable\library\network\socket\netssl\net_ssl-safe.ecf"> <library name="net_ssl" location="$ISE_LIBRARY\unstable\library\network\socket\netssl\net_ssl-safe.ecf">
<condition> <condition>
<custom name="httpd_ssl_enabled" value="true"/> <custom name="httpd_ssl_enabled" value="true"/>
@@ -27,12 +31,13 @@
</condition> </condition>
</library> </library>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/> <library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="wsf" location="..\..\..\wsf\wsf-safe.ecf" readonly="false"/>
<cluster name="httpd_server" location=".\src\httpd\" recursive="true"> <cluster name="httpd_server" location=".\src\httpd\" recursive="true">
<file_rule> <file_rule>
<exclude>/ssl$</exclude> <exclude>/concurrency$</exclude>
<exclude>/EIFGENs$</exclude> <exclude>/EIFGENs$</exclude>
<exclude>/no_ssl$</exclude> <exclude>/no_ssl$</exclude>
<exclude>/concurrency$</exclude> <exclude>/ssl$</exclude>
</file_rule> </file_rule>
<cluster name="no_ssl" location="$|no_ssl\" recursive="true"> <cluster name="no_ssl" location="$|no_ssl\" recursive="true">
<condition> <condition>
@@ -68,6 +73,10 @@
</target> </target>
<target name="dev" extends="connector_httpd"> <target name="dev" extends="connector_httpd">
<root class="HTTPD_CONNECTOR_DEV" feature="make"/> <root class="HTTPD_CONNECTOR_DEV" feature="make"/>
<option debug="true">
<debug name="dbglog" enabled="true"/>
<assertions precondition="true" postcondition="true" check="true" supplier_precondition="true"/>
</option>
<setting name="concurrency" value="scoop"/> <setting name="concurrency" value="scoop"/>
<cluster name="dev" location="dev\" recursive="true"/> <cluster name="dev" location="dev\" recursive="true"/>
</target> </target>

View File

@@ -59,14 +59,16 @@ feature {HTTPD_SERVER_I} -- Execution
accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET) accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET)
do 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 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 -- Process accept connection
-- note that the precondition matters for scoop synchronization. -- note that the precondition matters for scoop synchronization.
require require
concurrency: not a_pool.is_full or is_shutdown_requested or a_pool.stop_requested concurrency: not a_pool.is_full or is_shutdown_requested or a_pool.stop_requested
local
cl: separate HTTPD_STREAM_SOCKET
do do
debug ("dbglog") debug ("dbglog")
dbglog (generator + ".ENTER accept_connection_on_pool") dbglog (generator + ".ENTER accept_connection_on_pool")
@@ -74,7 +76,9 @@ feature {HTTPD_SERVER_I} -- Execution
if is_shutdown_requested then if is_shutdown_requested then
-- Cancel -- Cancel
elseif attached a_pool.separate_item (factory) as h then 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 else
check is_not_full: False end check is_not_full: False end
end end
@@ -83,36 +87,16 @@ feature {HTTPD_SERVER_I} -- Execution
end end
end end
process_request_handler_on_accept (hdl: separate HTTPD_REQUEST_HANDLER; a_listening_socket: HTTPD_STREAM_SOCKET) separate_client_socket (hdl: separate HTTPD_REQUEST_HANDLER): separate HTTPD_STREAM_SOCKET
require
not hdl.has_error
do do
--| FIXME jfiat [2011/11/03] : should use a Pool of Threads/Handler to process this connection Result := hdl.client_socket
--| also handle permanent connection...?
debug ("dbglog")
dbglog (generator + ".ENTER process_request_handler_on_accept")
end end
hdl.set_listening_socket (a_listening_socket) process_handler (hdl: separate HTTPD_REQUEST_HANDLER)
require
-- hdl.accept_from_listening_socket (a_listening_socket) hdl.is_connected
if hdl.has_error then do
log ("Internal error (accept_from_listening_socket failed)") hdl.separate_execute
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
end end
feature {HTTPD_SERVER_I} -- Status report feature {HTTPD_SERVER_I} -- Status report

View File

@@ -20,77 +20,52 @@ inherit
release as release_pool_item release as release_pool_item
end 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 do
listening_socket := a_listening_socket Result := client_socket.descriptor_available
end end
accept_from_listening_socket (a_listening_socket: separate HTTPD_STREAM_SOCKET) feature -- Execution
separate_execute
local local
retried: BOOLEAN retried: BOOLEAN
s: like client_socket
do do
if retried then if retried then
has_error := True release (client_socket)
else else
create s.make_empty if
client_socket := s not has_error and then
debug ("dbglog") is_connected
dbglog ("before accept_to") then
end execute (client_socket)
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
end end
separate_release
end end
rescue rescue
retried := True retried := True
retry retry
end 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 feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation
separate_release separate_release
do do
if attached client_socket as s then release (client_socket)
release (s)
end
end end
release (a_socket: HTTPD_STREAM_SOCKET) release (a_socket: detachable HTTPD_STREAM_SOCKET)
local local
d: STRING d: STRING
do do
if a_socket /= Void then
d := a_socket.descriptor.out d := a_socket.descriptor.out
else
d := "N/A"
end
debug ("dbglog") debug ("dbglog")
dbglog (generator + ".release: ENTER {" + d + "}") dbglog (generator + ".release: ENTER {" + d + "}")
end end

View File

@@ -16,6 +16,13 @@ inherit
end end
note 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)" 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 end

View File

@@ -88,6 +88,7 @@ feature -- Access
count := count + 1 count := count + 1
busy_items [pos] := True busy_items [pos] := True
Result := l_item Result := l_item
a_factory.update_item (l_item)
end end
end end
end end
@@ -159,17 +160,13 @@ feature -- Change
feature {NONE} -- Implementation feature {NONE} -- Implementation
-- new_separate_item: separate G
-- deferred
-- end
register_item (a_item: separate G) register_item (a_item: separate G)
do do
a_item.set_pool (Current) a_item.set_pool (Current)
end end
note 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software

View File

@@ -9,11 +9,24 @@ deferred class
feature -- Access feature -- Access
update_item (a_item: separate G)
-- Update `a_item' for optionally purpose.
do
end
new_separate_item: separate G new_separate_item: separate G
-- New separated object of type {G}.
deferred deferred
end end
note 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)" 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 end

View File

@@ -12,9 +12,20 @@ feature {NONE} -- Output
dbglog (m: READABLE_STRING_8) dbglog (m: READABLE_STRING_8)
require require
not m.ends_with_general ("%N") not m.ends_with_general ("%N")
local
s: STRING
do do
debug ("dbglog") 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
end end
@@ -28,7 +39,7 @@ feature -- runtime
end end
note 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software

View File

@@ -23,12 +23,10 @@ feature {NONE} -- Initialization
version := Void version := Void
remote_info := Void remote_info := Void
if attached client_socket as l_sock then if attached internal_client_socket as l_sock then
l_sock.cleanup l_sock.cleanup
end end
client_socket := Void internal_client_socket := Void
listening_socket := Void
-- FIXME: optimize to just wipe_out if needed -- FIXME: optimize to just wipe_out if needed
create method.make_empty create method.make_empty
@@ -36,13 +34,24 @@ feature {NONE} -- Initialization
create request_header.make_empty create request_header.make_empty
create request_header_map.make (10) create request_header_map.make (10)
is_waiting := False
end end
feature -- Access 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 request_header: STRING
-- Header' source -- Header' source
@@ -69,6 +78,8 @@ feature -- Settings
feature -- Status report feature -- Status report
is_waiting: BOOLEAN
has_error: BOOLEAN has_error: BOOLEAN
-- Error occurred during `analyze_request_message' -- Error occurred during `analyze_request_message'
@@ -96,7 +107,7 @@ feature -- Execution
end end
else else
debug ("dbglog") debug ("dbglog")
dbglog (generator + ".ENTER execute {" + a_socket.descriptor.out + "}") dbglog (generator + ".execute {" + a_socket.descriptor.out + "} ENTER")
end end
from until l_continue loop from until l_continue loop
if a_socket.ready_for_reading then if a_socket.ready_for_reading then
@@ -110,7 +121,7 @@ feature -- Execution
end end
analyze_request_message (a_socket) analyze_request_message (a_socket)
else else
log (generator + ".WAITING execute {" + a_socket.descriptor.out + "}") log (generator + ".execute {" + a_socket.descriptor.out + "} WAITING")
end end
end end
@@ -124,15 +135,17 @@ feature -- Execution
process_request (a_socket) process_request (a_socket)
end end
debug ("dbglog") debug ("dbglog")
dbglog (generator + ".LEAVE execute {" + a_socket.descriptor.out + "}") dbglog (generator + ".execute {" + a_socket.descriptor.out + "} LEAVE")
end end
end end
-- release (a_socket) -- release (a_socket)
end end
release (a_socket: HTTPD_STREAM_SOCKET) release (a_socket: detachable HTTPD_STREAM_SOCKET)
do do
if a_socket /= Void then
a_socket.cleanup a_socket.cleanup
end
reset reset
end end

View File

@@ -154,11 +154,13 @@ feature -- Listening
create l_connection_handler.make (Current) create l_connection_handler.make (Current)
from from
l_listening_socket.listen (configuration.max_tcp_clients) l_listening_socket.listen (configuration.max_tcp_clients)
if is_verbose and then configuration.is_secure then 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 + "/") log ("%NHTTP Connection Server ready on port " + l_http_port.out +" : https://localhost:" + l_http_port.out + "/")
elseif is_verbose then else
log ("%NHTTP Connection Server ready on port " + l_http_port.out +" : http://localhost:" + l_http_port.out + "/") log ("%NHTTP Connection Server ready on port " + l_http_port.out +" : http://localhost:" + l_http_port.out + "/")
end end
end
on_launched (l_http_port) on_launched (l_http_port)
until until
is_shutdown_requested is_shutdown_requested

View File

@@ -46,6 +46,14 @@ feature {NONE} -- Initialization
do do
Result := s.socket.descriptor Result := s.socket.descriptor
end 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 feature -- Access