You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ja...@apache.org on 2008/05/24 10:38:05 UTC
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/
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: " + 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: " + 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() ->
<<"&quot;\"word <<up!&quot;">> =
escape(<<""\"word <<up!"">>),
@@ -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(),