Support for concurrencies: none, thread and SCOOP

This commit is contained in:
2015-03-20 15:48:54 +01:00
parent 3da80fce0d
commit ddf73077b3
8 changed files with 93 additions and 124 deletions

View File

@@ -80,4 +80,10 @@
<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>
<target name="dev_mt" extends="dev">
<setting name="concurrency" value="thread"/>
</target>
<target name="dev_none" extends="dev">
<setting name="concurrency" value="none"/>
</target>
</system> </system>

View File

@@ -31,42 +31,25 @@ feature -- Access
feature -- Execution feature -- Execution
process_incoming_connection (a_socket: HTTPD_STREAM_SOCKET) accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET)
-- Process incoming connection local
-- note that the precondition matters for scoop synchronization. cl: HTTPD_STREAM_SOCKET
do do
is_shutdown_requested := is_shutdown_requested or shutdown_requested (server) is_shutdown_requested := is_shutdown_requested or shutdown_requested (server)
if is_shutdown_requested then if is_shutdown_requested then
a_socket.cleanup -- Cancel
elseif attached server.factory.new_handler as h then elseif attached factory.new_handler as h then
process_connection_handler (h, a_socket) cl := h.client_socket
a_listening_socket.accept_to (cl)
if h.is_connected then
h.execute
end
else else
check is_not_full: False end check is_not_full: False end
a_socket.cleanup
end end
update_is_shutdown_requested update_is_shutdown_requested
end 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 update_is_shutdown_requested
do do
is_shutdown_requested := shutdown_requested (server) is_shutdown_requested := shutdown_requested (server)
@@ -89,7 +72,7 @@ feature {HTTPD_SERVER_I} -- Status report
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

@@ -10,15 +10,10 @@ deferred class
inherit inherit
HTTPD_REQUEST_HANDLER_I HTTPD_REQUEST_HANDLER_I
feature -- Change
set_client_socket (a_socket: HTTPD_STREAM_SOCKET)
do
client_socket := a_socket
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

@@ -96,7 +96,7 @@ feature {HTTPD_SERVER_I} -- Execution
require require
hdl.is_connected hdl.is_connected
do do
hdl.separate_execute hdl.safe_execute
end end
feature {HTTPD_SERVER_I} -- Status report feature {HTTPD_SERVER_I} -- Status report

View File

@@ -20,56 +20,21 @@ inherit
release as release_pool_item release as release_pool_item
end 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 feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation
separate_release release
do
release (client_socket)
end
release (a_socket: detachable HTTPD_STREAM_SOCKET)
local local
d: STRING d: STRING
do do
if a_socket /= Void then if attached internal_client_socket as l_socket then
d := a_socket.descriptor.out d := l_socket.descriptor.out
else else
d := "N/A" d := "N/A"
end end
debug ("dbglog") debug ("dbglog")
dbglog (generator + ".release: ENTER {" + d + "}") dbglog (generator + ".release: ENTER {" + d + "}")
end end
Precursor {HTTPD_REQUEST_HANDLER_I} (a_socket) Precursor {HTTPD_REQUEST_HANDLER_I}
release_pool_item release_pool_item
debug ("dbglog") debug ("dbglog")
dbglog (generator + ".release: LEAVE {" + d + "}") dbglog (generator + ".release: LEAVE {" + d + "}")

View File

@@ -50,36 +50,27 @@ feature {HTTPD_SERVER_I} -- Execution
p.terminate p.terminate
end 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 do
if is_shutdown_requested then debug ("dbglog")
a_socket.cleanup dbglog (generator + ".ENTER accept_connection {"+ a_listening_socket.descriptor.out +"}")
else end
process_connection_handler (factory.new_handler, a_socket)
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
end
process_connection_handler (hdl: separate HTTPD_REQUEST_HANDLER; a_socket: HTTPD_STREAM_SOCKET)
require
not hdl.has_error
do
debug ("dbglog") debug ("dbglog")
dbglog (generator + ".ENTER process_connection_handler {"+ a_socket.descriptor.out +"}") dbglog (generator + ".LEAVE accept_incoming_connection {"+ a_listening_socket.descriptor.out +"}")
end 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 end
feature {HTTPD_SERVER_I} -- Status report feature {HTTPD_SERVER_I} -- Status report
@@ -99,7 +90,7 @@ invariant
pool_attached: pool /= Void pool_attached: pool /= Void
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

