diff --git a/src/emongo.erl b/src/emongo.erl index 666caa7..b7e95d0 100644 --- a/src/emongo.erl +++ b/src/emongo.erl @@ -29,8 +29,9 @@ -export([pools/0, oid/0, oid_generation_time/1, add_pool/5, auth/3, find/2, find/3, find/4, find_all/2, find_all/3, find_all/4, get_more/4, get_more/5, find_one/3, find_one/4, kill_cursors/2, - insert/3, update/4, update/5, delete/2, delete/3, - ensure_index/3, count/2, dec2hex/1, hex2dec/1]). + insert/3, update/4, update/5, update_sync/4, update_sync/5, + delete/2, delete/3, ensure_index/3, count/2, dec2hex/1, + hex2dec/1]). -include("emongo.hrl"). @@ -237,6 +238,27 @@ update(PoolId, Collection, Selector, Document, Upsert) when ?IS_DOCUMENT(Selecto Packet = emongo_packet:update(Pool#pool.database, Collection, Pool#pool.req_id, Upsert, Selector, Document), emongo_conn:send(Pid, Pool#pool.req_id, Packet). +%%------------------------------------------------------------------------------ +%% update_sync that runs db.$cmd.findOne({getlasterror: 1}); +%%------------------------------------------------------------------------------ +update_sync(PoolId, Collection, Selector, Document) when ?IS_DOCUMENT(Selector), ?IS_DOCUMENT(Document) -> + update_sync(PoolId, Collection, Selector, Document, false). + +update_sync(PoolId, Collection, Selector, Document, Upsert) when ?IS_DOCUMENT(Selector), ?IS_DOCUMENT(Document) -> + {Pid, Pool} = gen_server:call(?MODULE, {pid, PoolId}, infinity), + Packet1 = emongo_packet:update(Pool#pool.database, Collection, Pool#pool.req_id, Upsert, Selector, Document), + Query1 = #emo_query{q=[{<<"getlasterror">>, 1}], limit=1}, + Packet2 = emongo_packet:do_query(Pool#pool.database, "$cmd", Pool#pool.req_id, Query1), + Resp = emongo_conn:send_sync(Pid, Pool#pool.req_id, Packet1, Packet2, ?TIMEOUT), + case lists:keysearch(<<"updatedExisting">>, 1, lists:nth(1, Resp#response.documents)) of + false -> + undefined; + {value, {<<"updatedExisting">>, true}} -> + ok; + {value, {<<"updatedExisting">>, false}} -> + {error, not_updated} + end. + %%------------------------------------------------------------------------------ %% delete %%------------------------------------------------------------------------------ diff --git a/src/emongo_conn.erl b/src/emongo_conn.erl index 10f82ce..693a6ca 100644 --- a/src/emongo_conn.erl +++ b/src/emongo_conn.erl @@ -22,7 +22,7 @@ %% OTHER DEALINGS IN THE SOFTWARE. -module(emongo_conn). --export([start_link/3, init/4, send/3, send_recv/4]). +-export([start_link/3, init/4, send/3, send_sync/5, send_recv/4]). -record(request, {req_id, requestor}). -record(state, {pool_id, socket, requests}). @@ -42,6 +42,20 @@ send(Pid, ReqID, Packet) -> {ok, Result} -> Result; {error, Reason} -> exit(Reason) end. + +send_sync(Pid, ReqID, Packet1, Packet2, Timeout) -> + try + {ok, Resp} = gen:call(Pid, '$emongo_conn_send_sync', {ReqID, Packet1, Packet2}, Timeout), + Documents = emongo_bson:decode(Resp#response.documents), + Resp#response{documents=Documents} + catch + exit:timeout-> + %Clear the state from the timed out call + gen:call(Pid, '$emongo_recv_timeout', ReqID, Timeout), + #response{documents=[]}; + exit:ExitReason -> + exit(ExitReason) + end. send_recv(Pid, ReqID, Packet, Timeout) -> try @@ -64,6 +78,12 @@ loop(State, Leftover) -> gen_tcp:send(Socket, Packet), gen:reply({From, Mref}, ok), loop(State, Leftover); + {'$emongo_conn_send_sync', {From, Mref}, {ReqID, Packet1, Packet2}} -> + gen_tcp:send(Socket, Packet1), + gen_tcp:send(Socket, Packet2), % This is the packet containing getlasterror + Request = #request{req_id=ReqID, requestor={From, Mref}}, + State1 = State#state{requests=[{ReqID, Request}|State#state.requests]}, + loop(State1, Leftover); {'$emongo_conn_send_recv', {From, Mref}, {ReqID, Packet}} -> gen_tcp:send(Socket, Packet), Request = #request{req_id=ReqID, requestor={From, Mref}},