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_manager.erl | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'lib/inets/src/http_client/httpc_manager.erl') 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. -- cgit v1.2.3 From 345ffc04c94d583ec829bacf2807fe1562b7f72c Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 4 Jan 2012 17:59:23 +0100 Subject: [inets/httpc] Add test case Add a test case verifying the session selection. Add some more use of the update_session function. Improved verbosity printouts. OTP-9847 --- lib/inets/src/http_client/httpc_manager.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/inets/src/http_client/httpc_manager.erl') diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl index d699f1e7d8..4262abc5d0 100644 --- a/lib/inets/src/http_client/httpc_manager.erl +++ b/lib/inets/src/http_client/httpc_manager.erl @@ -206,7 +206,7 @@ insert_session(Session, ProfileName) -> update_session(ProfileName, SessionId, Pos, Value) -> SessionDbName = session_db_name(ProfileName), - ?hcrt("insert session", + ?hcrt("update session", [{id, SessionId}, {pos, Pos}, {value, Value}, -- cgit v1.2.3 From 5edcd0d6372d73124e4160a2bbc5b81853642fc5 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 5 Jan 2012 12:09:37 +0100 Subject: [inets/httpc] Add proper code change code Added proper code to handle code upgrade/downgrade. The manager and handler(s) are interdependant which makes it a bit tricky. OTP-9847 --- lib/inets/src/http_client/httpc_manager.erl | 65 +++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 3 deletions(-) (limited to 'lib/inets/src/http_client/httpc_manager.erl') diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl index 4262abc5d0..3d846c2bff 100644 --- a/lib/inets/src/http_client/httpc_manager.erl +++ b/lib/inets/src/http_client/httpc_manager.erl @@ -214,8 +214,6 @@ update_session(ProfileName, SessionId, Pos, Value) -> ets:update_element(SessionDbName, SessionId, {Pos, Value}). - - %%-------------------------------------------------------------------- %% Function: delete_session(SessionId, ProfileName) -> _ %% SessionId - {{Host, Port}, HandlerPid} @@ -572,9 +570,70 @@ terminate(_, State) -> %% Func: code_change(_OldVsn, State, Extra) -> {ok, NewState} %% Purpose: Convert process state when code is changed %%-------------------------------------------------------------------- -code_change(_OldVsn, State, _Extra) -> +code_change(_, + #state{session_db = SessionDB} = State, + upgrade_from_pre_5_7_3) -> + Upgrade = + fun({session, + Id, ClientClose, Scheme, Socket, SocketType, QueueLen, Type}) -> + {ok, #session{id = Id, + client_close = ClientClose, + scheme = Scheme, + socket = Socket, + socket_type = SocketType, + queue_length = QueueLen, + type = Type}}; + (_) -> % Already upgraded (by handler) + ignore + end, + (catch update_session_table(SessionDB, Upgrade)), + {ok, State}; + +code_change(_, + #state{session_db = SessionDB} = State, + downgrade_to_pre_5_7_3) -> + Downgrade = + fun(#session{id = Id, + client_close = ClientClose, + scheme = Scheme, + socket = Socket, + socket_type = SocketType, + queue_length = QueueLen, + type = Type}) -> + {ok, {session, + Id, ClientClose, Scheme, Socket, SocketType, + QueueLen, Type}}; + (_) -> % Already downgraded (by handler) + ignore + end, + (catch update_session_table(SessionDB, Downgrade)), + {ok, State}; + +code_change(_, State, _) -> {ok, State}. +%% This function is to catch everything that calls through the cracks... +update_session_table(SessionDB, Transform) -> + ets:safe_fixtable(SessionDB, true), + update_session_table(SessionDB, ets:first(SessionDB), Transform), + ets:safe_fixtable(SessionDB, false). + +update_session_table(_SessionDB, '$end_of_table', _Transform) -> + ok; +update_session_table(SessionDB, Key, Transform) -> + case ets:lookup(SessionDB, Key) of + [OldSession] -> + case Transform(OldSession) of + {ok, NewSession} -> + ets:insert(SessionDB, NewSession); + ignore -> + ok + end; + _ -> + ok + end, + update_session_table(SessionDB, ets:next(SessionDB, Key), Transform). + %%-------------------------------------------------------------------- %% Internal functions -- cgit v1.2.3