couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j..@apache.org
Subject svn commit: r659773 - in /incubator/couchdb/branches/runtimeconfig: ./ bin/ etc/couchdb/ share/server/ share/www/browse/ share/www/script/ share/www/style/ src/couchdb/ src/mochiweb/
Date Sat, 24 May 2008 08:38:05 GMT
Author: jan
Date: Sat May 24 01:38:04 2008
New Revision: 659773

URL: http://svn.apache.org/viewvc?rev=659773&view=rev
Log:
Merged revisions 657606,657926,657930,657963-657964,658405,658408-658409,659244,659501,659505,659522,659529,659537,659589,659596,659636,659676,659681,659685,659690,659699,659714,659717,659722 via svnmerge from 
https://jan@svn.apache.org/repos/asf/incubator/couchdb/trunk


Added:
    incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochifmt.erl
      - copied unchanged from r659722, incubator/couchdb/trunk/src/mochiweb/mochifmt.erl
    incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochifmt_records.erl
      - copied unchanged from r659722, incubator/couchdb/trunk/src/mochiweb/mochifmt_records.erl
    incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochifmt_std.erl
      - copied unchanged from r659722, incubator/couchdb/trunk/src/mochiweb/mochifmt_std.erl
Modified:
    incubator/couchdb/branches/runtimeconfig/   (props changed)
    incubator/couchdb/branches/runtimeconfig/README
    incubator/couchdb/branches/runtimeconfig/bin/couchdb.tpl.in
    incubator/couchdb/branches/runtimeconfig/configure.ac
    incubator/couchdb/branches/runtimeconfig/etc/couchdb/couch.ini.tpl.in
    incubator/couchdb/branches/runtimeconfig/share/server/main.js
    incubator/couchdb/branches/runtimeconfig/share/www/browse/database.html
    incubator/couchdb/branches/runtimeconfig/share/www/script/browse.js
    incubator/couchdb/branches/runtimeconfig/share/www/script/couch.js
    incubator/couchdb/branches/runtimeconfig/share/www/script/couch_tests.js
    incubator/couchdb/branches/runtimeconfig/share/www/script/jquery.couch.js
    incubator/couchdb/branches/runtimeconfig/share/www/script/jquery.resizer.js
    incubator/couchdb/branches/runtimeconfig/share/www/style/layout.css
    incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_btree.erl
    incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_db.erl
    incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_doc.erl
    incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_httpd.erl
    incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_view.erl
    incubator/couchdb/branches/runtimeconfig/src/mochiweb/Makefile.am
    incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb.erl
    incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_headers.erl
    incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_html.erl
    incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_multipart.erl
    incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_request.erl
    incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_socket_server.erl
    incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_util.erl

Propchange: incubator/couchdb/branches/runtimeconfig/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Sat May 24 01:38:04 2008
@@ -1 +1 @@
-/incubator/couchdb/trunk:1-657553
+/incubator/couchdb/trunk:1-659771

Modified: incubator/couchdb/branches/runtimeconfig/README
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/README?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/README (original)
+++ incubator/couchdb/branches/runtimeconfig/README Sat May 24 01:38:04 2008
@@ -45,7 +45,7 @@
 
 You will need the following installed:
 
- * [Erlang OTP][09] (>=R12B) (required)
+ * [Erlang OTP][09] (>=R11B) (required)
  * [ICU][10] (required)
  * [Mozilla SpiderMonkey][11] (required)
  * [GNU Make][12] (required)

Modified: incubator/couchdb/branches/runtimeconfig/bin/couchdb.tpl.in
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/bin/couchdb.tpl.in?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/bin/couchdb.tpl.in (original)
+++ incubator/couchdb/branches/runtimeconfig/bin/couchdb.tpl.in Sat May 24 01:38:04 2008
@@ -66,6 +66,8 @@
 
 The $basename command runs the %package_name% server.
 
+Erlang inherits the environment of this command.
+
 The exit status is 0 for success or 1 for failure.
 
 The \`-s' option will exit 0 for running and 1 for not running.
@@ -117,11 +119,6 @@
     if test -f $PID_FILE; then
         PID=$(cat $PID_FILE)
     fi
-    if test -z "$PID"; then
-        # Resort to searching for the running process manually.
-        PID=$(ps auxww | grep erlang | grep -- "couch_server:start()" | \
-            grep -v grep | awk "{print \$2}")
-    fi
     echo $PID
 }
 
@@ -224,9 +221,9 @@
     ini_file_list="[\\\"$INI_FILE\\\"]"
 
     command="`%ICU_CONFIG% --invoke` \
-        %ERL% $interactive_option -sasl errlog_type error \
+        %ERL% $interactive_option -smp auto -sasl errlog_type error \
         -pa %erlanglibdir%/couch-%version%/ebin \
-            %erlanglibdir%/mochiweb-r64/ebin \
+            %erlanglibdir%/mochiweb-r73/ebin \
         -eval \"application:load(inets)\" \
         -eval \"application:load(crypto)\" \
         -eval \"application:load(couch)\" \

Modified: incubator/couchdb/branches/runtimeconfig/configure.ac
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/configure.ac?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/configure.ac (original)
+++ incubator/couchdb/branches/runtimeconfig/configure.ac Sat May 24 01:38:04 2008
@@ -104,6 +104,10 @@
     AC_MSG_ERROR([Could not find the `erl' executable. Is Erlang installed?])
 fi
 
+if test $(${ERL} -version 2>&1 | sed "s/[[^0-9]]//g") -le 550; then
+    AC_MSG_ERROR([The installed Erlang version is less than 5.5.0 (R11B).])
+fi
+
 AC_PATH_PROG([ERLC], [erlc])
 
 if test x${ERLC} = x; then

Modified: incubator/couchdb/branches/runtimeconfig/etc/couchdb/couch.ini.tpl.in
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/etc/couchdb/couch.ini.tpl.in?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/etc/couchdb/couch.ini.tpl.in (original)
+++ incubator/couchdb/branches/runtimeconfig/etc/couchdb/couch.ini.tpl.in Sat May 24 01:38:04 2008
@@ -14,5 +14,4 @@
 Level=info
 
 [CouchDB Query Servers]
-text/javascript=%bindir%/%couchjs_command_name% %pkgdatadir%/server/main.js
-
+javascript=%bindir%/%couchjs_command_name% %pkgdatadir%/server/main.js

Modified: incubator/couchdb/branches/runtimeconfig/share/server/main.js
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/share/server/main.js?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/share/server/main.js [utf-8] (original)
+++ incubator/couchdb/branches/runtimeconfig/share/server/main.js [utf-8] Sat May 24 01:38:04 2008
@@ -16,23 +16,22 @@
 
 var sandbox = null;
 
-map = function(key, value) {
-    map_results.push([key, value]);
-  }
-  
+emit = function(key, value) {
+  map_results.push([key, value]);
+}
+
 sum = function(values) {
-    var values_sum=0;
-    for(var i in values) {
-      values_sum += values[i];
-    }
-    return values_sum;
+  var rv = 0;
+  for (var i in values) {
+    rv += values[i];
   }
-
+  return rv;
+}
 
 try {
   // if possible, use evalcx (not always available)
   sandbox = evalcx('');
-  sandbox.map = map;
+  sandbox.emit = emit;
   sandbox.sum = sum;
 } catch (e) {}
 
@@ -53,8 +52,8 @@
       case "add_fun":
         // The second arg is a string that will compile to a function.
         // and then we add it to funs array
-          funs.push(safe_compile_function(cmd[1]));
-          print("true");
+        funs.push(compileFunction(cmd[1]));
+        print("true");
         break;
       case "map_doc":
         // The second arg is a document. We compute all the map functions against
@@ -97,19 +96,20 @@
         }
         print(toJSON(buf));
         break;
-      
+
       case "combine":
       case "reduce":
