Return-Path: Delivered-To: apmail-incubator-couchdb-commits-archive@locus.apache.org Received: (qmail 4391 invoked from network); 4 Jul 2008 18:45:15 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 4 Jul 2008 18:45:15 -0000 Received: (qmail 15079 invoked by uid 500); 4 Jul 2008 18:45:16 -0000 Delivered-To: apmail-incubator-couchdb-commits-archive@incubator.apache.org Received: (qmail 15048 invoked by uid 500); 4 Jul 2008 18:45:16 -0000 Mailing-List: contact couchdb-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: couchdb-dev@incubator.apache.org Delivered-To: mailing list couchdb-commits@incubator.apache.org Received: (qmail 15039 invoked by uid 99); 4 Jul 2008 18:45:16 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 04 Jul 2008 11:45:16 -0700 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 04 Jul 2008 18:44:24 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id D946423889C2; Fri, 4 Jul 2008 11:44:45 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r674105 - in /incubator/couchdb/branches/runtimeconfig: ./ bin/ share/server/ src/couchdb/ src/mochiweb/ Date: Fri, 04 Jul 2008 18:44:45 -0000 To: couchdb-commits@incubator.apache.org From: jan@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080704184445.D946423889C2@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: jan Date: Fri Jul 4 11:44:44 2008 New Revision: 674105 URL: http://svn.apache.org/viewvc?rev=674105&view=rev Log: Merged revisions 670653,670720,670732,670737-670738,670774,671125,671151,671610,673631,673634,673778 via svnmerge from https://svn.apache.org/repos/asf/incubator/couchdb/trunk Modified: incubator/couchdb/branches/runtimeconfig/ (props changed) incubator/couchdb/branches/runtimeconfig/NEWS incubator/couchdb/branches/runtimeconfig/acinclude.m4.in incubator/couchdb/branches/runtimeconfig/bin/couchdb.tpl.in incubator/couchdb/branches/runtimeconfig/share/server/main.js incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_httpd.erl incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_util.erl incubator/couchdb/branches/runtimeconfig/src/mochiweb/Makefile.am incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_html.erl incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_request.erl incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_socket_server.erl Propchange: incubator/couchdb/branches/runtimeconfig/ ------------------------------------------------------------------------------ --- svnmerge-integrated (original) +++ svnmerge-integrated Fri Jul 4 11:44:44 2008 @@ -1 +1 @@ -/incubator/couchdb/trunk:1-669515 +/incubator/couchdb/trunk:1-674103 Modified: incubator/couchdb/branches/runtimeconfig/NEWS URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/NEWS?rev=674105&r1=674104&r2=674105&view=diff ============================================================================== --- incubator/couchdb/branches/runtimeconfig/NEWS (original) +++ incubator/couchdb/branches/runtimeconfig/NEWS Fri Jul 4 11:44:44 2008 @@ -5,6 +5,11 @@ http://wiki.apache.org/couchdb/BreakingChanges +Version 0.9.0-incubating +------------------------ + +This release is still under development. + Version 0.8.0-incubating ------------------------ @@ -18,7 +23,7 @@ * Miscellaneous improvements to system integration and portability. * Swapped out Erlang's inets HTTP server for the Mochiweb HTTP server. * SpiderMonkey is no longer included with CouchDB, but rather treated as an - external dependendancy. + external dependency. * Added bits of awesome. Please note that there have been many backwards incomatible changes in this Modified: incubator/couchdb/branches/runtimeconfig/acinclude.m4.in URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/acinclude.m4.in?rev=674105&r1=674104&r2=674105&view=diff ============================================================================== --- incubator/couchdb/branches/runtimeconfig/acinclude.m4.in (original) +++ incubator/couchdb/branches/runtimeconfig/acinclude.m4.in Fri Jul 4 11:44:44 2008 @@ -17,9 +17,9 @@ m4_define([LOCAL_PACKAGE_NAME], [Apache CouchDB]) m4_define([LOCAL_VERSION_MAJOR], [0]) -m4_define([LOCAL_VERSION_MINOR], [8]) +m4_define([LOCAL_VERSION_MINOR], [9]) m4_define([LOCAL_VERSION_REVISION], [0]) -m4_define([LOCAL_VERSION_STAGE], []) +m4_define([LOCAL_VERSION_STAGE], [a]) m4_define([LOCAL_VERSION_RELEASE], [%release%]) m4_define([LOCAL_VERSION_STATUS], [incubating]) m4_define([LOCAL_VERSION_PRIMARY], Modified: incubator/couchdb/branches/runtimeconfig/bin/couchdb.tpl.in URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/bin/couchdb.tpl.in?rev=674105&r1=674104&r2=674105&view=diff ============================================================================== --- incubator/couchdb/branches/runtimeconfig/bin/couchdb.tpl.in (original) +++ incubator/couchdb/branches/runtimeconfig/bin/couchdb.tpl.in Fri Jul 4 11:44:44 2008 @@ -186,7 +186,7 @@ command="`%ICU_CONFIG% --invoke` \ %ERL% $interactive_option -smp auto -sasl errlog_type error \ -pa %localerlanglibdir%/couch-%version%/ebin \ - %localerlanglibdir%/mochiweb-r76/ebin \ + %localerlanglibdir%/mochiweb-r82/ebin \ -eval \"application:load(inets)\" \ -eval \"application:load(crypto)\" \ -eval \"application:load(couch)\" \ Modified: incubator/couchdb/branches/runtimeconfig/share/server/main.js URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/share/server/main.js?rev=674105&r1=674104&r2=674105&view=diff ============================================================================== --- incubator/couchdb/branches/runtimeconfig/share/server/main.js [utf-8] (original) +++ incubator/couchdb/branches/runtimeconfig/share/server/main.js [utf-8] Fri Jul 4 11:44:44 2008 @@ -74,15 +74,13 @@ // ] // var doc = cmd[1]; - seal(doc); // seal to prevent map functions from changing doc + recursivelySeal(doc); // seal to prevent map functions from changing doc var buf = []; for (var i = 0; i < funs.length; i++) { map_results = []; try { funs[i](doc); - buf.push(map_results.filter(function(pair) { - return pair[0] !== undefined && pair[1] !== undefined; - })); + buf.push(toJSON(map_results)); } catch (err) { if (err == "fatal_error") { // Only if it's a "fatal_error" do we exit. What's a fatal error? @@ -96,10 +94,10 @@ reason: "function raised fatal exception"}; } print(toJSON({log: "function raised exception (" + err + ")"})); - buf.push([]); + buf.push("[]"); } } - print(toJSON(buf)); + print("[" + buf.join(", ") + "]"); break; case "rereduce": @@ -170,9 +168,18 @@ } } +function recursivelySeal(obj) { + seal(obj); + for (var propname in obj) { + if (typeof doc[propname] == "object") { + recursivelySeal(doc[propname]); + } + } +} + function toJSON(val) { if (typeof(val) == "undefined") { - throw {error:"bad_value", reason:"Cannot encode 'undefined' value as JSON"}; + throw "Cannot encode 'undefined' value as JSON"; } var subs = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'}; Modified: incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_httpd.erl URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_httpd.erl?rev=674105&r1=674104&r2=674105&view=diff ============================================================================== --- incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_httpd.erl (original) +++ incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_httpd.erl Fri Jul 4 11:44:44 2008 @@ -116,9 +116,11 @@ "/_restart" -> handle_restart_request(Req, Method); "/_utils" -> - {ok, Req:respond({301, [{"Location", "/_utils/"}], <<>>})}; + {ok, Req:respond({301, [ + {"Location", "/_utils/"} + ] ++ server_header(), <<>>})}; "/_utils/" ++ PathInfo -> - {ok, Req:serve_file(PathInfo, DocumentRoot)}; + {ok, Req:serve_file(PathInfo, DocumentRoot, server_header())}; "/_config/" ++ Config -> handle_config_request(Req, Method, {config, Config}); "/_" ++ _Path -> @@ -483,7 +485,7 @@ fun(_Key, _Red, {AccSeparator,AccSkip,AccCount}) when AccSkip > 0 -> {ok, {AccSeparator,AccSkip-1,AccCount}}; (_Key, _Red, {AccSeparator,0,AccCount}) when AccCount == 0 -> - {stop,{AccSeparator,0,AccCount}}; + {ok, {AccSeparator,0,AccCount}}; (_Key, Red, {AccSeparator,0,AccCount}) when GroupLevel == 0 -> Json = lists:flatten(cjson:encode({obj, [{key, null}, {value, Red}]})), Resp:write_chunk(AccSeparator ++ Json), @@ -633,9 +635,10 @@ throw({not_found, missing}); {Type, Bin} -> Resp = Req:respond({200, [ - {"content-type", Type}, - {"content-length", integer_to_list(couch_doc:bin_size(Bin))} - ], chunked}), + {"Cache-Control", "must-revalidate"}, + {"Content-Type", Type}, + {"Content-Length", integer_to_list(couch_doc:bin_size(Bin))} + ] ++ server_header(), chunked}), couch_doc:bin_foldl(Bin, fun(BinSegment, []) -> ok = Resp:write_chunk(BinSegment), @@ -722,6 +725,8 @@ Args#view_query_args{start_key=JsonKey,end_key=JsonKey}; {"startkey_docid", DocId} -> Args#view_query_args{start_docid=DocId}; + {"endkey_docid", DocId} -> + Args#view_query_args{end_docid=DocId}; {"startkey", Value} -> Args#view_query_args{start_key=cjson:decode(Value)}; {"endkey", Value} -> @@ -971,11 +976,11 @@ {500, error, Error}. send_error(Req, {method_not_allowed, Methods}) -> - {ok, Req:respond({405, [{"Allow", Methods}], <<>>})}; + {ok, Req:respond({405, [{"Allow", Methods}] ++ server_header(), <<>>})}; send_error(Req, {modified, Etag}) -> - {ok, Req:respond({412, [{"Etag", Etag}], <<>>})}; + {ok, Req:respond({412, [{"Etag", Etag}] ++ server_header(), <<>>})}; send_error(Req, {not_modified, Etag}) -> - {ok, Req:respond({304, [{"Etag", Etag}], <<>>})}; + {ok, Req:respond({304, [{"Etag", Etag}] ++ server_header(), <<>>})}; send_error(Req, Error) -> {Code, Json} = error_to_json(Error), ?LOG_INFO("HTTP Error (code ~w): ~p", [Code, Error]), @@ -991,18 +996,23 @@ send_json(Req, Code, [], Value). send_json(Req, Code, Headers, Value) -> - ContentType = negotiate_content_type(Req), + DefaultHeaders = [ + {"Content-Type", negotiate_content_type(Req)}, + {"Cache-Control", "must-revalidate"} + ] ++ server_header(), Body = cjson:encode(Value), - Resp = Req:respond({Code, [{"Content-Type", ContentType}] ++ Headers, - Body}), + Resp = Req:respond({Code, DefaultHeaders ++ Headers, Body}), {ok, Resp}. start_json_response(Req, Code) -> start_json_response(Req, Code, []). start_json_response(Req, Code, Headers) -> - ContentType = negotiate_content_type(Req), - Req:respond({Code, [{"Content-Type", ContentType}] ++ Headers, chunked}). + DefaultHeaders = [ + {"Content-Type", negotiate_content_type(Req)}, + {"Cache-Control", "must-revalidate"} + ] ++ server_header(), + Req:respond({Code, DefaultHeaders ++ Headers, chunked}). end_json_response(Resp) -> Resp:write_chunk(""), @@ -1021,3 +1031,7 @@ true -> "application/json"; false -> "text/plain;charset=utf-8" end. + +server_header() -> + [{"Server", "CouchDB/" ++ couch_server:get_version() ++ + " (Erlang OTP/" ++ erlang:system_info(otp_release) ++ ")"}]. Modified: incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_util.erl URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_util.erl?rev=674105&r1=674104&r2=674105&view=diff ============================================================================== --- incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_util.erl (original) +++ incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_util.erl Fri Jul 4 11:44:44 2008 @@ -41,7 +41,7 @@ case erl_ddll:load_driver(LibDir, "couch_erl_driver") of ok -> ok; {error, already_loaded} -> ok; - Error -> exit(Error) + {error, Error} -> exit(erl_ddll:format_error(Error)) end. new_uuid() -> Modified: incubator/couchdb/branches/runtimeconfig/src/mochiweb/Makefile.am URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/src/mochiweb/Makefile.am?rev=674105&r1=674104&r2=674105&view=diff ============================================================================== --- incubator/couchdb/branches/runtimeconfig/src/mochiweb/Makefile.am (original) +++ incubator/couchdb/branches/runtimeconfig/src/mochiweb/Makefile.am Fri Jul 4 11:44:44 2008 @@ -10,9 +10,7 @@ ## License for the specific language governing permissions and limitations under ## the License. -devdocdir = $(localdocdir)/developer/mochiweb - -mochiwebebindir = $(localerlanglibdir)/mochiweb-r76/ebin +mochiwebebindir = $(localerlanglibdir)/mochiweb-r82/ebin mochiwebebin_DATA = $(static_files) $(compiled_files) Modified: incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_html.erl URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_html.erl?rev=674105&r1=674104&r2=674105&view=diff ============================================================================== --- incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_html.erl (original) +++ incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_html.erl Fri Jul 4 11:44:44 2008 @@ -101,7 +101,7 @@ to_html(Tokens) when is_list(Tokens) -> to_html(Tokens, []). -%% @spec escape(string() | binary()) -> string() +%% @spec escape(string() | atom() | binary()) -> binary() %% @doc Escape a string such that it's safe for HTML (amp; lt; gt;). escape(B) when is_binary(B) -> escape(binary_to_list(B), []); @@ -110,7 +110,7 @@ escape(S) when is_list(S) -> escape(S, []). -%% @spec escape_attr(S::string()) -> string() +%% @spec escape_attr(string() | binary() | atom() | integer() | float()) -> binary() %% @doc Escape a string such that it's safe for HTML attrs %% (amp; lt; gt; quot;). escape_attr(B) when is_binary(B) -> Modified: incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_request.erl URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_request.erl?rev=674105&r1=674104&r2=674105&view=diff ============================================================================== --- incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_request.erl (original) +++ incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_request.erl Fri Jul 4 11:44:44 2008 @@ -15,11 +15,11 @@ -export([send/1, recv/1, recv/2, recv_body/0, recv_body/1]). -export([start_response/1, start_response_length/1, start_raw_response/1]). -export([respond/1, ok/1]). --export([not_found/0]). +-export([not_found/0, not_found/1]). -export([parse_post/0, parse_qs/0]). -export([should_close/0, cleanup/0]). -export([parse_cookie/0, get_cookie_value/1]). --export([serve_file/2]). +-export([serve_file/2, serve_file/3]). -export([test/0]). -define(SAVE_QS, mochiweb_request_qs). @@ -276,9 +276,16 @@ Response. %% @spec not_found() -> response() -%% @doc respond({404, [{"Content-Type", "text/plain"}], "Not found."}). +%% @doc Alias for not_found([]). not_found() -> - respond({404, [{"Content-Type", "text/plain"}], <<"Not found.">>}). + not_found([]). + +%% @spec not_found(ExtraHeaders) -> response() +%% @doc Alias for respond({404, [{"Content-Type", "text/plain"} +%% | ExtraHeaders], <<"Not found.">>}). +not_found(ExtraHeaders) -> + respond({404, [{"Content-Type", "text/plain"} | ExtraHeaders], + <<"Not found.">>}). %% @spec ok({value(), iodata()} | {value(), ioheaders(), iodata() | {file, IoDevice}}) -> %% response() @@ -326,7 +333,9 @@ %% unread data left on the socket, can't safely continue orelse (DidNotRecv andalso get_header_value("content-length") =/= undefined - andalso list_to_integer(get_header_value("content-length")) > 0). + andalso list_to_integer(get_header_value("content-length")) > 0) + orelse (DidNotRecv + andalso get_header_value("transfer-encoding") =:= "chunked"). %% @spec cleanup() -> ok %% @doc Clean up any junk in the process dictionary, required before continuing @@ -455,9 +464,14 @@ %% @spec serve_file(Path, DocRoot) -> Response %% @doc Serve a file relative to DocRoot. serve_file(Path, DocRoot) -> + serve_file(Path, DocRoot, []). + +%% @spec serve_file(Path, DocRoot, ExtraHeaders) -> Response +%% @doc Serve a file relative to DocRoot. +serve_file(Path, DocRoot, ExtraHeaders) -> case mochiweb_util:safe_relative_path(Path) of undefined -> - not_found(); + not_found(ExtraHeaders); RelPath -> FullPath = filename:join([DocRoot, RelPath]), File = case filelib:is_dir(FullPath) of @@ -471,20 +485,23 @@ LastModified = httpd_util:rfc1123_date(FileInfo#file_info.mtime), case get_header_value("if-modified-since") of LastModified -> - respond({304, [], ""}); + respond({304, ExtraHeaders, ""}); _ -> case file:open(File, [raw, binary]) of {ok, IoDevice} -> ContentType = mochiweb_util:guess_mime(File), - Res = ok({ContentType, [{"last-modified", LastModified}], {file, IoDevice}}), + Res = ok({ContentType, + [{"last-modified", LastModified} + | ExtraHeaders], + {file, IoDevice}}), file:close(IoDevice), Res; _ -> - not_found() + not_found(ExtraHeaders) end end; {error, _} -> - not_found() + not_found(ExtraHeaders) end end. Modified: incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_socket_server.erl URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_socket_server.erl?rev=674105&r1=674104&r2=674105&view=diff ============================================================================== --- incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_socket_server.erl (original) +++ incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_socket_server.erl Fri Jul 4 11:44:44 2008 @@ -96,6 +96,14 @@ gen_server:start_link(Name, ?MODULE, State, []) end. +ipv6_supported() -> + case (catch inet:getaddr("localhost", inet6)) of + {ok, _Addr} -> + true; + {error, _} -> + false + end. + init(State=#mochiweb_socket_server{ip=Ip, port=Port, backlog=Backlog}) -> process_flag(trap_exit, true), BaseOpts = [binary, @@ -106,11 +114,16 @@ {active, false}, {nodelay, true}], Opts = case Ip of - any -> - BaseOpts; - Ip -> - [{ip, Ip} | BaseOpts] - end, + any -> + case ipv6_supported() of % IPv4, and IPv6 if supported + true -> [inet, inet6 | BaseOpts]; + _ -> BaseOpts + end; + {_, _, _, _} -> % IPv4 + [inet, {ip, Ip} | BaseOpts]; + {_, _, _, _, _, _, _, _} -> % IPv6 + [inet6, {ip, Ip} | BaseOpts] + end, case gen_tcp_listen(Port, Opts, State) of {stop, eacces} -> case Port < 1024 of