@@ -17,23 +17,27 @@ inherit
feature {HTTPD_CONNECTION_HANDLER_I} -- Basic operation feature {HTTPD_CONNECTION_HANDLER_I} -- Basic operation
release (a_socket: HTTPD_STREAM_SOCKET) release
local local
d: STRING d: STRING
do do
-- FIXME: for log purpose -- 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") debug ("dbglog")
dbglog (generator + ".release: ENTER {" + d + "}") dbglog (generator + ".release: ENTER {" + d + "}")
end end
Precursor {HTTPD_REQUEST_HANDLER_I} (a_socket) Precursor {HTTPD_REQUEST_HANDLER_I}
debug ("dbglog") debug ("dbglog")
dbglog (generator + ".release: LEAVE {" + d + "}") dbglog (generator + ".release: LEAVE {" + d + "}")
end end
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

@@ -34,7 +34,14 @@ 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
feature -- Status report
is_connected: BOOLEAN
-- Is handler connected to incoming request via `client_socket'?
do
Result := client_socket.descriptor_available
end end
feature -- Access feature -- Access
@@ -78,8 +85,6 @@ 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'
@@ -92,36 +97,60 @@ feature -- Change
feature -- Execution 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 require
socket_attached: a_socket /= Void is_connected: is_connected
socket_valid: a_socket.is_open_read and then a_socket.is_open_write
a_http_socket: not a_socket.is_closed
local local
l_remote_info: detachable like remote_info l_remote_info: detachable like remote_info
l_continue: BOOLEAN l_continue: BOOLEAN
l_socket: like client_socket
do 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") debug ("dbglog")
dbglog (generator + ".execute {socket is Closed!}") dbglog (generator + ".execute {socket is Closed!}")
end end
else else
debug ("dbglog") debug ("dbglog")
dbglog (generator + ".execute {" + a_socket.descriptor.out + "} ENTER") dbglog (generator + ".execute socket=" + l_socket.descriptor.out + " ENTER")
end end
from until l_continue loop from until l_continue loop
if a_socket.ready_for_reading then if l_socket.ready_for_reading then
l_continue := True l_continue := True
create l_remote_info 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.addr := l_addr.host_address.host_address
l_remote_info.hostname := l_addr.host_address.host_name l_remote_info.hostname := l_addr.host_address.host_name
l_remote_info.port := l_addr.port l_remote_info.port := l_addr.port
remote_info := l_remote_info remote_info := l_remote_info
end end
analyze_request_message (a_socket) analyze_request_message (l_socket)
else else
log (generator + ".execute {" + a_socket.descriptor.out + "} WAITING") log (generator + ".execute socket=" + l_socket.descriptor.out + "} WAITING")
end end
end end
@@ -132,20 +161,16 @@ feature -- Execution
log ("ERROR: invalid HTTP incoming request") log ("ERROR: invalid HTTP incoming request")
end end
else else
process_request (a_socket) process_request (l_socket)
end end
debug ("dbglog") debug ("dbglog")
dbglog (generator + ".execute {" + a_socket.descriptor.out + "} LEAVE") dbglog (generator + ".execute {" + l_socket.descriptor.out + "} LEAVE")
end end
end end
-- release (a_socket)
end end
release (a_socket: detachable HTTPD_STREAM_SOCKET) release
do do
if a_socket /= Void then
a_socket.cleanup
end
reset reset
end end