-        {  
+        {
         var keys = null;
         var values = null;
         var reduceFuns = cmd[1];
         var is_combine = false;
+        
         if (cmd[0] == "reduce") {
           var kvs = cmd[2];
           keys = new Array(kvs.length);
           values = new Array(kvs.length);
-          for (var i = 0; i < kvs.length; i++) {
+          for(var i = 0; i < kvs.length; i++) {
               keys[i] = kvs[i][0];
               values[i] = kvs[i][1];
           }
@@ -117,13 +117,13 @@
           values = cmd[2];
           is_combine = true;
         }
-        
-        for(var i in reduceFuns) {
-          reduceFuns[i] = safe_compile_function(reduceFuns[i]);
+
+        for (var i in reduceFuns) {
+          reduceFuns[i] = compileFunction(reduceFuns[i]);
         }
-        
+
         var reductions = new Array(funs.length);
-        for (var i = 0; i < reduceFuns.length; i++) {
+        for(var i = 0; i < reduceFuns.length; i++) {
           try {
             reductions[i] = reduceFuns[i](keys, values, is_combine);
           } catch (err) {
@@ -138,30 +138,30 @@
         print("[true," + toJSON(reductions) + "]");
         }
         break;
-     
+
       default:
         print(toJSON({error: "query_server_error",
             reason: "unknown command '" + cmd[0] + "'"}));
         quit();
     }
-  } catch(exception) {
+  } catch (exception) {
     print(toJSON(exception));
   }
 }
 
 
-function safe_compile_function(Src) {
+function compileFunction(source) {
   try {
-    var functionObject = sandbox ? evalcx(Src, sandbox) : eval(Src);
+    var functionObject = sandbox ? evalcx(source, sandbox) : eval(source);
   } catch (err) {
     throw {error: "compilation_error",
-      reason: err.toString() + " (" + Src + ")"};
+      reason: err.toString() + " (" + source + ")"};
   }
   if (typeof(functionObject) == "function") {
     return functionObject;
   } else {
     throw {error: "compilation_error",
-      reason: "expression does not eval to a function. (" + Src + ")"};
+      reason: "expression does not eval to a function. (" + source + ")"};
   }
 }
 

Modified: incubator/couchdb/branches/runtimeconfig/share/www/browse/database.html
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/share/www/browse/database.html?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/share/www/browse/database.html [utf-8] (original)
+++ incubator/couchdb/branches/runtimeconfig/share/www/browse/database.html [utf-8] Sat May 24 01:38:04 2008
@@ -36,7 +36,7 @@
 
       $(document).ready(function() {
         $("h1 strong").text(page.db.name);
-        $("#viewcode label").click(function() {
+        $("#viewcode span").click(function() {
           $("#viewcode").toggleClass("expanded");
         });
         $("#viewcode button.run").click(function() {
@@ -51,11 +51,14 @@
         $("#viewcode button.saveas").click(function() {
           page.saveViewAs();
         });
-        $("#viewcode textarea").resizable({grippie: $("#viewcode .bottom")});
+        $("#viewcode textarea").resizable({
+          always: true,
+          grippie: $("#viewcode .bottom")
+        });
 
         // Restore preferences/state from cookies
         var query = $.cookies.get(page.db.name + ".query");
-        if (query) $("#viewcode textarea").val(query);
+        if (query) $("#viewcode_map").val(query);
         var desc = $.cookies.get(page.db.name + ".desc");
         if (desc) $("#documents thead th.key").addClass("desc");
         var rowsPerPage = $.cookies.get(page.db.name + ".perpage");
@@ -108,11 +111,18 @@
       <div id="viewcode" style="display: none">
         <div class="top">
           <a id="designdoc-link"></a>
-          <label for="viewcode_textarea">View Function</label>
+          <span id="view-toggle">View Code</span>
         </div>
-        <textarea id="viewcode_textarea" rows="5" cols="79" spellcheck="false" wrap="off">function(doc) {
-  map(null, doc);
+        <div class="code map">
+          <label for="viewcode_map">Map Function:</label>
+          <textarea id="viewcode_map" class="map" rows="5" cols="79" spellcheck="false" wrap="off">function(doc) {
+  emit(null, doc);
 }</textarea>
+        </div>
+        <div class="code reduce">
+          <label for="viewcode_reduce">Reduce Function (optional):</label>
+          <textarea id="viewcode_reduce" class="reduce" rows="5" cols="79" spellcheck="false" wrap="off"></textarea>
+        </div>
         <div class="bottom">
           <button class="save" type="button" disabled>Save</button>
           <button class="saveas" type="button">Save As…</button>

Modified: incubator/couchdb/branches/runtimeconfig/share/www/script/browse.js
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/share/www/script/browse.js?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/share/www/script/browse.js [utf-8] (original)
+++ incubator/couchdb/branches/runtimeconfig/share/www/script/browse.js [utf-8] Sat May 24 01:38:04 2008
@@ -145,7 +145,8 @@
           clearTimeout(dirtyTimeout);
           dirtyTimeout = setTimeout(function() {
             var buttons = $("#viewcode button.save, #viewcode button.revert");
-            page.isDirty = $("#viewcode textarea").val() != page.storedViewCode;
+            page.isDirty = ($("#viewcode_map").val() != page.storedViewCode.map)
+              || ($("#viewcode_reduce").val() != page.storedViewCode.reduce);
             if (page.isDirty) {
               buttons.removeAttr("disabled");
             } else {
@@ -214,13 +215,15 @@
         },
         success: function(resp) {
           page.storedViewCode = resp.views[localViewName];
-          $("#viewcode textarea").val(page.storedViewCode);
+          $("#viewcode_map").val(page.storedViewCode.map);
+          $("#viewcode_reduce").val(page.storedViewCode.reduce || "");
           $("#viewcode button.revert, #viewcode button.save").attr("disabled", "disabled");
           if (callback) callback();
         }
       });
     } else {
-      $("#viewcode textarea").val(page.storedViewCode);
+      $("#viewcode_map").val(page.storedViewCode.map);
+      $("#viewcode_reduce").val(page.storedViewCode.reduce || "");
       page.isDirty = false;
       $("#viewcode button.revert, #viewcode button.save").attr("disabled", "disabled");
       if (callback) callback();
@@ -274,10 +277,13 @@
           if (!data.name) errors.name = "Please enter a view name";
           callback(errors);
         } else {
-          var viewCode = $("#viewcode textarea").val();
+          var viewCode = {
+            map: $("#viewcode_map").val(),
+            reduce: $("#viewcode_reduce").val() || undefined
+          };
           var docId = ["_design", data.docid].join("/");
           function save(doc) {
-            if (!doc) doc = {_id: docId, language: "text/javascript"};
+            if (!doc) doc = {_id: docId, language: "javascript"};
             if (doc.views === undefined) doc.views = {};
             doc.views[data.name] = viewCode;
             db.saveDoc(doc, {
@@ -311,7 +317,9 @@
     $(document.body).addClass("loading");
     db.openDoc(["_design", designDocId].join("/"), {
       success: function(doc) {
-        doc.views[localViewName] = $("#viewcode textarea").val();
+        var viewDef = doc.views[localViewName];
+        viewDef.map = $("#viewcode_map").val();
+        viewDef.reduce = $("#viewcode_reduce").val() || undefined;
         db.saveDoc(doc, {
           success: function(resp) {
             page.isDirty = false;
@@ -351,11 +359,11 @@
     $("#documents tbody.content").empty();
     this.updateDesignDocLink();
 
-    function handleResults(resp) {
+    options.success = function(resp) {
       if (resp.offset === undefined) {
         resp.offset = 0;
       }
-      if (resp.offset > 0) {
+      if (resp.total_rows !== null && resp.offset > 0) {
         $("#paging a.prev").attr("href", "#" + (resp.offset - options.count)).click(function() {
           var firstDoc = resp.rows[0];
           page.updateDocumentListing({
@@ -369,7 +377,7 @@
       } else {
         $("#paging a.prev").removeAttr("href");
       }
-      if (resp.total_rows - resp.offset > options.count) {
+      if (resp.total_rows !== null && resp.total_rows - resp.offset > options.count) {
         $("#paging a.next").attr("href", "#" + (resp.offset + options.count)).click(function() {
           var lastDoc = resp.rows[resp.rows.length - 1];
           page.updateDocumentListing({
@@ -384,34 +392,45 @@
         $("#paging a.next").removeAttr("href");
       }
 
-      for (var i = 0; i < resp.rows.length; i++) {
-        var row = resp.rows[i];
+      if (resp.total_rows != null) {
+        for (var i = 0; i < resp.rows.length; i++) {
+          var row = resp.rows[i];
+          var tr = $("<tr></tr>");
+          var key = row.key;
+          $("<td class='key'><a href='document.html?" + encodeURIComponent(db.name) +
+            "/" + encodeURIComponent(row.id) + "'><em></em><br>" +
+            "<span class='docid'>ID:&nbsp;" + row.id + "</span></a></td>")
+            .find("em").text(key !== null ? prettyPrintJSON(key, 0, "") : "null").end()
+            .appendTo(tr);
+          var value = row.value;
+          $("<td class='value'></td>").text(
+            value !== null ? prettyPrintJSON(value, 0, "") : "null"
+          ).appendTo(tr).dblclick(function() {
+            location.href = this.previousSibling.firstChild.href;
+          });
+          tr.appendTo("#documents tbody.content");
+        }
+        $("#documents tbody.footer td span").text(
+          "Showing " + Math.min(resp.total_rows, resp.offset + 1) + "-" +
+          (resp.offset + resp.rows.length) + " of " + resp.total_rows +
+          " document" + (resp.total_rows != 1 ? "s" : ""));
+        $("#documents").removeClass("reduced");
+      } else {
         var tr = $("<tr></tr>");
-        var key = row.key;
-        $("<td class='key'><a href='document.html?" + encodeURIComponent(db.name) +
-          "/" + encodeURIComponent(row.id) + "'><em></em><br>" +
-          "<span class='docid'>ID:&nbsp;" + row.id + "</span></a></td>")
-          .find("em").text(key !== null ? prettyPrintJSON(key, 0, "") : "null").end()
-          .appendTo(tr);
-        var value = row.value;
+        $("<td class='key'></td>").appendTo(tr);
         $("<td class='value'></td>").text(
-          value !== null ? prettyPrintJSON(value, 0, "") : "null"
-        ).appendTo(tr).dblclick(function() {
-          location.href = this.previousSibling.firstChild.href;
-        });
+          resp.result !== null ? prettyPrintJSON(resp.result) : "null"
+        ).appendTo(tr);
         tr.appendTo("#documents tbody.content");
+        $("#documents tbody.footer td span").text("Showing reduce result");
+        $("#documents").addClass("reduced");
       }
-
       $("#documents tbody tr:odd").addClass("odd");
-      $("#documents tbody.footer td span").text(
-        "Showing " + Math.min(resp.total_rows, resp.offset + 1) + "-" +
-        (resp.offset + resp.rows.length) + " of " + resp.total_rows +
-        " document" + (resp.total_rows != 1 ? "s" : ""));
       $(document.body).removeClass("loading");
     }
-    options.success = handleResults;
-    options.error = function(error, reason) {
-      alert(reason);
+    options.error = function(status, error, reason) {
+      alert("Error: " + error + "\n\n" + reason);
+      $(document.body).removeClass("loading");
     }
 
     if (!viewName) {
@@ -420,18 +439,25 @@
     } else {
       if (viewName == "_temp_view") {
         $("#viewcode").show().addClass("expanded");
-        var query = $("#viewcode textarea").val();
-        $.cookies.set(db.name + ".query", query);
-        db.query(query, options);
+        var mapFun = $("#viewcode_map").val();
+        $.cookies.set(db.name + ".map", mapFun);
+        var reduceFun = $("#viewcode_reduce").val() || null;
+        if (reduceFun != null) {
+          $.cookies.set(db.name + ".reduce", reduceFun);
+        } else {
+          $.cookies.remove(db.name + ".reduce");
+        }
+        db.query(mapFun, reduceFun, null, options);
       } else if (viewName == "_design_docs") {
         options.startkey = options.descending ? "_design/ZZZZ" : "_design/";
         options.endkey = options.descending ? "_design/" : "_design/ZZZZ";
         db.allDocs(options);
       } else {
         $("#viewcode").show();
-        var currentViewCode = $("#viewcode textarea").val();
+        var currentMapCode = $("#viewcode_map").val();
+        var currentReduceCode = $("#viewcode_reduce").val() || null;
         if (page.isDirty) {
-          db.query(currentViewCode, options);
+          db.query(currentMapCode, currentReduceCode, null, options);
         } else {
           db.view(viewName.substr(8), options);
         }

Modified: incubator/couchdb/branches/runtimeconfig/share/www/script/couch.js
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/share/www/script/couch.js?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/share/www/script/couch.js [utf-8] (original)
+++ incubator/couchdb/branches/runtimeconfig/share/www/script/couch.js [utf-8] Sat May 24 01:38:04 2008
@@ -94,28 +94,19 @@
   }
 
   // Applies the map function to the contents of database and returns the results.
-  this.query = function(mapFun, options) {
+  this.query = function(mapFun, reduceFun, options) {
+    var body = {language: "javascript"};
     if (typeof(mapFun) != "string")
       mapFun = mapFun.toSource ? mapFun.toSource() : "(" + mapFun.toString() + ")";
+    body.map = mapFun;
+    if (reduceFun != null) {
+      if (typeof(reduceFun) != "string")
+        reduceFun = reduceFun.toSource ? reduceFun.toSource() : "(" + reduceFun.toString() + ")";
+      body.reduce = reduceFun;
+    }
     var req = request("POST", this.uri + "_temp_view" + encodeOptions(options), {
-      headers: {"Content-Type": "text/javascript"},
-      body: JSON.stringify(mapFun)
-    });
-    var result = JSON.parse(req.responseText);
-    if (req.status != 200)
-      throw result;
-    return result;
-  }
-  
-  // Applies the map function to the contents of database and returns the results.
-  this.reduce_query = function(mapFun, reduceFun, options) {
-    if (typeof(mapFun) != "string")
-      mapFun = mapFun.toSource ? mapFun.toSource() : "(" + mapFun.toString() + ")";
-    if (typeof(reduceFun) != "string")
-      reduceFun = reduceFun.toSource ? reduceFun.toSource() : "(" + reduceFun.toString() + ")";
-    var req = request("POST", this.uri + "_temp_view" + encodeOptions(options), {
-      headers: {"Content-Type": "text/javascript"},
-      body: JSON.stringify({map:mapFun, reduce:reduceFun})
+      headers: {"Content-Type": "application/json"},
+      body: JSON.stringify(body)
     });
     var result = JSON.parse(req.responseText);
     if (req.status != 200)
@@ -149,7 +140,7 @@
       throw result;
     return result;
   }
-  
+
   this.compact = function() {
     var req = request("POST", this.uri + "_compact");
     var result = JSON.parse(req.responseText);

Modified: incubator/couchdb/branches/runtimeconfig/share/www/script/couch_tests.js
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/share/www/script/couch_tests.js?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/share/www/script/couch_tests.js [utf-8] (original)
+++ incubator/couchdb/branches/runtimeconfig/share/www/script/couch_tests.js [utf-8] Sat May 24 01:38:04 2008
@@ -59,7 +59,7 @@
     // has a value of 4, and then returns the document's b value.
     var mapFunction = function(doc){
       if(doc.a==4)
-        map(null, doc.b);
+        emit(null, doc.b);
     };
 
     results = db.query(mapFunction);
@@ -91,15 +91,15 @@
     // 1 more document should now be in the result.
     T(results.total_rows == 3);
     T(db.info().doc_count == 6);
-    
+
     var reduceFunction = function(keys, values){
         return sum(values);
     };
-    
-    result = db.reduce_query(mapFunction, reduceFunction);
+
+    result = db.query(mapFunction, reduceFunction);
 
     T(result.result == 33);
-      
+
    // delete a document
     T(db.deleteDoc(existingDoc).ok);
 
@@ -208,7 +208,7 @@
     }
 
     // query all documents, and return the doc.integer member as a key.
-    results = db.query(function(doc){ map(doc.integer, null) });
+    results = db.query(function(doc){ emit(doc.integer, null) });
 
     T(results.total_rows == numDocsToCreate);
 
@@ -218,7 +218,9 @@
     }
 
     // do the query again, but with descending output
-    results = db.query(function(doc){ map(doc.integer, null) }, {descending:true});
+    results = db.query(function(doc){ emit(doc.integer, null) }, null, {
+      descending: true
+    });
 
     T(results.total_rows == numDocsToCreate);
 
@@ -227,7 +229,7 @@
       T(results.rows[numDocsToCreate-1-i].key==i);
     }
   },
-  
+
   reduce: function(debug) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
@@ -237,26 +239,23 @@
     var docs = makeDocs(1,numDocs + 1);
     T(db.bulkSave(docs).ok);
     var summate = function(N) {return (N+1)*N/2;};
-    
-    var map = function (doc) {map(doc.integer, doc.integer)};
-    var reduce = function (keys, values) { return sum(values); }; 
-    var result = db.reduce_query(map, reduce).result;
+
+    var map = function (doc) {emit(doc.integer, doc.integer)};
+    var reduce = function (keys, values) { return sum(values); };
+    var result = db.query(map, reduce).result;
     T(result == summate(numDocs));
-    
-    result = db.reduce_query(map, reduce, {startkey:4,endkey:4}).result;
-    
+
+    result = db.query(map, reduce, {startkey: 4, endkey: 4}).result;
     T(result == 4);
-    
-    result = db.reduce_query(map, reduce, {startkey:4,endkey:5}).result;
-    
+
+    result = db.query(map, reduce, {startkey: 4, endkey: 5}).result;
     T(result == 9);
-    
-    result = db.reduce_query(map, reduce, {startkey:4,endkey:6}).result;
-    
+
+    result = db.query(map, reduce, {startkey: 4, endkey: 6}).result;
     T(result == 15);
-    
+
     for(var i=1; i<numDocs/2; i+=30) {
-      result = db.reduce_query(map, reduce, {startkey:i,endkey:numDocs-i}).result;
+      result = db.query(map, reduce, {startkey: i, endkey: numDocs - i}).result;
       T(result == summate(numDocs-i) - summate(i-1));
     }
   },
@@ -277,7 +276,7 @@
 
     var generateListOfCitiesAndState = "function(doc) {" +
     " for (var i = 0; i < doc.cities.length; i++)" +
-    "  map(doc.cities[i] + \", \" + doc._id, null);" +
+    "  emit(doc.cities[i] + \", \" + doc._id, null);" +
     "}";
 
     var results = db.query(generateListOfCitiesAndState);
@@ -348,7 +347,7 @@
 
     // query all documents, and return the doc.foo member as a key.
     results = db.query(function(doc){
-        map(null, doc.longtest);
+        emit(null, doc.longtest);
     });
   },
 
@@ -376,7 +375,7 @@
     }
 
     // check that views and key collation don't blow up
-    var rows = db.query(function(doc) { map(null, doc.text) }).rows;
+    var rows = db.query(function(doc) { emit(null, doc.text) }).rows;
     for (var i=0; i<texts.length; i++) {
       T(rows[i].value == texts[i]);
     }
@@ -436,13 +435,15 @@
 
     var designDoc = {
       _id:"_design/test",
-      language: "text/javascript",
+      language: "javascript",
       views: {
-        all_docs: "function(doc) { map(doc.integer, null) }",
-        no_docs: "function(doc) {}",
-        single_doc: "function(doc) { if (doc._id == \"1\") { map(1, null) }}",
-        summate: {map:"function (doc) {map(doc.integer, doc.integer)};",
-                        reduce:"function (keys, values) { return sum(values); };"}
+        all_docs: {map: "function(doc) { emit(doc.integer, null) }"},
+        no_docs: {map: "function(doc) {}"},
+        single_doc: {map: "function(doc) { if (doc._id == \"1\") { emit(1, null) }}"},
+        summate: {map:"function (doc) {emit(doc.integer, doc.integer)};",
+                  reduce:"function (keys, values) { return sum(values); };"},
+        summate2: {map:"function (doc) {emit(doc.integer, doc.integer)};",
+                  reduce:"function (keys, values) { return sum(values); };"}
       }
     }
     T(db.save(designDoc).ok);
@@ -458,24 +459,26 @@
       T(db.view("test/single_doc").total_rows == 1)
       restartServer();
     }
-    
-    
+
+
     var summate = function(N) {return (N+1)*N/2;};
     var result = db.view("test/summate").result;
     T(result == summate(numDocs));
-    
+
     result = db.view("test/summate", {startkey:4,endkey:4}).result;
-    
     T(result == 4);
-    
+
     result = db.view("test/summate", {startkey:4,endkey:5}).result;
-    
     T(result == 9);
-    
-    result =db.view("test/summate", {startkey:4,endkey:6}).result;
-    
+
+    result = db.view("test/summate", {startkey:4,endkey:6}).result;
     T(result == 15);
-    
+
+    // Verify that a shared index (view def is an exact copy of "summate")
+    // does not confuse the reduce stage
+    result = db.view("test/summate2", {startkey:4,endkey:6}).result;
+    T(result == 15);
+
     for(var i=1; i<numDocs/2; i+=30) {
       result = db.view("test/summate", {startkey:i,endkey:numDocs-i}).result;
       T(result == summate(numDocs-i) - summate(i-1));
@@ -488,7 +491,7 @@
     restartServer();
     T(db.open(designDoc._id) == null);
     T(db.view("test/no_docs") == null);
-    
+
   },
 
   view_collation: function(debug) {
@@ -548,14 +551,14 @@
       db.save({_id:(i).toString(), foo:values[i]});
     }
 
-    var queryFun = function(doc) { map(doc.foo, null); }
+    var queryFun = function(doc) { emit(doc.foo, null); }
     var rows = db.query(queryFun).rows;
     for (i=0; i<values.length; i++) {
       T(equals(rows[i].key, values[i]))
     }
 
     // everything has collated correctly. Now to check the descending output
-    rows = db.query(queryFun, {descending:true}).rows
+    rows = db.query(queryFun, null, {descending: true}).rows
     for (i=0; i<values.length; i++) {
       T(equals(rows[i].key, values[values.length - 1 -i]))
     }
@@ -563,7 +566,7 @@
     // now check the key query args
     for (i=1; i<values.length; i++) {
       var queryOptions = {key:values[i]}
-      rows = db.query(queryFun, queryOptions).rows;
+      rows = db.query(queryFun, null, queryOptions).rows;
       T(rows.length == 1 && equals(rows[0].key, values[i]))
     }
   },
@@ -600,7 +603,7 @@
 
     var results = dbB.query(function(doc) {
       if (doc._conflicts) {
-        map(doc._id, doc._conflicts);
+        emit(doc._id, doc._conflicts);
       }
     });
     T(results.rows[0].value[0] == conflictRev);
@@ -615,12 +618,16 @@
     var docs = makeDocs(0, 100);
     T(db.bulkSave(docs).ok);
 
-    var queryFun = function(doc) { map(doc.integer, null) };
+    var queryFun = function(doc) { emit(doc.integer, null) };
     var i;
 
     // page through the view ascending and going forward
     for (i = 0; i < docs.length; i += 10) {
-      var queryResults = db.query(queryFun, {startkey:i, startkey_docid:i, count:10});
+      var queryResults = db.query(queryFun, null, {
+        startkey: i,
+        startkey_docid: i,
+        count: 10
+      });
       T(queryResults.rows.length == 10)
       T(queryResults.total_rows == docs.length)
       T(queryResults.offset == i)
@@ -632,8 +639,11 @@
 
     // page through the view ascending and going backward
     for (i = docs.length - 1; i >= 0; i -= 10) {
-      var queryResults = db.query(queryFun, {startkey:i, startkey_docid:i,
-                                             count:-10})
+      var queryResults = db.query(queryFun, null, {
+        startkey: i,
+        startkey_docid: i,
+        count:-10
+      });
       T(queryResults.rows.length == 10)
       T(queryResults.total_rows == docs.length)
       T(queryResults.offset == i - 9)
@@ -645,8 +655,12 @@
 
     // page through the view descending and going forward
     for (i = docs.length - 1; i >= 0; i -= 10) {
-      var queryResults = db.query(queryFun, {startkey:i, startkey_docid:i,
-                                             descending:true, count:10})
+      var queryResults = db.query(queryFun, null, {
+        startkey: i,
+        startkey_docid: i,
+        descending: true,
+        count: 10
+      });
       T(queryResults.rows.length == 10)
       T(queryResults.total_rows == docs.length)
       T(queryResults.offset == docs.length - i - 1)
@@ -658,8 +672,12 @@
 
     // page through the view descending and going backward
     for (i = 0; i < docs.length; i += 10) {
-      var queryResults = db.query(queryFun, {startkey:i, startkey_docid:i,
-                                             descending:true, count:-10});
+      var queryResults = db.query(queryFun, null, {
+        startkey: i,
+        startkey_docid: i,
+        descending: true,
+        count:-10
+      });
       T(queryResults.rows.length == 10)
       T(queryResults.total_rows == docs.length)
       T(queryResults.offset == docs.length - i - 10)
@@ -668,11 +686,15 @@
         T(queryResults.rows[j].key == i + 9 - j);
       }
     }
-    
+
     // ignore decending=false. CouchDB should just ignore that.
     for (i = 0; i < docs.length; i += 10) {
-      var queryResults = db.query(queryFun, {startkey:i, startkey_docid:i, 
-                                             descending:false, count:10});
+      var queryResults = db.query(queryFun, null, {
+        startkey: i,
+        startkey_docid: i,
+        descending: false,
+        count: 10
+      });
       T(queryResults.rows.length == 10)
       T(queryResults.total_rows == docs.length)
       T(queryResults.offset == i)
@@ -695,7 +717,7 @@
     // make sure that attempting to change the document throws an error
     var results = db.query(function(doc) {
       doc._id = "foo";
-      map(null, doc);
+      emit(null, doc);
     });
     T(results.total_rows == 0);
 
@@ -703,18 +725,18 @@
     // garbage collector
     var results = db.query(function(doc) {
       gc();
-      map(null, doc);
+      emit(null, doc);
     });
     T(results.total_rows == 0);
 
     // make sure that a view cannot access the map_funs array defined used by
     // the view server
-    var results = db.query(function(doc) { map_funs.push(1); map(null, doc) });
+    var results = db.query(function(doc) { map_funs.push(1); emit(null, doc) });
     T(results.total_rows == 0);
 
     // make sure that a view cannot access the map_results array defined used by
     // the view server
-    var results = db.query(function(doc) { map_results.push(1); map(null, doc) });
+    var results = db.query(function(doc) { map_results.push(1); emit(null, doc) });
     T(results.total_rows == 0);
   },
 
@@ -730,7 +752,7 @@
     var results = db.query(
       "function(doc) {\n" +
       "  var xml = new XML(doc.content);\n" +
-      "  map(xml.title.text(), null);\n" +
+      "  emit(xml.title.text(), null);\n" +
       "}");
     T(results.total_rows == 2);
     T(results.rows[0].key == "Testing E4X");
@@ -739,7 +761,7 @@
     var results = db.query(
       "function(doc) {\n" +
       "  var xml = new XML(doc.content);\n" +
-      "  map(xml.title.@id, null);\n" +
+      "  emit(xml.title.@id, null);\n" +
       "}");
     T(results.total_rows == 2);
     T(results.rows[0].key == "e4x");
@@ -928,7 +950,7 @@
     var docs = makeDocs(0, 10);
     var saveResult = db.bulkSave(docs);
     T(saveResult.ok);
-    
+
 
     var binAttDoc = {
       _id:"bin_doc",
@@ -941,28 +963,28 @@
     }
 
     T(db.save(binAttDoc).ok);
-    
+
     var originalsize = db.info().disk_size;
-    
+
     for(var i in docs) {
         db.deleteDoc(docs[i]);
     }
     var deletesize = db.info().disk_size;
     T(deletesize > originalsize);
-    
+
     var xhr = CouchDB.request("POST", "/test_suite_db/_compact");
     T(xhr.status == 202);
     //compaction isn't instantaneous, loop until done
     while(db.info().compact_running) {};
-    
-    
+
+
 
     var xhr = CouchDB.request("GET", "/test_suite_db/bin_doc/foo.txt");
     T(xhr.responseText == "This is a base64 encoded text")
     T(xhr.getResponseHeader("content-type") == "text/plain")
-    
+
     var compactedsize = db.info().disk_size;
-    
+
     T(deletesize > originalsize);
     },
     

Modified: incubator/couchdb/branches/runtimeconfig/share/www/script/jquery.couch.js
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/share/www/script/jquery.couch.js?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/share/www/script/jquery.couch.js [utf-8] (original)
+++ incubator/couchdb/branches/runtimeconfig/share/www/script/jquery.couch.js [utf-8] Sat May 24 01:38:04 2008
@@ -15,6 +15,7 @@
   $.fn.extend($.couch, {
 
     allDbs: function(options) {
+      options = options || {};
       $.ajax({
         type: "GET", url: "/_all_dbs",
         complete: function(req) {
@@ -37,6 +38,7 @@
         uri: "/" + encodeURIComponent(name) + "/",
 
         compact: function(options) {
+          options = options || {};
           $.ajax({
             type: "POST", url: this.uri + "_compact", dataType: "json",
             complete: function(req) {
@@ -52,6 +54,7 @@
           });
         },
         create: function(options) {
+          options = options || {};
           $.ajax({
             type: "PUT", url: this.uri, dataType: "json",
             complete: function(req) {
@@ -67,6 +70,7 @@
           });
         },
         drop: function(options) {
+          options = options || {};
           $.ajax({
             type: "DELETE", url: this.uri, dataType: "json",
             complete: function(req) {
@@ -82,6 +86,7 @@
           });
         },
         info: function(options) {
+          options = options || {};
           $.ajax({
             type: "GET", url: this.uri, dataType: "json",
             complete: function(req) {
@@ -98,6 +103,7 @@
           });
         },
         allDocs: function(options) {
+          options = options || {};
           $.ajax({
             type: "GET", url: this.uri + "_all_docs" + encodeOptions(options),
             dataType: "json",
@@ -115,6 +121,7 @@
           });
         },
         openDoc: function(docId, options) {
+          options = options || {};
           $.ajax({
             type: "GET",
             url: this.uri + encodeURIComponent(docId) + encodeOptions(options),
@@ -132,6 +139,7 @@
           });
         },
         saveDoc: function(doc, options) {
+          options = options || {};
           if (doc._id === undefined) {
             var method = "POST";
             var uri = this.uri;
@@ -158,6 +166,7 @@
           });
         },
         removeDoc: function(doc, options) {
+          options = options || {};
           $.ajax({
             type: "DELETE",
             url: this.uri + encodeURIComponent(doc._id) + encodeOptions({rev: doc._rev}),
@@ -174,12 +183,22 @@
             }
           });
         },
-        query: function(fun, options) {
-          if (typeof(fun) != "string")
-            fun = fun.toSource ? fun.toSource() : "(" + fun.toString() + ")";
+        query: function(mapFun, reduceFun, language, options) {
+          options = options || {};
+          language = language || "javascript"
+          if (typeof(mapFun) != "string") {
+            mapFun = mapFun.toSource ? mapFun.toSource() : "(" + mapFun.toString() + ")";
+          }
+          var body = {language: language, map: mapFun};
+          if (reduceFun != null) {
+            if (typeof(reduceFun) != "string")
+              reduceFun = reduceFun.toSource ? reduceFun.toSource() : "(" + reduceFun.toString() + ")";
+            body.reduce = reduceFun;
+          }
           $.ajax({
             type: "POST", url: this.uri + "_temp_view" + encodeOptions(options),
-            contentType: "text/javascript", data: fun, dataType: "json",
+            contentType: "application/json",
+            data: toJSON(body), dataType: "json",
             complete: function(req) {
               var resp = $.httpData(req, "json");
               if (req.status == 200 && options.success) {
@@ -193,6 +212,7 @@
           });
         },
         view: function(name, options) {
+          options = options || {};
           $.ajax({
             type: "GET", url: this.uri + "_view/" + name + encodeOptions(options),
             dataType: "json",
@@ -212,6 +232,7 @@
     },
 
     info: function(options) {
+      options = options || {};
       $.ajax({
         type: "GET", url: "/", dataType: "json",
         complete: function(req) {
@@ -228,6 +249,7 @@
     },
 
     replicate: function(source, target, options) {
+      options = options || {};
       $.ajax({
         type: "POST", url: "/_replicate", dataType: "json",
         data: JSON.stringify({source: source, target: target}),

Modified: incubator/couchdb/branches/runtimeconfig/share/www/script/jquery.resizer.js
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/share/www/script/jquery.resizer.js?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/share/www/script/jquery.resizer.js [utf-8] (original)
+++ incubator/couchdb/branches/runtimeconfig/share/www/script/jquery.resizer.js [utf-8] Sat May 24 01:38:04 2008
@@ -13,13 +13,15 @@
 (function($) {
 
   $.fn.resizable = function(options) {
-    if ($.browser.safari && parseInt($.browser.version) >= 522)
-      return this; // safari3 and later provides textarea resizing natively
     options = options || {};
+    options.always = options.always || false;
     options.grippie = options.grippie || null;
     options.minHeight = options.minHeight || 32;
     options.maxHeight = options.maxHeight || null;
 
+    if (!options.always && $.browser.safari && parseInt($.browser.version) >= 522)
+      return this; // safari3 and later provides textarea resizing natively
+
     return this.each(function() {
       var grippie = options.grippie;
       if (!grippie) grippie = $("<div></div>").appendTo(this.parentNode);

Modified: incubator/couchdb/branches/runtimeconfig/share/www/style/layout.css
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/share/www/style/layout.css?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/share/www/style/layout.css (original)
+++ incubator/couchdb/branches/runtimeconfig/share/www/style/layout.css Sat May 24 01:38:04 2008
@@ -251,35 +251,43 @@
 #viewcode { background: #fff; border: 1px solid;
   border-color: #999 #ddd #ddd #999; margin: 0 0 1em; padding: 0 .5em;
 }
-#viewcode div { background-color: #e9e9e9; border: 1px solid;
-  border-color: #ddd #ddd #e9e9e9 #ddd; color: #333; margin: 0 -.5em;
-  padding: 0 .5em 2px;
+#viewcode .top, #viewcode .bottom { background-color: #e9e9e9;
+  border: 1px solid; border-color: #ddd #ddd #e9e9e9 #ddd; color: #333;
+  margin: 0 -.5em; padding: 0 .5em 2px;
+}
+#viewcode .top {  color: #aaa; font-size: 95%; }
+#viewcode .top span { background: url(../image/twisty.gif) 0 3px no-repeat;
+  border: none; color: #666; cursor: pointer; display: block; font-size: 90%;
+  margin: 0; padding: 2px 0 0 15px;
 }
-#viewcode .top { color: #aaa; font-size: 95%; }
 #viewcode .top a { float: right; font-size: 90%; line-height: 1.4em;
   padding: 2px 2px 0 0;
 }
 #viewcode .top a:link, #viewcode .top a:visited { color: #999; }
-#viewcode label { background: url(../image/twisty.gif) 0 3px no-repeat;
-  color: #666; cursor: pointer; display: block; padding: 2px 0 0 15px;
-}
-#viewcode div.bottom, #viewcode textarea { display: none; }
-#viewcode textarea { border: none; color: #333; max-width: 100%;
-  min-height: 50px; padding: .5em 0; width: 100%;
-}
-#viewcode div.bottom { border-bottom: none; padding: 1px 3px; }
-#viewcode div.bottom button { font-size: 90%; margin: 0 1em 0 0;
+#viewcode .code, #viewcode .bottom { display: none; }
+#viewcode .code { float: left; padding: .2em 0; width: 49%; }
+#viewcode .code label { font-size: 90%; color: #999; }
+#viewcode .code textarea { border: none; border-top: 1px solid #ccc;
+  color: #333; margin: 0 0 .4em; min-height: 50px; max-width: 98%;
+  padding: .2em 0; resize: none;
+}
+#viewcode .code textarea:focus { background: #ffffe9; }
+#viewcode div.map { border-right: 3px double #ccc; margin-right: .5em; }
+#viewcode .bottom { border-bottom: none; clear: left; padding: 1px 3px; }
+#viewcode .bottom button { font-size: 90%; margin: 0 1em 0 0;
   padding-left: 2em; padding-right: 2em;
 }
-*html #viewcode div.bottom button { padding: 0 .5em; }
-*+html #viewcode div.bottom button { padding: 0 .5em; }
-#viewcode div.bottom button.revert, #viewcode div.bottom button.save,
-#viewcode div.bottom button.saveas {
+*html #viewcode .bottom button { padding: 0 .5em; }
+*+html #viewcode .bottom button { padding: 0 .5em; }
+#viewcode .bottom button.revert, #viewcode .bottom button.save,
+#viewcode .bottom button.saveas {
   float: right; margin: 0 0 0 1em;
 }
-#viewcode div.bottom button.save { font-weight: bold; }
-#viewcode.expanded label { background-position: 0 -96px; }
-#viewcode.expanded textarea, #viewcode.expanded div.bottom { display: block; }
+#viewcode .bottom button.save { font-weight: bold; }
+#viewcode .grippie { background-position: 49% 50%; }
+#viewcode.expanded .top { border-bottom: 1px solid #ddd; }
+#viewcode.expanded .top span { background-position: 0 -96px; }
+#viewcode.expanded .code, #viewcode.expanded .bottom { display: block; }
 
 /* Database table */
 
@@ -302,6 +310,12 @@
 }
 #documents tbody.content td.value { font-size: 10px; }
 
+#documents.reduced th.key, #documents.reduced td.key,
+#documents.reduced #paging {
+  display: none;
+}
+#documents.reduced td.value { white-space: pre; }
+
 /* Document fields table */
 
 #fields { table-layout: fixed; }

Modified: incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_btree.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_btree.erl?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_btree.erl (original)
+++ incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_btree.erl Sat May 24 01:38:04 2008
@@ -390,40 +390,42 @@
     end.
 
 
+collect_node(_Bt, {P, R}, nil, nil) ->
+    {[], [{nil, {P,R}}]};
 collect_node(Bt, {P, R}, KeyStart, KeyEnd) ->
     case get_node(Bt, P) of
     {kp_node, NodeList} ->
         collect_kp_node(Bt, NodeList, KeyStart, KeyEnd);
     {kv_node, KVs} ->
-        GTEKeyStartKVs =
-        case KeyStart of
-        nil ->
-            KVs;
-        _ ->
-            lists:dropwhile(
-                fun({Key,_}) ->
-                    less(Bt, Key, KeyStart)
-                end, KVs)
-        end,
-        KVs2 =
-        case KeyEnd of
-        nil ->
-            GTEKeyStartKVs;
-        _ ->
-            lists:dropwhile(
-                fun({Key,_}) -> 
-                    less(Bt, KeyEnd, Key)
-                end, lists:reverse(GTEKeyStartKVs))
-        end,
-        case length(KVs2) == length(KVs) of
-        true -> % got full node, return the already calculated reduction
-            {[], [{nil, {P, R}}]};
-        false -> % otherwise return the keyvalues for later reduction
-            {KVs2, []}
-        end
+        collect_kv_node(Bt, {P,R}, KVs, KeyStart, KeyEnd)
     end.
 
-
+collect_kv_node(Bt, {P,R}, KVs, KeyStart, KeyEnd) ->
+    GTEKeyStartKVs =
+    case KeyStart of
+    nil ->
+        KVs;
+    _ ->
+        lists:dropwhile(fun({Key,_}) -> less(Bt, Key, KeyStart) end, KVs)
+    end,
+    KVs2 =
+    case KeyEnd of
+    nil ->
+        GTEKeyStartKVs;
+    _ ->
+        lists:dropwhile(
+            fun({Key,_}) -> 
+                less(Bt, KeyEnd, Key)
+            end, lists:reverse(GTEKeyStartKVs))
+    end,
+    case length(KVs2) == length(KVs) of
+    true -> % got full node, return the already calculated reduction
+        {[], [{nil, {P, R}}]};
+    false -> % otherwise return the keyvalues for later reduction
+        {[assemble(Bt,K,V) || {K,V} <- KVs2], []}
+    end.
+        
+        
 collect_kp_node(Bt, NodeList, KeyStart, KeyEnd) ->   
     Nodes =
     case KeyStart of
@@ -568,9 +570,10 @@
 stream_kv_node2(_Bt, _Reds, _PrevKVs, [], _Dir, _Fun, Acc) ->
     {ok, Acc};
 stream_kv_node2(Bt, Reds, PrevKVs, [{K,V} | RestKVs], Dir, Fun, Acc) ->
-    case Fun(assemble(Bt, K, V), {PrevKVs, Reds}, Acc) of
+    AssembledKV = assemble(Bt, K, V),
+    case Fun(AssembledKV, {PrevKVs, Reds}, Acc) of
     {ok, Acc2} ->
-        stream_kv_node2(Bt, Reds, [{K,V} | PrevKVs], RestKVs, Dir, Fun, Acc2);
+        stream_kv_node2(Bt, Reds, [AssembledKV | PrevKVs], RestKVs, Dir, Fun, Acc2);
     {stop, Acc2} ->
         {stop, Acc2}
     end.

Modified: incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_db.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_db.erl?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_db.erl (original)
+++ incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_db.erl Sat May 24 01:38:04 2008
@@ -121,7 +121,7 @@
 
 delete_doc(MainPid, Id, Revisions) ->
     DeletedDocs = [#doc{id=Id, revs=[Rev], deleted=true} || Rev <- Revisions],
-    {ok, [Result]} = update_docs(MainPid, DeletedDocs, [new_edits]),
+    {ok, [Result]} = update_docs(MainPid, DeletedDocs, []),
     {ok, Result}.
 
 open_doc(MainPid, IdOrDocInfo) ->
@@ -291,13 +291,13 @@
     % flush unwritten binaries to disk.
     DocBuckets3 = [[doc_flush_binaries(Doc, Db#db.fd) || Doc <- Bucket] || Bucket <- DocBuckets2],
 
-    case gen_server:call(MainPid, {update_docs, DocBuckets3, Options}) of
+    case gen_server:call(MainPid, {update_docs, DocBuckets3, [new_edits | Options]}) of
     ok -> {ok, NewRevs};
     retry ->
         Db2 = get_db(MainPid),
         DocBuckets4 = [[doc_flush_binaries(Doc, Db2#db.fd) || Doc <- Bucket] || Bucket <- DocBuckets3],
         % We only retry once
-        case gen_server:call(MainPid, {update_docs, DocBuckets4, Options}) of
+        case gen_server:call(MainPid, {update_docs, DocBuckets4, [new_edits | Options]}) of
         ok -> {ok, NewRevs};
         Else -> throw(Else)
         end;
@@ -838,7 +838,7 @@
         end, {0, 0}, OldDocLookups),
     
     % Merge the new docs into the revision trees.
-    NoConflicts = lists:member(no_conflicts, Options),
+    NoConflicts = lists:member(new_edits, Options),
     {ok, NewDocInfos, NewSeq} = merge_rev_trees(NoConflicts, DocsList2, OldDocInfos, [], LastSeq),
     
     RemoveSeqs =

Modified: incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_doc.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_doc.erl?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_doc.erl (original)
+++ incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_doc.erl Sat May 24 01:38:04 2008
@@ -172,7 +172,7 @@
     Bin.
 
 get_view_functions(#doc{body={obj, Fields}}) ->
-    Lang = proplists:get_value("language", Fields, "text/javascript"),
+    Lang = proplists:get_value("language", Fields, "javascript"),
     {obj, Views} = proplists:get_value("views", Fields, {obj, []}),
     {Lang, [{ViewName, Value} || {ViewName, Value} <- Views, is_list(Value)]};
 get_view_functions(_Doc) ->

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=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_httpd.erl (original)
+++ incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_httpd.erl Sat May 24 01:38:04 2008
@@ -52,7 +52,7 @@
     mochiweb_http:stop(?MODULE).
 
 handle_request(Req, DocumentRoot) ->
-    
+
     % alias HEAD to GET as mochiweb takes care of stripping the body
     Method = case Req:get(method) of
         'HEAD' -> 'GET';
@@ -67,7 +67,7 @@
     ?LOG_DEBUG("Method:      ~p", [Method]),
     ?LOG_DEBUG("Request URI: ~p", [Path]),
     ?LOG_DEBUG("Headers: ~p", [mochiweb_headers:to_list(Req:get(headers))]),
-    
+
     {ok, Resp} = case catch(handle_request(Req, DocumentRoot, Method, Path)) of
         {ok, Resp0} ->
             {ok, Resp0};
@@ -82,6 +82,12 @@
     ]).
     
 handle_request(Req, DocumentRoot, Method, Path) ->
+    % Start = erlang:now(),
+    X = handle_request0(Req, DocumentRoot, Method, Path),
+    % io:format("now_diff:~p~n", [timer:now_diff(erlang:now(), Start)]),
+    X.
+
+handle_request0(Req, DocumentRoot, Method, Path) ->
     case Path of
         "/" ->
             handle_welcome_request(Req, Method);
@@ -132,25 +138,25 @@
 handle_replicate_request(_Req, _Method) ->
     throw({method_not_allowed, "POST"}).
 
-handle_unkown_private_uri_request(Req, _Method, UnknownPrivatePath) ->    
+handle_unkown_private_uri_request(Req, _Method, UnknownPrivatePath) ->
   KnownPrivatePaths = ["_utils"],
-  Msg = {obj, 
+  Msg = {obj,
     [
-      {error, "Sorry, we could not find the private path '_" ++ 
-        mochiweb_util:unquote(UnknownPrivatePath) ++ 
-        "' you are looking for. We only know about the following path(s): '" ++ 
+      {error, "Could not find the private path '_" ++
+        mochiweb_util:unquote(UnknownPrivatePath) ++
+        "'. Known private path(s): '" ++
         lists:flatten(KnownPrivatePaths) ++ "'"}
     ]
   },
   send_error(Req, 404, Msg).
-  
+
 % Database request handlers
 
 handle_db_request(Req, Method, {Path}) ->
     UriParts = string:tokens(Path, "/"),
     [DbName|Rest] = UriParts,
     handle_db_request(Req, Method, {mochiweb_util:unquote(DbName), Rest});
-    
+
 handle_db_request(Req, 'PUT', {DbName, []}) ->
     case couch_server:create(DbName, []) of
         {ok, _Db} ->
@@ -251,7 +257,7 @@
     throw({method_not_allowed, "POST"});
 
 handle_db_request(Req, 'GET', {DbName, _Db, ["_search"]}) ->
-    case Req:parse_qs() of 
+    case Req:parse_qs() of
         [{"q", Query}] when (length(Query) > 0) ->
             {ok, Response} = couch_ft_query:execute(DbName, Query),
             send_json(Req, {obj, [{ok, true} | Response]});
@@ -398,30 +404,30 @@
         end_docid = EndDocId
     } = QueryArgs = parse_view_query(Req),
 
-    ContentType = case Req:get_primary_header_value("content-type") of
-        undefined ->
-            "text/javascript";
-        Else ->
-            Else
-    end,
-    case cjson:decode(Req:recv_body()) of
-    {obj, Props} ->
-        MapSrc = proplists:get_value("map",Props),
-        RedSrc = proplists:get_value("reduce",Props),
-        {ok, View} = couch_view:get_reduce_view(
-                {temp, DbName, ContentType, MapSrc, RedSrc}),
-        {ok, Value} = couch_view:reduce(View, {StartKey, StartDocId}, {EndKey, EndDocId}),
-        send_json(Req, {obj, [{ok,true}, {result, Value}]});
-    Src when is_list(Src) ->
-        
-        {ok, View} = couch_view:get_map_view({temp, DbName, ContentType, Src}),
+    case Req:get_primary_header_value("content-type") of
+        undefined -> ok;
+        "application/json" -> ok;
+        Else -> throw({incorrect_mime_type, Else})
+    end,
+    {obj, Props} = cjson:decode(Req:recv_body()),
+    Language = proplists:get_value("language", Props, "javascript"),
+    MapSrc = proplists:get_value("map", Props),
+    case proplists:get_value("reduce", Props, null) of
+    null ->
+        {ok, View} = couch_view:get_map_view({temp, DbName, Language, MapSrc}),
         Start = {StartKey, StartDocId},
         {ok, TotalRows} = couch_view:get_row_count(View),
         FoldlFun = make_view_fold_fun(Req, QueryArgs, TotalRows,
                 fun couch_view:reduce_to_count/1),
         FoldAccInit = {Count, SkipCount, undefined, []},
         FoldResult = couch_view:fold(View, Start, Dir, FoldlFun, FoldAccInit),
-        finish_view_fold(Req, TotalRows, FoldResult)
+        finish_view_fold(Req, TotalRows, FoldResult);
+
+    RedSrc ->
+        {ok, View} = couch_view:get_reduce_view(
+                {temp, DbName, Language, MapSrc, RedSrc}),
+        {ok, Value} = couch_view:reduce(View, {StartKey, StartDocId}, {EndKey, EndDocId}),
+        send_json(Req, {obj, [{ok,true}, {result, Value}]})
     end;
 
 handle_db_request(_Req, _Method, {_DbName, _Db, ["_temp_view"]}) ->
@@ -700,7 +706,7 @@
         {"descending", "false"} ->
           % The descending=false behaviour is the default behaviour, so we
           % simpply ignore it. This is only for convenience when playing with
-          % the HTTP API, so that a user doesn't get served an error when 
+          % the HTTP API, so that a user doesn't get served an error when
           % flipping true to false in the descending option.
           Args;
         {"skip", Value} ->
@@ -739,7 +745,7 @@
             couch_view:less_json({ViewKey, ViewId}, {EndKey, EndDocId})
         end
     end,
-    
+
     NegCountFun = fun({{Key, DocId}, Value}, OffsetReds,
                       {AccCount, AccSkip, Resp, AccRevRows}) ->
         Offset = ReduceCountFun(OffsetReds),
@@ -923,25 +929,33 @@
     send_json(Req, Code, [], Value).
 
 send_json(Req, Code, Headers, Value) ->
-    Resp = start_json_response(Req, Code, Headers),
-    Resp:write_chunk(cjson:encode(Value)),
-    end_json_response(Resp),
+    ContentType = negotiate_content_type(Req),
+    Body = cjson:encode(Value),
+    Resp = Req:respond({Code, [{"Content-Type", ContentType}] ++ 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}).
+
+end_json_response(Resp) ->
+    Resp:write_chunk(""),
+    {ok, Resp}.
+
+negotiate_content_type(Req) ->
+    %% Determine the appropriate Content-Type header for a JSON response
+    %% depending on the Accept header in the request. A request that explicitly
+    %% lists the correct JSON MIME type will get that type, otherwise the
+    %% response will have the generic MIME type "text/plain"
     AcceptedTypes = case Req:get_header_value("Accept") of
         undefined       -> [];
         AcceptHeader    -> string:tokens(AcceptHeader, ", ")
     end,
-    ContentType = case lists:member("application/json", AcceptedTypes) of
+    case lists:member("application/json", AcceptedTypes) of
         true  -> "application/json";
         false -> "text/plain;charset=utf-8"
-    end,
-    Req:respond({Code, [{"Content-Type", ContentType}] ++ Headers, chunked}).
-
-end_json_response(Resp) ->
-    Resp:write_chunk(""),
-    {ok, Resp}.
+    end.

Modified: incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_view.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_view.erl?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_view.erl (original)
+++ incubator/couchdb/branches/runtimeconfig/src/couchdb/couch_view.erl Sat May 24 01:38:04 2008
@@ -117,8 +117,8 @@
             {ok, Reduced} = couch_query_servers:combine(Lang, [FunSrc], UserReds),
             {0, PreResultPadding ++ Reduced ++ PostResultPadding}
         end,
-    {0, [FinalReduction]} = couch_btree:final_reduce(ReduceFun, PartialReductions),
-    {ok, FinalReduction}.
+    {_, FinalReds} = couch_btree:final_reduce(ReduceFun, PartialReductions),
+    {ok, lists:nth(NthRed, FinalReds)}.
         
 get_key_pos(_Key, [], _N) ->
     0;
@@ -154,34 +154,28 @@
                 
 
 design_doc_to_view_group(#doc{id=Id,body={obj, Fields}}) ->
-    Language = proplists:get_value("language", Fields, "text/javascript"),
+    Language = proplists:get_value("language", Fields, "javascript"),
     {obj, RawViews} = proplists:get_value("views", Fields, {obj, []}),
-    
-    % extract the map/reduce views from the json fields and into lists
-    MapViewsRaw = [{Name, Src, nil} || {Name, Src} <- RawViews, is_list(Src)],
-    MapReduceViewsRaw =
-        [{Name,
-            proplists:get_value("map", MRFuns),
-            proplists:get_value("reduce", MRFuns)}
-            || {Name, {obj, MRFuns}} <- RawViews],
             
     % add the views to a dictionary object, with the map source as the key
     DictBySrc =
     lists:foldl(
-        fun({Name, MapSrc, RedSrc}, DictBySrcAcc) ->
+        fun({Name, {obj, MRFuns}}, DictBySrcAcc) ->
+            MapSrc = proplists:get_value("map", MRFuns),
+            RedSrc = proplists:get_value("reduce", MRFuns, null),
             View =
             case dict:find(MapSrc, DictBySrcAcc) of
                 {ok, View0} -> View0;
                 error -> #view{def=MapSrc} % create new view object
             end,
             View2 =
-            if RedSrc == nil ->
+            if RedSrc == null ->
                 View#view{map_names=[Name|View#view.map_names]};
             true ->
                 View#view{reduce_funs=[{Name,RedSrc}|View#view.reduce_funs]}
             end,
             dict:store(MapSrc, View2, DictBySrcAcc)
-        end, dict:new(), MapViewsRaw ++ MapReduceViewsRaw),
+        end, dict:new(), RawViews),
     % number the views
     {Views, _N} = lists:mapfoldl(
         fun({_Src, View}, N) ->

Modified: incubator/couchdb/branches/runtimeconfig/src/mochiweb/Makefile.am
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/src/mochiweb/Makefile.am?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/src/mochiweb/Makefile.am (original)
+++ incubator/couchdb/branches/runtimeconfig/src/mochiweb/Makefile.am Sat May 24 01:38:04 2008
@@ -12,9 +12,12 @@
 
 datarootdir = @prefix@/share
 
-mochiwebebindir = $(erlanglibdir)/mochiweb-r64/ebin
+mochiwebebindir = $(erlanglibdir)/mochiweb-r73/ebin
 
 mochiweb_file_collection = \
+    mochifmt.erl \
+    mochifmt_records.erl \
+    mochifmt_std.erl \
     mochihex.erl \
     mochijson.erl \
     mochijson2.erl \
@@ -39,6 +42,9 @@
 mochiwebebin_static_file = mochiweb.app
 
 mochiwebebin_make_generated_file_list = \
+    mochifmt.beam \
+    mochifmt_records.beam \
+    mochifmt_std.beam \
     mochihex.beam \
     mochijson.beam \
     mochijson2.beam \

Modified: incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb.erl?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb.erl (original)
+++ incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb.erl Sat May 24 01:38:04 2008
@@ -35,6 +35,7 @@
     mochijson:test(),
     mochiweb_charref:test(),
     mochiweb_html:test(),
+    mochifmt:test(),
     test_request(),
     ok.
 

Modified: incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_headers.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_headers.erl?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_headers.erl (original)
+++ incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_headers.erl Sat May 24 01:38:04 2008
@@ -160,7 +160,7 @@
     V0 ++ ", " ++ V1.
 
 normalize(K) when is_list(K) ->
-    string:to_lower(K);
+    mochiweb_util:to_lower(K);
 normalize(K) when is_atom(K) ->
     normalize(atom_to_list(K));
 normalize(K) when is_binary(K) ->

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=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_html.erl (original)
+++ incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_html.erl Sat May 24 01:38:04 2008
@@ -35,7 +35,7 @@
 -define(IS_LITERAL_SAFE(C),
         ((C >= $A andalso C =< $Z) orelse (C >= $a andalso C =< $z)
          orelse (C >= $0 andalso C =< $9))).
-                                
+
 -record(decoder, {line=1,
                   column=1,
                   offset=0}).
@@ -202,7 +202,7 @@
     attrs_to_html(Rest,
                   [[<<" ">>, escape(K), <<"=\"">>,
                     escape_attr(V), <<"\"">>] | Acc]).
-    
+
 test_escape() ->
     <<"&amp;quot;\"word &lt;&lt;up!&amp;quot;">> =
         escape(<<"&quot;\"word <<up!&quot;">>),
@@ -299,6 +299,14 @@
         tokens(<<"<foo bar=baz wibble='wibble' alice=bob/>">>),
     [{comment, <<"[if lt IE 7]>\n<style type=\"text/css\">\n.no_ie { display: none; }\n</style>\n<![endif]">>}] =
         tokens(<<"<!--[if lt IE 7]>\n<style type=\"text/css\">\n.no_ie { display: none; }\n</style>\n<![endif]-->">>),
+    [{start_tag, <<"script">>, [{<<"type">>, <<"text/javascript">>}], false},
+     {data, <<" A= B <= C ">>, false},
+     {end_tag, <<"script">>}] =
+        tokens(<<"<script type=\"text/javascript\"> A= B <= C </script>">>),
+    [{start_tag, <<"textarea">>, [], false},
+     {data, <<"<html></body>">>, false},
+     {end_tag, <<"textarea">>}] =
+        tokens(<<"<textarea><html></body></textarea>">>),
     ok.
 
 tokens(B, S=#decoder{offset=O}, Acc) ->
@@ -307,8 +315,29 @@
             lists:reverse(Acc);
         _ ->
             {Tag, S1} = tokenize(B, S),
-            tokens(B, S1, [Tag | Acc])
-    end.
+            case parse_flag(Tag) of
+                script ->
+                    {Tag2, S2} = tokenize_script(B, S1),
+                    tokens(B, S2, [Tag2, Tag | Acc]);
+                textarea ->
+                    {Tag2, S2} = tokenize_textarea(B, S1),
+                    tokens(B, S2, [Tag2, Tag | Acc]);
+                none ->
+                    tokens(B, S1, [Tag | Acc])
+            end
+    end.
+
+parse_flag({start_tag, B, _, false}) ->
+    case mochiweb_util:to_lower(binary_to_list(B)) of
+        "script" ->
+            script;
+        "textarea" ->
+            textarea;
+        _ ->
+            none
+    end;
+parse_flag(_) ->
+    none.
 
 tokenize(B, S=#decoder{offset=O}) ->
     case B of
@@ -330,7 +359,7 @@
             {S2, _} = find_gt(B, S1),
             {{end_tag, Tag}, S2};
         <<_:O/binary, "<", C, _/binary>> when ?IS_WHITESPACE(C) ->
-            %% This isn't really strict HTML but we want this for markdown
+            %% This isn't really strict HTML
             tokenize_data(B, ?INC_COL(S));
         <<_:O/binary, "<", _/binary>> ->
             {Tag, S1} = tokenize_literal(B, ?INC_COL(S)),
@@ -492,7 +521,7 @@
 norm(Tag) when is_binary(Tag) ->
     Tag;
 norm(Tag) ->
-    list_to_binary(string:to_lower(Tag)).
+    list_to_binary(mochiweb_util:to_lower(Tag)).
 
 test_destack() ->
     {<<"a">>, [], []} =
@@ -524,7 +553,7 @@
 
 destack(TagName, Stack) when is_list(Stack) ->
     F = fun (X) ->
-                case X of 
+                case X of
                     {TagName, _, _} ->
                         false;
                     _ ->
@@ -542,7 +571,7 @@
             %% Unfurl up to the tag, then accumulate it
             [{T0, A0, [destack(Pre ++ [T]) | Acc0]} | Post]
     end.
-    
+
 destack([{Tag, Attrs, Acc}]) ->
     {Tag, Attrs, lists:reverse(Acc)};
 destack([{T1, A1, Acc1}, {T0, A0, Acc0} | Rest]) ->
@@ -655,7 +684,7 @@
 
 tokenize_charref(Bin, S=#decoder{offset=O}) ->
     tokenize_charref(Bin, S, O).
-    
+
 tokenize_charref(Bin, S=#decoder{offset=O}, Start) ->
     case Bin of
         <<_:O/binary>> ->
@@ -758,3 +787,49 @@
         <<_:Start/binary, Raw/binary>> ->
             {{comment, Raw}, S}
     end.
+
+tokenize_script(Bin, S=#decoder{offset=O}) ->
+    tokenize_script(Bin, S, O).
+
+tokenize_script(Bin, S=#decoder{offset=O}, Start) ->
+    case Bin of
+        %% Just a look-ahead, we want the end_tag separately
+        <<_:O/binary, $<, $/, SS, CC, RR, II, PP, TT, _/binary>>
+        when (SS =:= $s orelse SS =:= $S) andalso
+             (CC =:= $c orelse CC =:= $C) andalso
+             (RR =:= $r orelse RR =:= $R) andalso
+             (II =:= $i orelse II =:= $I) andalso
+             (PP =:= $p orelse PP =:= $P) andalso
+             (TT=:= $t orelse TT =:= $T) ->
+            Len = O - Start,
+            <<_:Start/binary, Raw:Len/binary, _/binary>> = Bin,
+            {{data, Raw, false}, S};
+        <<_:O/binary, C, _/binary>> ->
+            tokenize_script(Bin, ?INC_CHAR(S, C), Start);
+        <<_:Start/binary, Raw/binary>> ->
+            {{data, Raw, false}, S}
+    end.
+
+tokenize_textarea(Bin, S=#decoder{offset=O}) ->
+    tokenize_textarea(Bin, S, O).
+
+tokenize_textarea(Bin, S=#decoder{offset=O}, Start) ->
+    case Bin of
+        %% Just a look-ahead, we want the end_tag separately
+        <<_:O/binary, $<, $/, TT, EE, XX, TT2, AA, RR, EE2, AA2, _/binary>>
+        when (TT =:= $t orelse TT =:= $T) andalso
+             (EE =:= $e orelse EE =:= $E) andalso
+             (XX =:= $x orelse XX =:= $X) andalso
+             (TT2 =:= $t orelse TT2 =:= $T) andalso
+             (AA =:= $a orelse AA =:= $A) andalso
+             (RR =:= $r orelse RR =:= $R) andalso
+             (EE2 =:= $e orelse EE2 =:= $E) andalso
+             (AA2 =:= $a orelse AA2 =:= $A) ->
+            Len = O - Start,
+            <<_:Start/binary, Raw:Len/binary, _/binary>> = Bin,
+            {{data, Raw, false}, S};
+        <<_:O/binary, C, _/binary>> ->
+            tokenize_textarea(Bin, ?INC_CHAR(S, C), Start);
+        <<_:Start/binary, Raw/binary>> ->
+            {{data, Raw, false}, S}
+    end.

Modified: incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_multipart.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_multipart.erl?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_multipart.erl (original)
+++ incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_multipart.erl Sat May 24 01:38:04 2008
@@ -6,7 +6,7 @@
 -module(mochiweb_multipart).
 -author('bob@mochimedia.com').
 
--export([parse_form/2]).
+-export([parse_form/1, parse_form/2]).
 -export([parse_multipart_request/2]).
 -export([test/0]).
 
@@ -16,6 +16,9 @@
 
 %% TODO: DOCUMENT THIS MODULE.
 
+parse_form(Req) ->
+    parse_form(Req, fun default_file_handler/2).
+
 parse_form(Req, FileHandler) ->
     Callback = fun (Next) -> parse_form_outer(Next, FileHandler, []) end,
     {_, _, Res} = parse_multipart_request(Req, Callback),
@@ -56,6 +59,17 @@
     H1 = Handler(Data),
     fun (Next) -> parse_form_file(Next, {Name, H1}, FileHandler, State) end.
 
+default_file_handler(Filename, ContentType) ->
+    default_file_handler_1(Filename, ContentType, []).
+
+default_file_handler_1(Filename, ContentType, Acc) ->
+    fun(eof) ->
+            Value = iolist_to_binary(lists:reverse(Acc)),
+            {Filename, ContentType, Value};
+       (Next) ->
+            default_file_handler_1(Filename, ContentType, [Next | Acc])
+    end.
+
 parse_multipart_request(Req, Callback) ->
     %% TODO: Support chunked?
     Length = list_to_integer(Req:get_header_value("content-length")),
@@ -89,7 +103,7 @@
 split_header(Line) ->
     {Name, [$: | Value]} = lists:splitwith(fun (C) -> C =/= $: end,
                                            binary_to_list(Line)),
-    {string:to_lower(string:strip(Name)),
+    {mochiweb_util:to_lower(string:strip(Name)),
      mochiweb_util:parse_header(Value)}.
 
 read_chunk(Req, Length) when Length > 0 ->
@@ -295,19 +309,6 @@
     ok = with_socket_server(ServerFun, ClientFun),
     ok.
 
-handler_test(Filename, ContentType) ->
-    fun (Next) ->
-            handler_test_read(Next, {Filename, ContentType}, [])
-    end.
-
-handler_test_read(eof, {Filename, ContentType}, Acc) ->
-    Value = iolist_to_binary(lists:reverse(Acc)),
-    {Filename, ContentType, Value};
-handler_test_read(Data, H, Acc) ->
-    Acc1 = [Data | Acc],
-    fun (Next) -> handler_test_read(Next, H, Acc1) end.
-
-
 test_parse_form() ->
     ContentType = "multipart/form-data; boundary=AaB03x",
     "AaB03x" = get_boundary(ContentType),
@@ -334,7 +335,7 @@
     ClientFun = fun (Socket) ->
                         Req = fake_request(Socket, ContentType,
                                            size(BinContent)),
-                        Res = parse_form(Req, fun handler_test/2),
+                        Res = parse_form(Req),
                         [{"submit-name", "Larry"},
                          {"files", {"file1.txt", {"text/plain",[]},
                                     <<"... contents of file1.txt ...">>}

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=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_request.erl (original)
+++ incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_request.erl Sat May 24 01:38:04 2008
@@ -386,7 +386,7 @@
                              [];
                          Binary ->
                              case get_primary_header_value("content-type") of
-                                 "application/x-www-form-urlencoded" ->
+                                 "application/x-www-form-urlencoded" ++ _ ->
                                      mochiweb_util:parse_qs(Binary);
                                  _ ->
                                      []

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=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_socket_server.erl (original)
+++ incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_socket_server.erl Sat May 24 01:38:04 2008
@@ -103,7 +103,8 @@
                 {packet, 0},
                 {backlog, Backlog},
                 {recbuf, 8192},
-                {active, false}],
+                {active, false},
+                {nodelay, true}],
     Opts = case Ip of
                any ->
                    BaseOpts;

Modified: incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_util.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_util.erl?rev=659773&r1=659772&r2=659773&view=diff
==============================================================================
--- incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_util.erl (original)
+++ incubator/couchdb/branches/runtimeconfig/src/mochiweb/mochiweb_util.erl Sat May 24 01:38:04 2008
@@ -11,6 +11,7 @@
 -export([guess_mime/1, parse_header/1]).
 -export([shell_quote/1, cmd/1, cmd_string/1, cmd_port/2]).
 -export([record_to_proplist/2, record_to_proplist/3]).
+-export([to_lower/1]).
 -export([test/0]).
 
 -define(PERCENT, 37).  % $\%
@@ -170,7 +171,7 @@
 urlsplit_scheme([], Acc) ->
     {"", lists:reverse(Acc)};
 urlsplit_scheme(":" ++ Rest, Acc) ->
-    {string:to_lower(lists:reverse(Acc)), Rest};
+    {to_lower(lists:reverse(Acc)), Rest};
 urlsplit_scheme([C | Rest], Acc) ->
     urlsplit_scheme(Rest, [C | Acc]).
 
@@ -322,11 +323,11 @@
                         %% Skip anything with no value
                         Acc;
                     {Name, [$\= | Value]} ->
-                        [{string:to_lower(string:strip(Name)),
+                        [{to_lower(string:strip(Name)),
                           unquote_header(string:strip(Value))} | Acc]
                 end
         end,
-    {string:to_lower(Type),
+    {to_lower(Type),
      lists:foldr(F, [], Parts)}.
 
 unquote_header("\"" ++ Rest) ->
@@ -369,6 +370,20 @@
 shell_quote([C | Rest], Acc) ->
     shell_quote(Rest, [C | Acc]).
 
+to_lower_char(C) when is_integer(C),  C >= $A, C =< $Z ->
+    C + 32;
+to_lower_char(C) when is_integer(C),  C >= 16#C1, C =< 16#D6 ->
+    C + 32;
+to_lower_char(C) when is_integer(C),  C >= 16#D8, C =< 16#DE ->
+    C + 32;
+to_lower_char(C) ->
+    C.
+
+to_lower(S) when is_list(S) ->
+    [to_lower_char(C) || C <- S];
+to_lower(C) when is_integer(C) ->
+    to_lower_char(C).
+
 test() ->
     test_join(),
     test_quote_plus(),



Mime
View raw message