Support for concurrencies: none, thread and SCOOP
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 + "}")
|
||||||
|
|||||||
@@ -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
|
||||||
|
debug ("dbglog")
|
||||||
|
dbglog (generator + ".ENTER accept_connection {"+ a_listening_socket.descriptor.out +"}")
|
||||||
|
end
|
||||||
|
|
||||||
if is_shutdown_requested then
|
if is_shutdown_requested then
|
||||||
a_socket.cleanup
|
-- cancel
|
||||||
else
|
elseif attached factory.new_handler as h then
|
||||||
process_connection_handler (factory.new_handler, a_socket)
|
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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user