From 10014b400da456869449c2affe683ddd2e252d0c Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 3 Jan 2012 11:42:58 +0100 Subject: [inets/httpc] Fix the selection of session for keep-alive mode When selecting a session, the "state" of the session (specifically if the server has responded) was not taken into account. Attempting to fix this, a "state" field (actually available) has been added to the session record. OTP-9847 --- lib/inets/src/http_client/httpc_handler.erl | 24 ++++++++++++++----- lib/inets/src/http_client/httpc_internal.hrl | 36 +++++++++++++++++++++------- lib/inets/src/http_client/httpc_manager.erl | 29 ++++++++++++++++++++-- lib/inets/src/inets_app/inets.appup.src | 30 +++++++++++++++++++---- 4 files changed, 98 insertions(+), 21 deletions(-) (limited to 'lib/inets/src') diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl index 587e24cc8d..8874304bd6 100644 --- a/lib/inets/src/http_client/httpc_handler.erl +++ b/lib/inets/src/http_client/httpc_handler.erl @@ -1403,7 +1403,9 @@ try_to_enable_pipeline_or_keep_alive( end. answer_request(#request{id = RequestId, from = From} = Request, Msg, - #state{timers = Timers, profile_name = ProfileName} = State) -> + #state{session = Session, + timers = Timers, + profile_name = ProfileName} = State) -> ?hcrt("answer request", [{request, Request}, {msg, Msg}]), httpc_response:send(From, Msg), RequestTimers = Timers#timers.request_timers, @@ -1412,12 +1414,22 @@ answer_request(#request{id = RequestId, from = From} = Request, Msg, Timer = {RequestId, TimerRef}, cancel_timer(TimerRef, {timeout, Request#request.id}), httpc_manager:request_done(RequestId, ProfileName), - + NewSession = maybe_make_session_available(ProfileName, Session), + Timers2 = Timers#timers{request_timers = lists:delete(Timer, + RequestTimers)}, State#state{request = Request#request{from = answer_sent}, - timers = - Timers#timers{request_timers = - lists:delete(Timer, RequestTimers)}}. - + session = NewSession, + timers = Timers2}. + +maybe_make_session_available(ProfileName, + #session{id = SessionId, + available = false} = Session) -> + httpc_manager:update_session(ProfileName, SessionId, + #session.available, true), + Session#session{available = true}; +maybe_make_session_available(_ProfileName, Session) -> + Session. + cancel_timers(#timers{request_timers = ReqTmrs, queue_timer = QTmr}) -> cancel_timer(QTmr, timeout_queue), CancelTimer = fun({_, Timer}) -> cancel_timer(Timer, timeout) end, diff --git a/lib/inets/src/http_client/httpc_internal.hrl b/lib/inets/src/http_client/httpc_internal.hrl index 1d8a5b6a92..3261061d61 100644 --- a/lib/inets/src/http_client/httpc_internal.hrl +++ b/lib/inets/src/http_client/httpc_internal.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2010. All Rights Reserved. +%% Copyright Ericsson AB 2005-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -112,17 +112,37 @@ } ). + -record(session, { - id, % {{Host, Port}, HandlerPid} - client_close, % true | false - scheme, % http (HTTP/TCP) | https (HTTP/SSL/TCP) - socket, % Open socket, used by connection - socket_type, % socket-type, used by connection - queue_length = 1, % Current length of pipeline or keep-alive queue - type % pipeline | keep_alive (wait for response before sending new request) + %% {{Host, Port}, HandlerPid} + id, + + %% true | false + client_close, + + %% http (HTTP/TCP) | https (HTTP/SSL/TCP) + scheme, + + %% Open socket, used by connection + socket, + + %% socket-type, used by connection + socket_type, + + %% Current length of pipeline or keep-alive queue + queue_length = 1, + + %% pipeline | keep_alive (wait for response before sending new request) + type, + + %% true | false + %% This will be true, when a response has been received for + %% the first request. See type above. + available = false }). + -record(http_cookie, { domain, diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl index 9015bf1ce2..d699f1e7d8 100644 --- a/lib/inets/src/http_client/httpc_manager.erl +++ b/lib/inets/src/http_client/httpc_manager.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2011. All Rights Reserved. +%% Copyright Ericsson AB 2002-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -34,6 +34,7 @@ retry_request/2, redirect_request/2, insert_session/2, + update_session/4, delete_session/2, set_options/2, store_cookies/3, @@ -192,6 +193,29 @@ insert_session(Session, ProfileName) -> ets:insert(SessionDbName, Session). +%%-------------------------------------------------------------------- +%% Function: update_session(ProfileName, SessionId, Pos, Value) -> _ +%% Session - #session{} +%% ProfileName - atom() +%% +%% Description: Update, only one field (Pos) of the session record +%% identified by the SessionId, the session information +%% of the httpc manager table _session_db. +%% Intended to be called by the httpc request handler process. +%%-------------------------------------------------------------------- + +update_session(ProfileName, SessionId, Pos, Value) -> + SessionDbName = session_db_name(ProfileName), + ?hcrt("insert session", + [{id, SessionId}, + {pos, Pos}, + {value, Value}, + {profile, ProfileName}]), + ets:update_element(SessionDbName, SessionId, {Pos, Value}). + + + + %%-------------------------------------------------------------------- %% Function: delete_session(SessionId, ProfileName) -> _ %% SessionId - {{Host, Port}, HandlerPid} @@ -679,6 +703,7 @@ select_session(Method, HostPort, Scheme, SessionType, scheme = Scheme, queue_length = '$2', type = SessionType, + available = true, _ = '_'}, %% {'_', {HostPort, '$1'}, false, Scheme, '_', '$2', SessionTyp}, Candidates = ets:match(SessionDb, Pattern), @@ -716,7 +741,7 @@ pipeline_or_keep_alive(Request, HandlerPid, State) -> ets:insert(State#state.handler_db, {Request#request.id, HandlerPid, Request#request.from}); - _ -> %timeout pipelining failed + _ -> % timeout pipelining failed start_handler(Request, State) end. diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src index fb605351b4..9108faf197 100644 --- a/lib/inets/src/inets_app/inets.appup.src +++ b/lib/inets/src/inets_app/inets.appup.src @@ -1,7 +1,7 @@ %% This is an -*- erlang -*- file. %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2011. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -18,6 +18,12 @@ {"%VSN%", [ + {"5.7.2", + [ + {update, httpc_handler, soft, soft_purge, soft_purge, []}, + {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]} + ] + }, {"5.7.1", [ {load_module, http_uri, soft_purge, soft_purge, []}, @@ -26,7 +32,9 @@ {load_module, httpd_file, soft_purge, soft_purge, []}, {load_module, httpd_request, soft_purge, soft_purge, []}, {load_module, mod_responsecontrol, soft_purge, soft_purge, []}, - {load_module, httpd_response, soft_purge, soft_purge, [mod_responsecontrol]} + {load_module, httpd_response, soft_purge, soft_purge, [mod_responsecontrol]}, + {update, httpc_handler, soft, soft_purge, soft_purge, []}, + {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]} ] }, {"5.7", @@ -38,7 +46,9 @@ {load_module, httpc_cookie, soft_purge, soft_purge, [http_util]}, {load_module, http_util, soft_purge, soft_purge, []}, {load_module, mod_responsecontrol, soft_purge, soft_purge, []}, - {load_module, httpd_response, soft_purge, soft_purge, [mod_responsecontrol]} + {load_module, httpd_response, soft_purge, soft_purge, [mod_responsecontrol]}, + {update, httpc_handler, soft, soft_purge, soft_purge, []}, + {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]} ] }, {"5.6", @@ -80,6 +90,12 @@ } ], [ + {"5.7.2", + [ + {update, httpc_handler, soft, soft_purge, soft_purge, []}, + {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]} + ] + }, {"5.7.1", [ {load_module, http_uri, soft_purge, soft_purge, []}, @@ -88,7 +104,9 @@ {load_module, httpd_file, soft_purge, soft_purge, []}, {load_module, httpd_request, soft_purge, soft_purge, []}, {load_module, mod_responsecontrol, soft_purge, soft_purge, []}, - {load_module, httpd_response, soft_purge, soft_purge, [mod_responsecontrol]} + {load_module, httpd_response, soft_purge, soft_purge, [mod_responsecontrol]}, + {update, httpc_handler, soft, soft_purge, soft_purge, []}, + {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]} ] }, {"5.7", @@ -100,7 +118,9 @@ {load_module, httpc_cookie, soft_purge, soft_purge, [http_util]}, {load_module, http_util, soft_purge, soft_purge, []}, {load_module, mod_responsecontrol, soft_purge, soft_purge, []}, - {load_module, httpd_response, soft_purge, soft_purge, [mod_responsecontrol]} + {load_module, httpd_response, soft_purge, soft_purge, [mod_responsecontrol]}, + {update, httpc_handler, soft, soft_purge, soft_purge, []}, + {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]} ] }, {"5.6", -- cgit v1.2.3