Permalink
Browse files

small replica-set fix

  • Loading branch information...
1 parent 445ebaf commit 6a618019dfc3056a0eacd865277564669778d28a Tony Hannan committed May 19, 2011
Showing with 18 additions and 8 deletions.
  1. +8 −4 src/mongo_connect.erl
  2. +9 −3 src/mongo_replset.erl
  3. +1 −1 src/mongodb_tests.erl
View
@@ -72,19 +72,23 @@ 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.
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
@@ -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
@@ -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 = [

0 comments on commit 6a61801

Please sign in to comment.