diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/couch/src/couch_httpd_db.erl | 22 | ||||
-rw-r--r-- | apps/couch/src/couch_rep.erl | 8 | ||||
-rw-r--r-- | apps/couch/src/couch_rep_changes_feed.erl | 2 | ||||
-rw-r--r-- | apps/couch/src/couch_server.erl | 30 |
4 files changed, 37 insertions, 25 deletions
diff --git a/apps/couch/src/couch_httpd_db.erl b/apps/couch/src/couch_httpd_db.erl index 0bf97e26..6458fe70 100644 --- a/apps/couch/src/couch_httpd_db.erl +++ b/apps/couch/src/couch_httpd_db.erl @@ -20,7 +20,7 @@ -import(couch_httpd, [send_json/2,send_json/3,send_json/4,send_method_not_allowed/2, - send_response/4,start_json_response/2,start_json_response/3, + start_json_response/2, send_chunk/2,last_chunk/1,end_json_response/1, start_chunked_response/3, absolute_uri/2, send/2, start_response_length/4]). @@ -236,7 +236,7 @@ db_req(#httpd{method='POST',path_parts=[DbName]}=Req, Db) -> ?LOG_INFO("Batch doc error (~s): ~p",[DocId, Error]) end end), - + send_json(Req, 202, [], {[ {ok, true}, {id, DocId} @@ -689,7 +689,7 @@ db_doc_req(#httpd{method='PUT'}=Req, Db, DocId) -> update_type = UpdateType } = parse_doc_query(Req), couch_doc:validate_docid(DocId), - + Loc = absolute_uri(Req, "/" ++ ?b2l(Db#db.name) ++ "/" ++ ?b2l(DocId)), RespHeaders = [{"Location", Loc}], case couch_util:to_list(couch_httpd:header_value(Req, "Content-Type")) of @@ -711,7 +711,7 @@ db_doc_req(#httpd{method='PUT'}=Req, Db, DocId) -> "ok" -> % batch Doc = couch_doc_from_req(Req, DocId, couch_httpd:json_body(Req)), - + spawn(fun() -> case catch(couch_db:update_doc(Db, Doc, [])) of {ok, _} -> ok; @@ -776,7 +776,7 @@ send_doc_efficiently(#httpd{mochi_req = MochiReq} = Req, send_json(Req, 200, Headers, couch_doc:to_json_obj(Doc, Options)); true -> Boundary = couch_uuids:random(), - JsonBytes = ?JSON_ENCODE(couch_doc:to_json_obj(Doc, + JsonBytes = ?JSON_ENCODE(couch_doc:to_json_obj(Doc, [attachments, follows, att_encoding_info | Options])), {ContentType, Len} = couch_doc:len_doc_to_multi_part_stream( Boundary,JsonBytes, Atts, true), @@ -793,7 +793,7 @@ send_docs_multipart(Req, Results, Options1) -> OuterBoundary = couch_uuids:random(), InnerBoundary = couch_uuids:random(), Options = [attachments, follows, att_encoding_info | Options1], - CType = {"Content-Type", + CType = {"Content-Type", "multipart/mixed; boundary=\"" ++ ?b2l(OuterBoundary) ++ "\""}, {ok, Resp} = start_chunked_response(Req, 200, [CType]), couch_httpd:send_chunk(Resp, <<"--", OuterBoundary/binary>>), @@ -811,8 +811,8 @@ send_docs_multipart(Req, Results, Options1) -> ({{not_found, missing}, RevId}) -> RevStr = couch_doc:rev_to_str(RevId), Json = ?JSON_ENCODE({[{"missing", RevStr}]}), - couch_httpd:send_chunk(Resp, - [<<"\r\nContent-Type: application/json; error=\"true\"\r\n\r\n">>, + couch_httpd:send_chunk(Resp, + [<<"\r\nContent-Type: application/json; error=\"true\"\r\n\r\n">>, Json, <<"\r\n--", OuterBoundary/binary>>]) end, Results), @@ -848,7 +848,7 @@ receive_request_data(Req, LenLeft) when LenLeft > 0 -> {Data, fun() -> receive_request_data(Req, LenLeft - iolist_size(Data)) end}; receive_request_data(_Req, _) -> throw(<<"expected more data">>). - + make_content_range(From, To, Len) -> ?l2b(io_lib:format("bytes ~B-~B/~B", [From, To, Len])). @@ -1078,8 +1078,8 @@ db_attachment_req(#httpd{method=Method,mochi_req=MochiReq}=Req, Db, DocId, FileN _Else -> ok end, - - + + fun(Size) -> couch_httpd:recv(Req, Size) end end, att_len = case couch_httpd:header_value(Req,"Content-Length") of diff --git a/apps/couch/src/couch_rep.erl b/apps/couch/src/couch_rep.erl index 82b69bc9..761fbd76 100644 --- a/apps/couch/src/couch_rep.erl +++ b/apps/couch/src/couch_rep.erl @@ -275,7 +275,7 @@ handle_info({'EXIT', _Pid, Reason}, State) -> terminate(normal, #state{checkpoint_scheduled=nil, init_args=[RepId, _, _, Module]} = State) -> do_terminate(State), Module:replication_completed(RepId); - + terminate(normal, #state{init_args=[RepId, _, _, Module]} = State) -> timer:cancel(State#state.checkpoint_scheduled), do_terminate(do_checkpoint(State)), @@ -409,7 +409,7 @@ do_terminate(State) -> continuous = Continuous, source_log = #doc{body={OldHistory}} } = State, - + NewRepHistory = case CheckpointHistory of nil -> {[{<<"no_changes">>, true} | OldHistory]}; @@ -504,7 +504,7 @@ make_replication_id({Props}, UserCtx, 1) -> maybe_append_filters({Props}, [HostName, Src, Tgt], UserCtx). maybe_append_filters({Props}, Base, UserCtx) -> - Base2 = Base ++ + Base2 = Base ++ case couch_util:get_value(<<"filter">>, Props) of undefined -> case couch_util:get_value(<<"doc_ids">>, Props) of @@ -794,7 +794,7 @@ commit_to_both(Source, Target, RequiredSeq) -> exit(replication_link_failure) end, {SourceStartTime, TargetStartTime}. - + ensure_full_commit(#http_db{headers = Headers} = Target) -> Headers1 = [ {"Content-Length", 0} | diff --git a/apps/couch/src/couch_rep_changes_feed.erl b/apps/couch/src/couch_rep_changes_feed.erl index 651069fb..4781b583 100644 --- a/apps/couch/src/couch_rep_changes_feed.erl +++ b/apps/couch/src/couch_rep_changes_feed.erl @@ -242,7 +242,7 @@ handle_call({add_change, Row}, From, State) -> handle_call(next_changes, From, State) -> handle_next_changes(From, State); - + handle_call(stop, _From, State) -> {stop, normal, ok, State}. diff --git a/apps/couch/src/couch_server.erl b/apps/couch/src/couch_server.erl index f9c960c5..c7850990 100644 --- a/apps/couch/src/couch_server.erl +++ b/apps/couch/src/couch_server.erl @@ -199,16 +199,28 @@ try_close_lru(StartTime) -> % There may exist an extremely small possibility of a race % condition here, if a process could lookup the DB before the lock, % but fail to monitor the fd before the is_idle check. - true = ets:update_element(couch_dbs, DbName, {#db.fd_monitor, locked}), - [#db{main_pid = Pid} = Db] = ets:lookup(couch_dbs, DbName), - case couch_db:is_idle(Db) of true -> - true = ets:delete(couch_dbs, DbName), - true = ets:delete(couch_lru, DbName), - exit(Pid, kill), - ok; + % + % If we do hit this race condition the behavior is that the process + % grabbing the database will end up inserting a value into the + % couch_lru table. Its possible that we end up picking that up + % as the DbName above to close. So we here we'll just remove the + % couch_lru entry and ignore it. + case ets:update_element(couch_dbs, DbName, {#db.fd_monitor, locked}) of + true -> + [#db{main_pid = Pid} = Db] = ets:lookup(couch_dbs, DbName), + case couch_db:is_idle(Db) of true -> + true = ets:delete(couch_dbs, DbName), + true = ets:delete(couch_lru, DbName), + exit(Pid, kill), + ok; + false -> + Update = {#db.fd_monitor, nil}, + true = ets:update_element(couch_dbs, DbName, Update), + true = ets:insert(couch_lru, {DbName, now()}), + try_close_lru(StartTime) + end; false -> - true = ets:update_element(couch_dbs, DbName, {#db.fd_monitor, nil}), - true = ets:insert(couch_lru, {DbName, now()}), + true = ets:delete(couch_lru, DbName), try_close_lru(StartTime) end end. |