aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMicael Karlberg <[email protected]>2012-01-05 12:09:37 +0100
committerMicael Karlberg <[email protected]>2012-01-05 12:09:37 +0100
commit5edcd0d6372d73124e4160a2bbc5b81853642fc5 (patch)
tree4a3eb2e9f1d5c4599e3afe2d77e18a0f09651328
parent345ffc04c94d583ec829bacf2807fe1562b7f72c (diff)
downloadotp-5edcd0d6372d73124e4160a2bbc5b81853642fc5.tar.gz
otp-5edcd0d6372d73124e4160a2bbc5b81853642fc5.tar.bz2
otp-5edcd0d6372d73124e4160a2bbc5b81853642fc5.zip
[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
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl103
-rw-r--r--lib/inets/src/http_client/httpc_manager.erl65
-rw-r--r--lib/inets/src/inets_app/inets.appup.src114
3 files changed, 162 insertions, 120 deletions
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index a88945898a..4ae2275f70 100644
--- a/lib/inets/src/http_client/httpc_handler.erl
+++ b/lib/inets/src/http_client/httpc_handler.erl
@@ -295,7 +295,7 @@ handle_call(#request{address = Addr} = Request, _,
%% Queue + current
queue:len(NewPipeline) + 1,
client_close = ClientClose},
- httpc_manager:insert_session(NewSession, ProfileName),
+ insert_session(NewSession, ProfileName),
?hcrd("session updated", []),
{reply, ok, State#state{pipeline = NewPipeline,
session = NewSession,
@@ -363,7 +363,7 @@ handle_call(#request{address = Addr} = Request, _,
%% Queue + current
queue:len(NewKeepAlive) + 1,
client_close = ClientClose},
- httpc_manager:insert_session(NewSession, ProfileName),
+ insert_session(NewSession, ProfileName),
?hcrd("session updated", []),
{reply, ok, State#state{keep_alive = NewKeepAlive,
session = NewSession,
@@ -377,7 +377,7 @@ handle_call(#request{address = Addr} = Request, _,
NewSession =
Session#session{queue_length = 1,
client_close = ClientClose},
- httpc_manager:insert_session(NewSession, ProfileName),
+ insert_session(NewSession, ProfileName),
Relaxed =
(Request#request.settings)#http_options.relaxed,
MFA = {httpc_response, parse,
@@ -766,23 +766,52 @@ deliver_answer(Request) ->
%% Func: code_change(_OldVsn, State, Extra) -> {ok, NewState}
%% Purpose: Convert process state when code is changed
%%--------------------------------------------------------------------
-%% code_change(_, #state{request = Request, pipeline = Queue} = State,
-%% [{from, '5.0.1'}, {to, '5.0.2'}]) ->
-%% Settings = new_http_options(Request#request.settings),
-%% NewRequest = Request#request{settings = Settings},
-%% NewQueue = new_queue(Queue, fun new_http_options/1),
-%% {ok, State#state{request = NewRequest, pipeline = NewQueue}};
-
-%% code_change(_, #state{request = Request, pipeline = Queue} = State,
-%% [{from, '5.0.2'}, {to, '5.0.1'}]) ->
-%% Settings = old_http_options(Request#request.settings),
-%% NewRequest = Request#request{settings = Settings},
-%% NewQueue = new_queue(Queue, fun old_http_options/1),
-%% {ok, State#state{request = NewRequest, pipeline = NewQueue}};
+
+code_change(_,
+ #state{session = OldSession,
+ profile_name = ProfileName} = State,
+ upgrade_from_pre_5_7_3) ->
+ case OldSession of
+ {session,
+ Id, ClientClose, Scheme, Socket, SocketType, QueueLen, Type} ->
+ NewSession = #session{id = Id,
+ client_close = ClientClose,
+ scheme = Scheme,
+ socket = Socket,
+ socket_type = SocketType,
+ queue_length = QueueLen,
+ type = Type},
+ insert_session(NewSession, ProfileName),
+ {ok, State#state{session = NewSession}};
+ _ ->
+ {ok, State}
+ end;
+
+code_change(_,
+ #state{session = OldSession,
+ profile_name = ProfileName} = State,
+ downgrade_to_pre_5_7_3) ->
+ case OldSession of
+ #session{id = Id,
+ client_close = ClientClose,
+ scheme = Scheme,
+ socket = Socket,
+ socket_type = SocketType,
+ queue_length = QueueLen,
+ type = Type} ->
+ NewSession = {session,
+ Id, ClientClose, Scheme, Socket, SocketType,
+ QueueLen, Type},
+ insert_session(NewSession, ProfileName),
+ {ok, State#state{session = NewSession}};
+ _ ->
+ {ok, State}
+ end;
code_change(_, State, _) ->
{ok, State}.
+
%% new_http_options({http_options, TimeOut, AutoRedirect, SslOpts,
%% Auth, Relaxed}) ->
%% {http_options, "HTTP/1.1", TimeOut, AutoRedirect, SslOpts,
@@ -1192,9 +1221,7 @@ handle_pipeline(#state{status = pipeline,
%% If a pipeline that has been idle for some time is not
%% closed by the server, the client may want to close it.
NewState = activate_queue_timeout(TimeOut, State),
- httpc_manager:update_session(ProfileName,
- Session#session.id,
- #session.queue_length, 0),
+ update_session(ProfileName, Session, #session.queue_length, 0),
%% Note mfa will be initilized when a new request
%% arrives.
{noreply,
@@ -1220,7 +1247,7 @@ handle_pipeline(#state{status = pipeline,
Session#session{queue_length =
%% Queue + current
queue:len(Pipeline) + 1},
- httpc_manager:insert_session(NewSession, ProfileName),
+ insert_session(NewSession, ProfileName),
Relaxed =
(NextRequest#request.settings)#http_options.relaxed,
MFA = {httpc_response,
@@ -1268,9 +1295,7 @@ handle_keep_alive_queue(
%% If a keep_alive session has been idle for some time is not
%% closed by the server, the client may want to close it.
NewState = activate_queue_timeout(TimeOut, State),
- httpc_manager:update_session(ProfileName,
- Session#session.id,
- #session.queue_length, 0),
+ update_session(ProfileName, Session, #session.queue_length, 0),
%% Note mfa will be initilized when a new request
%% arrives.
{noreply,
@@ -1392,10 +1417,10 @@ try_to_enable_pipeline_or_keep_alive(
case (is_pipeline_enabled_client(Session) andalso
httpc_request:is_idempotent(Method)) of
true ->
- httpc_manager:insert_session(Session, ProfileName),
+ insert_session(Session, ProfileName),
State#state{status = pipeline};
false ->
- httpc_manager:insert_session(Session, ProfileName),
+ insert_session(Session, ProfileName),
%% Make sure type is keep_alive in session
%% as it in this case might be pipeline
NewSession = Session#session{type = keep_alive},
@@ -1426,10 +1451,8 @@ answer_request(#request{id = RequestId, from = From} = Request, Msg,
timers = Timers2}.
maybe_make_session_available(ProfileName,
- #session{id = SessionId,
- available = false} = Session) ->
- httpc_manager:update_session(ProfileName, SessionId,
- #session.available, true),
+ #session{available = false} = Session) ->
+ update_session(ProfileName, Session, #session.available, true),
Session#session{available = true};
maybe_make_session_available(_ProfileName, Session) ->
Session.
@@ -1672,6 +1695,28 @@ send_raw(SocketType, Socket, ProcessBody, Acc) ->
end.
+%% ---------------------------------------------------------------------
+%% Session wrappers
+%% ---------------------------------------------------------------------
+
+insert_session(Session, ProfileName) ->
+ httpc_manager:insert_session(Session, ProfileName).
+
+
+update_session(ProfileName, #session{id = SessionId} = Session, Pos, Value) ->
+ try
+ begin
+ httpc_manager:update_session(ProfileName, SessionId, Pos, Value)
+ end
+ catch
+ error:undef -> % This could happen during code upgrade
+ Session2 = erlang:setelement(Pos, Session, Value),
+ insert_session(Session2, ProfileName)
+ end.
+
+
+%% ---------------------------------------------------------------------
+
call(Msg, Pid) ->
Timeout = infinity,
call(Msg, Pid, Timeout).
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
diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src
index 9108faf197..0e5024abe2 100644
--- a/lib/inets/src/inets_app/inets.appup.src
+++ b/lib/inets/src/inets_app/inets.appup.src
@@ -20,8 +20,10 @@
[
{"5.7.2",
[
- {update, httpc_handler, soft, soft_purge, soft_purge, []},
- {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]}
+ {update, httpc_handler, {advanced, upgrade_from_pre_4_7_3},
+ soft_purge, soft_purge, []},
+ {update, httpc_manager, {advanced, upgrade_from_pre_4_7_3},
+ soft_purge, soft_purge, [httpc_handler]}
]
},
{"5.7.1",
@@ -33,8 +35,10 @@
{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]},
- {update, httpc_handler, soft, soft_purge, soft_purge, []},
- {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]}
+ {update, httpc_handler, {advanced, upgrade_from_pre_4_7_3},
+ soft_purge, soft_purge, []},
+ {update, httpc_manager, {advanced, upgrade_from_pre_4_7_3},
+ soft_purge, soft_purge, [httpc_handler]}
]
},
{"5.7",
@@ -47,53 +51,20 @@
{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]},
- {update, httpc_handler, soft, soft_purge, soft_purge, []},
- {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]}
+ {update, httpc_handler, {advanced, upgrade_from_pre_4_7_3},
+ soft_purge, soft_purge, []},
+ {update, httpc_manager, {advanced, upgrade_from_pre_4_7_3},
+ soft_purge, soft_purge, [httpc_handler]}
]
- },
- {"5.6",
- [
- {load_module, http_uri, soft_purge, soft_purge, []},
- {load_module, httpd_util, soft_purge, soft_purge, [http_util]},
- {load_module, httpd_file, soft_purge, soft_purge, []},
- {load_module, httpd_request, soft_purge, soft_purge, []},
- {load_module, httpc, soft_purge, soft_purge, [httpc_manager]},
- {load_module, http_transport, soft_purge, soft_purge, [http_transport]},
- {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]},
- {update, httpc_handler, soft, soft_purge, soft_purge, []},
- {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]},
- {update, ftp, soft, soft_purge, soft_purge, []}
- ]
- },
- {"5.5.2",
- [
- {restart_application, inets}
- ]
- },
- {"5.5.1",
- [
- {restart_application, inets}
- ]
- },
- {"5.5",
- [
- {restart_application, inets}
- ]
- },
- {"5.4",
- [
- {restart_application, inets}
- ]
- }
+ }
],
[
{"5.7.2",
[
- {update, httpc_handler, soft, soft_purge, soft_purge, []},
- {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]}
+ {update, httpc_handler, {advanced, downgrade_to_pre_4_7_3},
+ soft_purge, soft_purge, []},
+ {update, httpc_manager, {advanced, downgrade_to_pre_4_7_3},
+ soft_purge, soft_purge, [httpc_handler]}
]
},
{"5.7.1",
@@ -105,8 +76,10 @@
{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]},
- {update, httpc_handler, soft, soft_purge, soft_purge, []},
- {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]}
+ {update, httpc_handler, {advanced, downgrade_to_pre_4_7_3},
+ soft_purge, soft_purge, []},
+ {update, httpc_manager, {advanced, downgrade_to_pre_4_7_3},
+ soft_purge, soft_purge, [httpc_handler]}
]
},
{"5.7",
@@ -119,46 +92,11 @@
{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]},
- {update, httpc_handler, soft, soft_purge, soft_purge, []},
- {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]}
- ]
- },
- {"5.6",
- [
- {load_module, http_uri, soft_purge, soft_purge, []},
- {load_module, httpd_util, soft_purge, soft_purge, [http_util]},
- {load_module, httpd_file, soft_purge, soft_purge, []},
- {load_module, httpd_request, soft_purge, soft_purge, []},
- {load_module, httpc, soft_purge, soft_purge, [httpc_manager]},
- {load_module, http_transport, soft_purge, soft_purge, [http_transport]},
- {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]},
- {update, httpc_handler, soft, soft_purge, soft_purge, []},
- {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]},
- {update, ftp, soft, soft_purge, soft_purge, []}
- ]
- },
- {"5.5.2",
- [
- {restart_application, inets}
- ]
- },
- {"5.5.1",
- [
- {restart_application, inets}
- ]
- },
- {"5.5",
- [
- {restart_application, inets}
- ]
- },
- {"5.4",
- [
- {restart_application, inets}
+ {update, httpc_handler, {advanced, downgrade_to_pre_4_7_3},
+ soft_purge, soft_purge, []},
+ {update, httpc_manager, {advanced, downgrade_to_pre_4_7_3},
+ soft_purge, soft_purge, [httpc_handler]}
]
- }
+ }
]
}.