diff options
-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 | ||||
-rwxr-xr-x | configure | 9 | ||||
-rwxr-xr-x | rel/overlay/bin/remsh | 39 | ||||
-rw-r--r-- | rel/overlay/etc/vm.args | 13 | ||||
-rw-r--r-- | rel/reltool.config | 1 |
8 files changed, 94 insertions, 30 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. @@ -44,8 +44,12 @@ do BIGCOUCH_USER=$2 shift 2 ;; + -c) + COOKIE=$2 + shift 2 + ;; *) - echo "usage: $0 [-p {prefix} -t {template} -d {data_dir} -v {view_dir} -u {user}]" + echo "usage: $0 [-p {prefix} -t {template} -d {data_dir} -v {view_dir} -u {user} -c {cookie}]" exit ;; esac @@ -53,6 +57,7 @@ done if test ! -n "$DATA"; then DATA="$PREFIX/var/lib"; fi if test ! -n "$VIEW"; then VIEW="$PREFIX/var/lib"; fi +if test -n "$COOKIE"; then COOKIE="-setcookie $COOKIE"; fi echo "==> configuring bigcouch in rel/bigcouch.config" cat > rel/bigcouch.config << EOF @@ -61,6 +66,7 @@ cat > rel/bigcouch.config << EOF {view_dir, "$VIEW"}. {user, "$BIGCOUCH_USER"}. {node_name, "-name bigcouch"}. +{cookie, "$COOKIE"}. {cluster_port, 5984}. {cluster_ssl, 6984}. {backend_port, 5986}. @@ -81,6 +87,7 @@ cat > rel/dev$i.config << EOF {data_dir, "$DIRPATH/rel/tmpdata/dev$i"}. {view_dir, "$DIRPATH/rel/tmpdata/dev$i"}. {node_name, "-name dev$i@127.0.0.1"}. +{cookie, "$COOKIE"}. {cluster_port, `expr 10000 \* $i + 5984`}. {cluster_ssl, `expr 10000 \* $i + 6984`}. {backend_port, `expr 10000 \* $i + 5986`}. diff --git a/rel/overlay/bin/remsh b/rel/overlay/bin/remsh new file mode 100755 index 00000000..39955ae8 --- /dev/null +++ b/rel/overlay/bin/remsh @@ -0,0 +1,39 @@ +#!/bin/bash + +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +NAME="remsh$$" +REM_NODE="{{node_name}}" +NAME_TYPE=${REM_NODE% *} +REM_NODE=${REM_NODE#* } +HOST=`echo "$REM_NODE" | grep -o "@.*" | sed 's/@//'` + +if test -n $HOST; then + NAME="$NAME_TYPE $NAME@$HOST" +else + NAME="$NAME_TYPE $NAME" +fi + +ERTS_BIN_DIR=$(cd ${0%/*} && pwd) +ROOTDIR=${ERTS_BIN_DIR%/*} + +START_ERL=`cat $ROOTDIR/releases/start_erl.data` +ERTS_VSN=${START_ERL% *} +APP_VSN=${START_ERL#* } +START_CLEAN="${ROOTDIR}/releases/${APP_VSN}/start_clean" + +BINDIR=$ROOTDIR/erts-$ERTS_VSN/bin + +COOKIE="{{cookie}}" + +exec $BINDIR/erl $NAME -remsh $REM_NODE $COOKIE -hidden -boot $START_CLEAN diff --git a/rel/overlay/etc/vm.args b/rel/overlay/etc/vm.args index bb143502..03e5af27 100644 --- a/rel/overlay/etc/vm.args +++ b/rel/overlay/etc/vm.args @@ -4,10 +4,15 @@ # with the -name flag. {{node_name}} -# All nodes must share the same magic cookie for distributed Erlang to work. -# Comment out this line if you synchronized the cookies by other means (using -# the ~/.erlang.cookie file, for example). --setcookie monster +# If you passed a value for the cookie to ./configure it will be set here. +# Otherwise it will default to using ~/.erlang.cookie which will be generated +# automatically if it doesn't exist. +# +# Note that you need to make sure that the cookie value used is synchronized +# across all nodes in the cluster. This means that if you don't set the +# cookie by hand you need to manually sync ~/.erlang.cookie across all nodes +# in the cluster. +{{cookie}} # Tell SASL not to log progress reports -sasl errlog_type error diff --git a/rel/reltool.config b/rel/reltool.config index 3caff2d1..4486c1d5 100644 --- a/rel/reltool.config +++ b/rel/reltool.config @@ -57,6 +57,7 @@ {copy, "overlay/share"}, {copy, "../couchjs/build/couchjs", "bin/couchjs"}, {copy, "../couchjs/build/main.js", "share/couchjs/main.js"}, + {template, "overlay/bin/remsh", "bin/remsh"}, {template, "overlay/etc/default.ini", "etc/default.ini"}, {template, "overlay/etc/vm.args", "etc/vm.args"} ]}. |