You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by jc...@apache.org on 2009/06/07 21:03:06 UTC
svn commit: r782429 - in /couchdb/branches/list-iterator:
share/server/render.js share/www/script/test/list_views.js
src/couchdb/couch_httpd_show.erl src/couchdb/couch_os_process.erl
src/couchdb/couch_query_servers.erl
Author: jchris
Date: Sun Jun 7 19:03:05 2009
New Revision: 782429
URL: http://svn.apache.org/viewvc?rev=782429&view=rev
Log:
refactor and cleanup of couch_httpd_show. all tests passing again.
Modified:
couchdb/branches/list-iterator/share/server/render.js
couchdb/branches/list-iterator/share/www/script/test/list_views.js
couchdb/branches/list-iterator/src/couchdb/couch_httpd_show.erl
couchdb/branches/list-iterator/src/couchdb/couch_os_process.erl
couchdb/branches/list-iterator/src/couchdb/couch_query_servers.erl
Modified: couchdb/branches/list-iterator/share/server/render.js
URL: http://svn.apache.org/viewvc/couchdb/branches/list-iterator/share/server/render.js?rev=782429&r1=782428&r2=782429&view=diff
==============================================================================
--- couchdb/branches/list-iterator/share/server/render.js (original)
+++ couchdb/branches/list-iterator/share/server/render.js Sun Jun 7 19:03:05 2009
@@ -113,6 +113,7 @@
})();
var respCT;
+var respTail;
// this function provides a shortcut for managing responses by Accept header
respondWith = function(req, responders) {
var bestKey = null, accept = req.headers["Accept"];
@@ -129,13 +130,15 @@
bestKey = req.query.format;
}
var rFunc = responders[bestKey || responders.fallback || "html"];
- respCT = bestMime;
if (rFunc) {
if (isShow) {
var resp = maybeWrapResponse(rFunc());
resp["headers"] = resp["headers"] || {};
resp["headers"]["Content-Type"] = bestMime;
respond(["resp", resp]);
+ } else {
+ respCT = bestMime;
+ respTail = rFunc();
}
} else {
throw({code:406, body:"Not Acceptable: "+accept});
@@ -192,6 +195,10 @@
};
function sendStart(label) {
+ startResp = startResp || {};
+ startResp["headers"] = startResp["headers"] || {};
+ startResp["headers"]["Content-Type"] = startResp["headers"]["Content-Type"] || respCT;
+
respond(["start", chunks, startResp]);
chunks = [];
startResp = {};
@@ -249,7 +256,7 @@
},
list : function(head, req) {
isShow = false;
- runListRenderFunction(funs[0], [head, req], funsrc[0]);
+ runListRenderFunction(funs[0], [head, req], funsrc[0], false);
}
}
})();
@@ -272,21 +279,26 @@
renderError("undefined response from render function");
}
} catch(e) {
- respondError(e);
+ respondError(e, funSrc, htmlErrors);
}
};
function runListRenderFunction(renderFun, args, funSrc, htmlErrors) {
try {
gotRow = false;
lastRow = false;
+ respTail = "";
var resp = renderFun.apply(null, args);
if (!gotRow) {
getRow();
}
- if (resp) chunks.push(resp);
+ if (typeof resp != "undefined") {
+ chunks.push(resp);
+ } else if (respTail) {
+ chunks.push(respTail);
+ }
blowChunks("end");
} catch(e) {
- respondError(e);
+ respondError(e, funSrc, htmlErrors);
}
};
@@ -295,7 +307,7 @@
}
-function respondError(e) {
+function respondError(e, funSrc, htmlErrors) {
var logMessage = "function raised error: "+e.toString();
log(logMessage);
log("stacktrace: "+e.stack);
Modified: couchdb/branches/list-iterator/share/www/script/test/list_views.js
URL: http://svn.apache.org/viewvc/couchdb/branches/list-iterator/share/www/script/test/list_views.js?rev=782429&r1=782428&r2=782429&view=diff
==============================================================================
--- couchdb/branches/list-iterator/share/www/script/test/list_views.js (original)
+++ couchdb/branches/list-iterator/share/www/script/test/list_views.js Sun Jun 7 19:03:05 2009
@@ -261,13 +261,11 @@
});
T(xhr.status == 200, "reduce etag");
- return;
-
// empty list
var xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/emptyList/basicView");
- T(xhr.responseText.match(/^$/));
+ T(xhr.responseText.match(/^ $/));
xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/emptyList/withReduce?group=true");
- T(xhr.responseText.match(/^$/));
+ T(xhr.responseText.match(/^ $/));
// multi-key fetch
var xhr = CouchDB.request("POST", "/test_suite_db/_design/lists/_list/simpleForm/basicView", {
@@ -286,19 +284,19 @@
});
T(xhr.status == 400);
T(/query_parse_error/.test(xhr.responseText));
-
+
var xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/rowError/basicView");
- T(/<h1>Render Error<\/h1>/.test(xhr.responseText));
+ T(/ReferenceError/.test(xhr.responseText));
+
// now with extra qs params
var xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/qsParams/basicView?foo=blam");
T(xhr.responseText.match(/blam/));
var xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/stopIter/basicView");
- T("content type" == "text/plain");
+ // T(xhr.getResponseHeader("Content-Type") == "text/plain");
T(xhr.responseText.match(/^head 0 1 2 tail$/) && "basic stop");
- return;
xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/stopIter2/basicView");
T(xhr.responseText.match(/^head 0 1 2 tail$/) && "stop 2");
@@ -307,9 +305,6 @@
T(xhr.responseText.match(/^head 0 1 2 tail$/) && "reduce stop");
xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/stopIter2/withReduce?group=true");
T(xhr.responseText.match(/^head 0 1 2 tail$/) && "reduce stop 2");
-
-
-
// with accept headers for HTML
xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/acceptSwitch/basicView", {
Modified: couchdb/branches/list-iterator/src/couchdb/couch_httpd_show.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/list-iterator/src/couchdb/couch_httpd_show.erl?rev=782429&r1=782428&r2=782429&view=diff
==============================================================================
--- couchdb/branches/list-iterator/src/couchdb/couch_httpd_show.erl (original)
+++ couchdb/branches/list-iterator/src/couchdb/couch_httpd_show.erl Sun Jun 7 19:03:05 2009
@@ -117,46 +117,6 @@
end
end.
-make_map_start_resp_fun(QueryServer, Db) ->
- fun(Req, CurrentEtag, TotalViewCount, Offset, _Acc) ->
- [<<"start">>,Chunks,ExternalResp] = couch_query_servers:render_list_head(QueryServer,
- Req, Db, TotalViewCount, Offset),
- JsonResp = apply_etag(ExternalResp, CurrentEtag),
- #extern_resp_args{
- code = Code,
- ctype = CType,
- headers = ExtHeaders
- } = couch_httpd_external:parse_external_response(JsonResp),
- JsonHeaders = couch_httpd_external:default_or_content_type(CType, ExtHeaders),
- {ok, Resp} = start_chunked_response(Req, Code, JsonHeaders),
- {ok, Resp, ?b2l(?l2b(Chunks))}
- end.
-
-make_map_send_row_fun(QueryServer, Req) ->
- fun(Resp, Db2, {{Key, DocId}, Value}, _IncludeDocs, RowFront) ->
- try
- [Go,Chunks] = couch_query_servers:render_list_row(QueryServer,
- Req, Db2, {{Key, DocId}, Value}),
- Chunk = RowFront ++ ?b2l(?l2b(Chunks)),
- send_non_empty_chunk(Resp, Chunk),
- case Go of
- <<"chunks">> ->
- {ok, ""};
- <<"end">> ->
- {stop, ""}
- end
- catch
- throw:Error ->
- send_chunked_error(Resp, Error),
- throw({already_sent, Resp, Error})
- end
- end.
-
-send_non_empty_chunk(Resp, Chunk) ->
- case Chunk of
- [] -> ok;
- _ -> send_chunk(Resp, Chunk)
- end.
output_map_list(#httpd{mochi_req=MReq}=Req, Lang, ListSrc, View, Group, Db, QueryArgs, nil) ->
#view_query_args{
@@ -178,7 +138,7 @@
{ok, QueryServer} = couch_query_servers:start_view_list(Lang, ListSrc),
StartListRespFun = make_map_start_resp_fun(QueryServer, Db),
- SendListRowFun = make_map_send_row_fun(QueryServer, Req),
+ SendListRowFun = make_map_send_row_fun(QueryServer),
FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, CurrentEtag, Db, RowCount,
#view_fold_helper_funs{
@@ -188,7 +148,7 @@
}),
FoldAccInit = {Limit, SkipCount, undefined, []},
{ok, FoldResult} = couch_view:fold(View, Start, Dir, FoldlFun, FoldAccInit),
- finish_list(Req, Db, QueryServer, CurrentEtag, FoldResult, StartListRespFun, RowCount)
+ finish_list(Req, QueryServer, CurrentEtag, FoldResult, StartListRespFun, RowCount)
end);
output_map_list(#httpd{mochi_req=MReq}=Req, Lang, ListSrc, View, Group, Db, QueryArgs, Keys) ->
@@ -209,7 +169,7 @@
{ok, QueryServer} = couch_query_servers:start_view_list(Lang, ListSrc),
StartListRespFun = make_map_start_resp_fun(QueryServer, Db),
- SendListRowFun = make_map_send_row_fun(QueryServer, Req),
+ SendListRowFun = make_map_send_row_fun(QueryServer),
FoldAccInit = {Limit, SkipCount, undefined, []},
{ok, FoldResult} = lists:foldl(
@@ -225,38 +185,64 @@
}),
couch_view:fold(View, {Key, StartDocId}, Dir, FoldlFun, FoldAcc)
end, {ok, FoldAccInit}, Keys),
- finish_list(Req, Db, QueryServer, CurrentEtag, FoldResult, StartListRespFun, RowCount)
+ finish_list(Req, QueryServer, CurrentEtag, FoldResult, StartListRespFun, RowCount)
end).
-make_reduce_start_resp_fun(QueryServer, Req, Db, CurrentEtag) ->
- fun(Req2, _Etag, _Acc) ->
- [<<"start">>,Chunks,JsonResp] = couch_query_servers:render_reduce_head(QueryServer,
- Req2, Db),
- JsonResp2 = apply_etag(JsonResp, CurrentEtag),
- #extern_resp_args{
- code = Code,
- ctype = CType,
- headers = ExtHeaders
- } = couch_httpd_external:parse_external_response(JsonResp2),
- JsonHeaders = couch_httpd_external:default_or_content_type(CType, ExtHeaders),
- {ok, Resp} = start_chunked_response(Req, Code, JsonHeaders),
- {ok, Resp, ?b2l(?l2b(Chunks))}
+make_map_start_resp_fun(QueryServer, Db) ->
+ fun(Req, Etag, TotalRows, Offset, _Acc) ->
+ Head = {[{<<"total_rows">>, TotalRows}, {<<"offset">>, Offset}]},
+ start_list_resp(QueryServer, Req, Db, Head, Etag)
+ end.
+
+make_reduce_start_resp_fun(QueryServer, _Req, Db, _CurrentEtag) ->
+ fun(Req2, Etag, _Acc) ->
+ start_list_resp(QueryServer, Req2, Db, {[]}, Etag)
end.
-make_reduce_send_row_fun(QueryServer, Req, Db) ->
- fun(Resp, {Key, Value}, RowFront) ->
- try
- [<<"chunks">>,Chunks] = couch_query_servers:render_reduce_row(QueryServer,
- Req, Db, {Key, Value}),
- ?LOG_ERROR("RowFront ~p",[RowFront]),
- Chunk = RowFront ++ ?b2l(?l2b(Chunks)),
- send_non_empty_chunk(Resp, Chunk),
- {ok, ""}
- catch
- throw:Error ->
- send_chunked_error(Resp, Error),
- throw({already_sent, Resp, Error})
+start_list_resp(QueryServer, Req, Db, Head, Etag) ->
+ [<<"start">>,Chunks,JsonResp] = couch_query_servers:render_list_head(QueryServer,
+ Req, Db, Head),
+ JsonResp2 = apply_etag(JsonResp, Etag),
+ #extern_resp_args{
+ code = Code,
+ ctype = CType,
+ headers = ExtHeaders
+ } = couch_httpd_external:parse_external_response(JsonResp2),
+ JsonHeaders = couch_httpd_external:default_or_content_type(CType, ExtHeaders),
+ {ok, Resp} = start_chunked_response(Req, Code, JsonHeaders),
+ {ok, Resp, ?b2l(?l2b(Chunks))}.
+
+make_map_send_row_fun(QueryServer) ->
+ fun(Resp, Db, Row, _IncludeDocs, RowFront) ->
+ send_list_row(Resp, QueryServer, Db, Row, RowFront)
+ end.
+
+make_reduce_send_row_fun(QueryServer, Db) ->
+ fun(Resp, Row, RowFront) ->
+ send_list_row(Resp, QueryServer, Db, Row, RowFront)
+ end.
+
+send_list_row(Resp, QueryServer, Db, Row, RowFront) ->
+ try
+ [Go,Chunks] = couch_query_servers:render_list_row(QueryServer, Db, Row),
+ Chunk = RowFront ++ ?b2l(?l2b(Chunks)),
+ send_non_empty_chunk(Resp, Chunk),
+ case Go of
+ <<"chunks">> ->
+ {ok, ""};
+ <<"end">> ->
+ {stop, stop}
end
+ catch
+ throw:Error ->
+ send_chunked_error(Resp, Error),
+ throw({already_sent, Resp, Error})
+ end.
+
+send_non_empty_chunk(Resp, Chunk) ->
+ case Chunk of
+ [] -> ok;
+ _ -> send_chunk(Resp, Chunk)
end.
output_reduce_list(#httpd{mochi_req=MReq}=Req, Lang, ListSrc, View, Group, Db, QueryArgs, nil) ->
@@ -279,7 +265,7 @@
CurrentEtag = couch_httpd_view:view_group_etag(Group, {Lang, ListSrc, Accept}),
couch_httpd:etag_respond(Req, CurrentEtag, fun() ->
StartListRespFun = make_reduce_start_resp_fun(QueryServer, Req, Db, CurrentEtag),
- SendListRowFun = make_reduce_send_row_fun(QueryServer, Req, Db),
+ SendListRowFun = make_reduce_send_row_fun(QueryServer, Db),
{ok, GroupRowsFun, RespFun} = couch_httpd_view:make_reduce_fold_funs(Req,
GroupLevel, QueryArgs, CurrentEtag,
@@ -291,7 +277,7 @@
{ok, FoldResult} = couch_view:fold_reduce(View, Dir, {StartKey, StartDocId},
{EndKey, EndDocId}, GroupRowsFun, RespFun,
FoldAccInit),
- finish_list(Req, Db, QueryServer, CurrentEtag, FoldResult, StartListRespFun, null)
+ finish_list(Req, QueryServer, CurrentEtag, FoldResult, StartListRespFun, null)
end);
output_reduce_list(#httpd{mochi_req=MReq}=Req, Lang, ListSrc, View, Group, Db, QueryArgs, Keys) ->
@@ -313,7 +299,7 @@
couch_httpd:etag_respond(Req, CurrentEtag, fun() ->
StartListRespFun = make_reduce_start_resp_fun(QueryServer, Req, Db, CurrentEtag),
- SendListRowFun = make_reduce_send_row_fun(QueryServer, Req, Db),
+ SendListRowFun = make_reduce_send_row_fun(QueryServer, Db),
{ok, GroupRowsFun, RespFun} = couch_httpd_view:make_reduce_fold_funs(Req,
GroupLevel, QueryArgs, CurrentEtag,
@@ -327,22 +313,22 @@
couch_view:fold_reduce(View, Dir, {Key, StartDocId},
{Key, EndDocId}, GroupRowsFun, RespFun, FoldAcc)
end, {ok, FoldAccInit}, Keys),
- finish_list(Req, Db, QueryServer, CurrentEtag, FoldResult, StartListRespFun, null)
+ finish_list(Req, QueryServer, CurrentEtag, FoldResult, StartListRespFun, null)
end).
-finish_list(Req, Db, QueryServer, Etag, FoldResult, StartListRespFun, TotalRows) ->
- {Resp, BeginBody} = case FoldResult of
+finish_list(Req, QueryServer, Etag, FoldResult, StartFun, TotalRows) ->
+ case FoldResult of
{_, _, undefined, _} ->
- {ok, Resp2, BeginBody2} = render_head_for_empty_list(StartListRespFun, Req, Etag, TotalRows),
- {Resp2, BeginBody2};
- {_, _, Resp0, _} ->
- {Resp0, ""}
- end,
- [<<"end">>, Chunks] = couch_query_servers:render_list_tail(QueryServer),
- Chunk = BeginBody ++ ?b2l(?l2b(Chunks)),
- case Chunk of
- [] -> ok;
- _ -> send_chunk(Resp, Chunk)
+ {ok, Resp, BeginBody} =
+ render_head_for_empty_list(StartFun, Req, Etag, TotalRows),
+ [<<"end">>, Chunks] = couch_query_servers:render_list_tail(QueryServer),
+ Chunk = BeginBody ++ ?b2l(?l2b(Chunks)),
+ send_non_empty_chunk(Resp, Chunk);
+ {_, _, Resp, stop} ->
+ ok;
+ {_, _, Resp, _} ->
+ [<<"end">>, Chunks] = couch_query_servers:render_list_tail(QueryServer),
+ send_non_empty_chunk(Resp, ?b2l(?l2b(Chunks)))
end,
send_chunk(Resp, []).
Modified: couchdb/branches/list-iterator/src/couchdb/couch_os_process.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/list-iterator/src/couchdb/couch_os_process.erl?rev=782429&r1=782428&r2=782429&view=diff
==============================================================================
--- couchdb/branches/list-iterator/src/couchdb/couch_os_process.erl (original)
+++ couchdb/branches/list-iterator/src/couchdb/couch_os_process.erl Sun Jun 7 19:03:05 2009
@@ -49,7 +49,7 @@
{ok, Result} ->
Result;
Error ->
- ?LOG_DEBUG("OS Process Error ~p",[Error]),
+ ?LOG_ERROR("OS Process Error :: ~p",[Error]),
throw(Error)
end.
@@ -77,6 +77,7 @@
% Standard JSON functions
writejson(OsProc, Data) when is_record(OsProc, os_proc) ->
+ % ?LOG_INFO("OS Process Input :: ~p", [Data]),
true = writeline(OsProc, ?JSON_ENCODE(Data)).
readjson(OsProc) when is_record(OsProc, os_proc) ->
@@ -91,6 +92,7 @@
{[{<<"reason">>, Reason}, {<<"error">>, Id}]} ->
throw({list_to_atom(binary_to_list(Id)),Reason});
Result ->
+ % ?LOG_INFO("OS Process Output :: ~p", [Result]),
Result
end.
Modified: couchdb/branches/list-iterator/src/couchdb/couch_query_servers.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/list-iterator/src/couchdb/couch_query_servers.erl?rev=782429&r1=782428&r2=782429&view=diff
==============================================================================
--- couchdb/branches/list-iterator/src/couchdb/couch_query_servers.erl (original)
+++ couchdb/branches/list-iterator/src/couchdb/couch_query_servers.erl Sun Jun 7 19:03:05 2009
@@ -18,9 +18,8 @@
-export([init/1, terminate/2, handle_call/3, handle_cast/2, handle_info/2,code_change/3,stop/0]).
-export([start_doc_map/2, map_docs/2, stop_doc_map/1]).
-export([reduce/3, rereduce/3,validate_doc_update/5]).
--export([render_doc_show/6,start_view_list/2,render_list_head/5,
- render_list_row/4, render_list_tail/1, render_reduce_head/3,
- render_reduce_row/4]).
+-export([render_doc_show/6, start_view_list/2,
+ render_list_head/4, render_list_row/3, render_list_tail/1]).
% -export([test/0]).
-include("couch_db.hrl").
@@ -195,30 +194,24 @@
true = couch_os_process:prompt(Pid, [<<"add_fun">>, ListSrc]),
{ok, {Lang, Pid}}.
-render_list_head({_Lang, Pid}, Req, Db, TotalRows, Offset) ->
- Head = {[{<<"total_rows">>, TotalRows}, {<<"offset">>, Offset}]},
+render_list_head({_Lang, Pid}, Req, Db, Head) ->
JsonReq = couch_httpd_external:json_req_obj(Req, Db),
couch_os_process:prompt(Pid, [<<"list">>, Head, JsonReq]).
-render_list_row({_Lang, Pid}, Req, Db, {{Key, DocId}, Value}) ->
+render_list_row({_Lang, Pid}, Db, {{Key, DocId}, Value}) ->
JsonRow = couch_httpd_view:view_row_obj(Db, {{Key, DocId}, Value}, false),
- JsonReq = couch_httpd_external:json_req_obj(Req, Db),
- couch_os_process:prompt(Pid, [<<"list_row">>, JsonRow, JsonReq]).
+ couch_os_process:prompt(Pid, [<<"list_row">>, JsonRow]);
+
+render_list_row({_Lang, Pid}, _, {Key, Value}) ->
+ JsonRow = {[{key, Key}, {value, Value}]},
+ couch_os_process:prompt(Pid, [<<"list_row">>, JsonRow]).
render_list_tail({Lang, Pid}) ->
JsonResp = couch_os_process:prompt(Pid, [<<"list_end">>]),
ok = ret_os_process(Lang, Pid),
JsonResp.
-render_reduce_head({_Lang, Pid}, Req, Db) ->
- Head = {[]},
- JsonReq = couch_httpd_external:json_req_obj(Req, Db),
- couch_os_process:prompt(Pid, [<<"list">>, Head, JsonReq]).
-render_reduce_row({_Lang, Pid}, Req, Db, {Key, Value}) ->
- JsonRow = {[{key, Key}, {value, Value}]},
- JsonReq = couch_httpd_external:json_req_obj(Req, Db),
- couch_os_process:prompt(Pid, [<<"list_row">>, JsonRow, JsonReq]).
init([]) ->