Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fix option connect_timeout + Add options connection_timeout and max_c…

…onnections
  • Loading branch information...
commit ba00638d9c772957ba59310b737603b33e4064e3 1 parent 4af873c
@lpgauth lpgauth authored
View
6 src/lhttpc.app.src
@@ -1,7 +1,7 @@
%%% ----------------------------------------------------------------------------
%%% Copyright (c) 2009, Erlang Training and Consulting Ltd.
%%% All rights reserved.
-%%%
+%%%
%%% Redistribution and use in source and binary forms, with or without
%%% modification, are permitted provided that the following conditions are met:
%%% * Redistributions of source code must retain the above copyright
@@ -12,7 +12,7 @@
%%% * Neither the name of Erlang Training and Consulting Ltd. nor the
%%% names of its contributors may be used to endorse or promote products
%%% derived from this software without specific prior written permission.
-%%%
+%%%
%%% THIS SOFTWARE IS PROVIDED BY Erlang Training and Consulting Ltd. ''AS IS''
%%% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
%%% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -34,6 +34,6 @@
{registered, [lhttpc_manager]},
{applications, [kernel, stdlib, ssl, crypto]},
{mod, {lhttpc, nil}},
- {env, [{connection_timeout, 300000}]}
+ {env, []}
]}.
View
8 src/lhttpc.erl
@@ -539,6 +539,14 @@ verify_options([{connect_timeout, infinity} | Options], Errors) ->
verify_options([{connect_timeout, MS} | Options], Errors)
when is_integer(MS), MS >= 0 ->
verify_options(Options, Errors);
+verify_options([{connection_timeout, infinity} | Options], Errors) ->
+ verify_options(Options, Errors);
+verify_options([{connection_timeout, MS} | Options], Errors)
+ when is_integer(MS), MS >= 0 ->
+ verify_options(Options, Errors);
+verify_options([{max_connections, MS} | Options], Errors)
+ when is_integer(MS), MS >= 0 ->
+ verify_options(Options, Errors);
verify_options([{partial_upload, WindowSize} | Options], Errors)
when is_integer(WindowSize), WindowSize >= 0 ->
verify_options(Options, Errors);
View
7 src/lhttpc_client.erl
@@ -105,9 +105,11 @@ execute(From, Host, Port, Ssl, Path, Method, Hdrs, Body, Options) ->
PartialDownloadOptions = proplists:get_value(partial_download, Options, []),
ConnectOptions = proplists:get_value(connect_options, Options, []),
NormalizedMethod = lhttpc_lib:normalize_method(Method),
+ MaxConnections = proplists:get_value(max_connections, Options, 10),
+ ConnectionTimeout = proplists:get_value(connection_timeout, Options, infinity),
{ChunkedUpload, Request} = lhttpc_lib:format_request(Path, NormalizedMethod,
Hdrs, Host, Port, Body, PartialUpload),
- LbRequest = {lb, Host, Port, Ssl},
+ LbRequest = {lb, Host, Port, Ssl, MaxConnections, ConnectionTimeout},
{ok, Lb} = gen_server:call(lhttpc_manager, LbRequest, infinity),
State = #client_state{
host = Host,
@@ -149,8 +151,9 @@ send_request(#client_state{attempts = 0}) ->
throw(connection_closed);
send_request(#client_state{socket = undefined} = State) ->
ConnectOptions = State#client_state.connect_options,
+ ConnectTimeout = State#client_state.connect_timeout,
Lb = State#client_state.load_balancer,
- SocketRequest = {socket, self(), ConnectOptions},
+ SocketRequest = {socket, self(), ConnectOptions, ConnectTimeout},
case gen_server:call(Lb, SocketRequest, infinity) of
{ok, Socket} ->
send_request(State#client_state{socket = Socket});
View
54 src/lhttpc_lb.erl
@@ -18,10 +18,10 @@
host :: string(),
port = 80 :: integer(),
ssl = false :: true | false,
+ max_connections = 10 :: non_neg_integer(),
+ connection_timeout = 300000 :: non_neg_integer(),
sockets = dict:new(),
- idle_sockets = queue:new(),
- timeout = 1000000 :: non_neg_integer(),
- max_sockets = 10 :: non_neg_integer()
+ available_sockets = queue:new()
}).
%% @spec (any()) -> {ok, pid()}
@@ -29,27 +29,27 @@
%% This is normally called by a supervisor.
%% @end
-spec start_link(any()) -> {ok, pid()}.
-start_link(Args) ->
- gen_server:start_link(?MODULE, Args, []).
+start_link([Dest, Opts]) ->
+ gen_server:start_link(?MODULE, [Dest, Opts], []).
%% @hidden
-spec init(any()) -> {ok, #httpc_man{}}.
-init({Host, Port, Ssl}) ->
+init([{Host, Port, Ssl}, {MaxConnections, ConnectionTimeout}]) ->
process_flag(priority, high),
- {ok, Timeout} = application:get_env(lhttpc, connection_timeout),
State = #httpc_man{
host = Host,
port = Port,
ssl = Ssl,
- timeout = Timeout
+ max_connections = MaxConnections,
+ connection_timeout = ConnectionTimeout
},
{ok, State}.
%% @hidden
-spec handle_call(any(), any(), #httpc_man{}) ->
{reply, any(), #httpc_man{}}.
-handle_call({socket, Pid, ConnectOptions}, _, State) ->
- {Reply, NewState} = find_socket(Pid, ConnectOptions, State),
+handle_call({socket, Pid, ConnectOptions, ConnectTimeout}, _, State) ->
+ {Reply, NewState} = find_socket(Pid, ConnectOptions, ConnectTimeout, State),
{reply, Reply, NewState};
handle_call(_, _, State) ->
{reply, {error, unknown_request}, State}.
@@ -65,8 +65,6 @@ handle_cast({remove, Socket}, State) ->
handle_cast({terminate}, State) ->
terminate(undefined, State),
{noreply, State};
-handle_cast({update_timeout, Milliseconds}, State) ->
- {noreply, State#httpc_man{timeout = Milliseconds}};
handle_cast(_, State) ->
{noreply, State}.
@@ -99,11 +97,11 @@ terminate(_, State) ->
code_change(_, State, _) ->
State.
-find_socket(Pid, ConnectOptions, State) ->
+find_socket(Pid, ConnectOptions, ConnectTimeout, State) ->
Host = State#httpc_man.host,
Port = State#httpc_man.port,
Ssl = State#httpc_man.ssl,
- Q1 = State#httpc_man.idle_sockets,
+ Q1 = State#httpc_man.available_sockets,
case queue:out(Q1) of
{{value, Socket}, Q2} ->
lhttpc_sock:setopts(Socket, [{active, false}], Ssl),
@@ -112,30 +110,29 @@ find_socket(Pid, ConnectOptions, State) ->
Timer = dict:fetch(Socket, State#httpc_man.sockets),
cancel_timer(Timer, Socket),
NewState = State#httpc_man{
- idle_sockets = Q2
+ available_sockets = Q2
},
{{ok, Socket}, NewState};
{error, badarg} ->
lhttpc_sock:setopts(Socket, [{active, once}], Ssl),
NewState = State#httpc_man{
- idle_sockets = queue:in(Socket, Q2)
+ available_sockets = queue:in(Socket, Q2)
},
{{error, no_pid}, NewState};
{error, _Reason} ->
NewState = State#httpc_man{
- idle_sockets = Q2
+ available_sockets = Q2
},
- find_socket(Pid, ConnectOptions, remove_socket(Socket, NewState))
+ find_socket(Pid, ConnectOptions, ConnectTimeout, remove_socket(Socket, NewState))
end;
{empty, _Q2} ->
- MaxSockets = State#httpc_man.max_sockets,
+ MaxSockets = State#httpc_man.max_connections,
case MaxSockets > dict:size(State#httpc_man.sockets) of
true ->
- Timeout = State#httpc_man.timeout,
SocketOptions = [binary, {packet, http}, {active, false} | ConnectOptions],
- case lhttpc_sock:connect(Host, Port, SocketOptions, 1000, Ssl) of
+ case lhttpc_sock:connect(Host, Port, SocketOptions, ConnectTimeout, Ssl) of
{ok, Socket} ->
- find_socket(Pid, ConnectOptions, store_socket(Socket, State));
+ find_socket(Pid, ConnectOptions, ConnectTimeout, store_socket(Socket, State));
{error, etimedout} ->
{{error, sys_timeout}, State};
{error, timeout} ->
@@ -161,11 +158,16 @@ remove_socket(Socket, State) ->
end.
store_socket(Socket, State) ->
- Timeout = State#httpc_man.timeout,
- Timer = erlang:send_after(Timeout, self(), {timeout, Socket}),
+ Timeout = State#httpc_man.connection_timeout,
+ Timer = case Timeout of
+ infinity ->
+ undefined;
+ _Other ->
+ erlang:send_after(Timeout, self(), {timeout, Socket})
+ end,
lhttpc_sock:setopts(Socket, [{active, once}], State#httpc_man.ssl),
State#httpc_man{
- idle_sockets = queue:in(Socket, State#httpc_man.idle_sockets),
+ available_sockets = queue:in(Socket, State#httpc_man.available_sockets),
sockets = dict:store(Socket, Timer, State#httpc_man.sockets)
}.
@@ -175,6 +177,8 @@ close_sockets(Sockets, Ssl) ->
erlang:cancel_timer(Timer)
end, dict:to_list(Sockets)).
+cancel_timer(undefined, _Socket) ->
+ ok;
cancel_timer(Timer, Socket) ->
case erlang:cancel_timer(Timer) of
false ->
View
8 src/lhttpc_manager.erl
@@ -70,8 +70,8 @@ init(_) ->
%% @hidden
-spec handle_call(any(), any(), #httpc_man{}) ->
{reply, any(), #httpc_man{}}.
-handle_call({lb, Host, Port, Ssl}, _, State) ->
- {Reply, NewState} = find_lb({Host, Port, Ssl}, State),
+handle_call({lb, Host, Port, Ssl, MaxConnections, ConnectionTimeout}, _, State) ->
+ {Reply, NewState} = find_lb({Host, Port, Ssl}, {MaxConnections, ConnectionTimeout}, State),
{reply, Reply, NewState};
handle_call(_, _, State) ->
{reply, {error, unknown_request}, State}.
@@ -96,13 +96,13 @@ terminate(_, State) ->
code_change(_, State, _) ->
State.
-find_lb(Dest, State) ->
+find_lb(Dest, Options, State) ->
Dests = State#httpc_man.destinations,
case dict:find(Dest, Dests) of
{ok, Lb} ->
{{ok, Lb}, State};
error ->
- {ok, Pid} = lhttpc_lb:start_link(Dest),
+ {ok, Pid} = lhttpc_lb:start_link([Dest, Options]),
NewState = State#httpc_man{
destinations = update_dest(Dest, Pid, Dests)
},
Please sign in to comment.
Something went wrong with that request. Please try again.