summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/couch/src/couch_httpd_db.erl22
-rw-r--r--apps/couch/src/couch_rep.erl8
-rw-r--r--apps/couch/src/couch_rep_changes_feed.erl2
-rw-r--r--apps/couch/src/couch_server.erl30
-rwxr-xr-xconfigure9
-rwxr-xr-xrel/overlay/bin/remsh39
-rw-r--r--rel/overlay/etc/vm.args13
-rw-r--r--rel/reltool.config1
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.
diff --git a/configure b/configure
index 0e299604..72d441e2 100755
--- a/configure
+++ b/configure
@@ -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"}
]}.