Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

small replica-set fix

  • Loading branch information...
commit 6a618019dfc3056a0eacd865277564669778d28a 1 parent 445ebaf
Tony Hannan authored
View
12 src/mongo_connect.erl
@@ -72,11 +72,13 @@ call ({Db, Conn = {connection, _Host, VSocket}}, Notices, Request) ->
tcp_send (Socket, MessagesBin),
<<?get_int32 (N)>> = tcp_recv (Socket, 4),
tcp_recv (Socket, N-4) end,
- try mvar:with (VSocket, Call)
- of ReplyBin ->
+ try mvar:with (VSocket, Call) of
+ ReplyBin ->
{RequestId, Reply, <<>>} = mongo_protocol:get_reply (ReplyBin),
Reply % ^ ResponseTo must match RequestId
- catch _:Reason -> close (Conn), throw ({connection_failure, Conn, Reason}) end.
+ catch
+ throw: Reason -> close (Conn), throw ({connection_failure, Conn, Reason});
+ exit: {noproc, _} -> throw ({connection_failure, Conn, closed}) end.
-spec send (dbconnection(), [mongo_protocol:notice()]) -> ok. % IO throws failure()
% Asynchronous send (no reply). Don't know if send succeeded. Exclusive access to the connection during send.
@@ -84,7 +86,9 @@ send ({Db, Conn = {connection, _Host, VSocket}}, Notices) ->
{NoticesBin, _} = messages_binary (Db, Notices),
Send = fun (Socket) -> tcp_send (Socket, NoticesBin) end,
try mvar:with (VSocket, Send)
- catch _:Reason -> close (Conn), throw ({connection_failure, Conn, Reason}) end.
+ catch
+ throw: Reason -> close (Conn), throw ({connection_failure, Conn, Reason});
+ exit: {noproc, _} -> throw ({connection_failure, Conn, closed}) end.
-spec messages_binary (mongo_protocol:db(), [mongo_protocol:message()]) -> {binary(), mongo_protocol:requestid()}.
% Binary representation of messages
View
12 src/mongo_replset.erl
@@ -105,11 +105,17 @@ fetch_member_info (ReplConn = {rs_connection, _ReplName, VConns}) ->
{Conn, Info} = until_success (OldHosts_, fun (Host) -> connect_member (ReplConn, Host) end),
OldHosts = sets:from_list (OldHosts_),
NewHosts = sets:from_list (lists:map (fun mongo_connect:read_host/1, bson:at (hosts, Info))),
+ RemovedHosts = sets:subtract (OldHosts, NewHosts),
+ AddedHosts = sets:subtract (NewHosts, OldHosts),
mvar:modify_ (VConns, fun (Dict) ->
- Dict1 = sets:fold (fun remove_host/2, Dict, sets:subtract (OldHosts, NewHosts)),
- Dict2 = sets:fold (fun add_host/2, Dict1, sets:subtract (NewHosts, OldHosts)),
+ Dict1 = sets:fold (fun remove_host/2, Dict, RemovedHosts),
+ Dict2 = sets:fold (fun add_host/2, Dict1, AddedHosts),
Dict2 end),
- {Conn, Info}.
+ case sets:is_element (mongo_connect:conn_host (Conn), RemovedHosts) of
+ false -> {Conn, Info};
+ true -> % Conn connected to member but under wrong name (eg. localhost instead of 127.0.0.1) so it was closed and removed because it did not match a host in isMaster info. Reconnect using correct name.
+ Hosts = dict:fetch_keys (mvar:read (VConns)),
+ until_success (Hosts, fun (Host) -> connect_member (ReplConn, Host) end) end.
add_host (Host, Dict) -> dict:store (Host, {}, Dict).
View
2  src/mongodb_tests.erl
@@ -139,7 +139,7 @@ replset_test() -> % TODO: change from connect_test
% Replica set named "rs1" must be running on localhost:27017 & 27018
mongo_rs_test() ->
- RsConn = mongo:rs_connect ({<<"rs1">>,[localhost]}),
+ RsConn = mongo:rs_connect ({<<"rs1">>,["127.0.0.1"]}),
{ok, {Teams1, Ids1}} = mongo:do (safe, master, RsConn, baseball, fun () ->
mongo:delete (team, {}),
Teams0 = [
Please sign in to comment.
Something went wrong with that request. Please try again.