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([]) ->