You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by jc...@apache.org on 2009/03/05 07:14:39 UTC
svn commit: r750332 [1/2] - in /couchdb/branches/rep_security: ./ bin/
etc/couchdb/ etc/default/ etc/init/ share/ share/server/ share/www/
share/www/script/ share/www/script/test/ share/www/style/ src/couchdb/
src/ibrowse/ src/mochiweb/ test/
Author: jchris
Date: Thu Mar 5 06:14:36 2009
New Revision: 750332
URL: http://svn.apache.org/viewvc?rev=750332&view=rev
Log:
svn merge to bring rep_security branch up to date with trunk as of r750305
Added:
couchdb/branches/rep_security/share/www/script/test/etags_views.js
- copied, changed from r750305, couchdb/trunk/share/www/script/test/etags_views.js
couchdb/branches/rep_security/share/www/script/test/invalid_docids.js
- copied, changed from r750305, couchdb/trunk/share/www/script/test/invalid_docids.js
couchdb/branches/rep_security/share/www/script/test/list_views.js
- copied, changed from r750305, couchdb/trunk/share/www/script/test/list_views.js
couchdb/branches/rep_security/share/www/script/test/show_documents.js
- copied unchanged from r750305, couchdb/trunk/share/www/script/test/show_documents.js
couchdb/branches/rep_security/share/www/script/test/stats.js
- copied unchanged from r750305, couchdb/trunk/share/www/script/test/stats.js
couchdb/branches/rep_security/src/couchdb/couch_httpd_stats_handlers.erl
- copied unchanged from r750305, couchdb/trunk/src/couchdb/couch_httpd_stats_handlers.erl
couchdb/branches/rep_security/src/couchdb/couch_ref_counter.erl
- copied unchanged from r750305, couchdb/trunk/src/couchdb/couch_ref_counter.erl
couchdb/branches/rep_security/src/couchdb/couch_stats.hrl
- copied unchanged from r750305, couchdb/trunk/src/couchdb/couch_stats.hrl
couchdb/branches/rep_security/src/couchdb/couch_stats_aggregator.erl
- copied unchanged from r750305, couchdb/trunk/src/couchdb/couch_stats_aggregator.erl
couchdb/branches/rep_security/src/couchdb/couch_stats_collector.erl
- copied unchanged from r750305, couchdb/trunk/src/couchdb/couch_stats_collector.erl
Removed:
couchdb/branches/rep_security/src/couchdb/couch_file_stats.erl
Modified:
couchdb/branches/rep_security/ (props changed)
couchdb/branches/rep_security/THANKS
couchdb/branches/rep_security/acinclude.m4.in
couchdb/branches/rep_security/bin/Makefile.am
couchdb/branches/rep_security/bin/couchdb.tpl.in
couchdb/branches/rep_security/configure.ac
couchdb/branches/rep_security/etc/couchdb/default.ini.tpl.in
couchdb/branches/rep_security/etc/default/couchdb (props changed)
couchdb/branches/rep_security/etc/init/couchdb.tpl.in
couchdb/branches/rep_security/share/Makefile.am
couchdb/branches/rep_security/share/server/main.js
couchdb/branches/rep_security/share/www/couch_tests.html
couchdb/branches/rep_security/share/www/index.html
couchdb/branches/rep_security/share/www/script/couch.js
couchdb/branches/rep_security/share/www/script/couch_test_runner.js
couchdb/branches/rep_security/share/www/script/futon.browse.js
couchdb/branches/rep_security/share/www/script/jquery.couch.js
couchdb/branches/rep_security/share/www/script/test/ (props changed)
couchdb/branches/rep_security/share/www/script/test/attachments.js
couchdb/branches/rep_security/share/www/script/test/basics.js
couchdb/branches/rep_security/share/www/script/test/content_negotiation.js
couchdb/branches/rep_security/share/www/script/test/security_validation.js
couchdb/branches/rep_security/share/www/script/test/uuids.js
couchdb/branches/rep_security/share/www/script/test/view_errors.js
couchdb/branches/rep_security/share/www/style/layout.css
couchdb/branches/rep_security/src/couchdb/Makefile.am
couchdb/branches/rep_security/src/couchdb/couch_db.erl
couchdb/branches/rep_security/src/couchdb/couch_db.hrl
couchdb/branches/rep_security/src/couchdb/couch_db_updater.erl
couchdb/branches/rep_security/src/couchdb/couch_doc.erl
couchdb/branches/rep_security/src/couchdb/couch_file.erl
couchdb/branches/rep_security/src/couchdb/couch_httpd.erl
couchdb/branches/rep_security/src/couchdb/couch_httpd_db.erl
couchdb/branches/rep_security/src/couchdb/couch_httpd_external.erl
couchdb/branches/rep_security/src/couchdb/couch_httpd_misc_handlers.erl
couchdb/branches/rep_security/src/couchdb/couch_httpd_show.erl
couchdb/branches/rep_security/src/couchdb/couch_httpd_view.erl
couchdb/branches/rep_security/src/couchdb/couch_query_servers.erl
couchdb/branches/rep_security/src/couchdb/couch_rep.erl
couchdb/branches/rep_security/src/couchdb/couch_server.erl
couchdb/branches/rep_security/src/couchdb/couch_server_sup.erl
couchdb/branches/rep_security/src/couchdb/couch_stream.erl
couchdb/branches/rep_security/src/couchdb/couch_view.erl
couchdb/branches/rep_security/src/ibrowse/Makefile.am
couchdb/branches/rep_security/src/mochiweb/Makefile.am
couchdb/branches/rep_security/src/mochiweb/mochijson.erl
couchdb/branches/rep_security/src/mochiweb/mochijson2.erl
couchdb/branches/rep_security/src/mochiweb/mochiweb.app
couchdb/branches/rep_security/src/mochiweb/mochiweb_headers.erl
couchdb/branches/rep_security/src/mochiweb/mochiweb_html.erl
couchdb/branches/rep_security/src/mochiweb/mochiweb_http.erl
couchdb/branches/rep_security/src/mochiweb/mochiweb_request.erl
couchdb/branches/rep_security/src/mochiweb/mochiweb_util.erl
couchdb/branches/rep_security/test/runner.sh
couchdb/branches/rep_security/test/test.js
Propchange: couchdb/branches/rep_security/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Mar 5 06:14:36 2009
@@ -1 +1,2 @@
/couchdb/branches/form:729440-730015
+/couchdb/trunk:741843-750305
Modified: couchdb/branches/rep_security/THANKS
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/THANKS?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/THANKS (original)
+++ couchdb/branches/rep_security/THANKS Thu Mar 5 06:14:36 2009
@@ -26,5 +26,6 @@
* Brian Palmer <ji...@brian.codekitchen.net>
* Jason Davies <ja...@jasondavies.com>
* Maximillian Dornseif <md...@hudora.de>
+ * Eric Casteleijn <er...@canonical.com>
For a list of authors see the `AUTHORS` file.
Modified: couchdb/branches/rep_security/acinclude.m4.in
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/acinclude.m4.in?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/acinclude.m4.in (original)
+++ couchdb/branches/rep_security/acinclude.m4.in Thu Mar 5 06:14:36 2009
@@ -21,11 +21,10 @@
m4_define([LOCAL_VERSION_REVISION], [0])
m4_define([LOCAL_VERSION_STAGE], [a])
m4_define([LOCAL_VERSION_RELEASE], [%release%])
-m4_define([LOCAL_VERSION_STATUS], [incubating])
m4_define([LOCAL_VERSION_PRIMARY],
[LOCAL_VERSION_MAJOR.LOCAL_VERSION_MINOR.LOCAL_VERSION_REVISION])
m4_define([LOCAL_VERSION_SECONDARY],
- [LOCAL_VERSION_STAGE[]LOCAL_VERSION_RELEASE-LOCAL_VERSION_STATUS])
+ [LOCAL_VERSION_STAGE[]LOCAL_VERSION_RELEASE])
m4_define([LOCAL_VERSION],
[LOCAL_VERSION_PRIMARY[]LOCAL_VERSION_SECONDARY])
Modified: couchdb/branches/rep_security/bin/Makefile.am
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/bin/Makefile.am?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/bin/Makefile.am (original)
+++ couchdb/branches/rep_security/bin/Makefile.am Thu Mar 5 06:14:36 2009
@@ -29,7 +29,7 @@
-e "s|%bindir%|@bindir@|g" \
-e "s|%localerlanglibdir%|@localerlanglibdir@|g" \
-e "s|%couchdbebindir%|couch-@version@/ebin|g" \
- -e "s|%mochiwebebindir%|mochiweb-r82/ebin|g" \
+ -e "s|%mochiwebebindir%|mochiweb-r97/ebin|g" \
-e "s|%ibrowseebindir%|ibrowse-1.4.1/ebin|g" \
-e "s|%defaultini%|default.ini|g" \
-e "s|%localini%|local.ini|g" \
Modified: couchdb/branches/rep_security/bin/couchdb.tpl.in
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/bin/couchdb.tpl.in?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/bin/couchdb.tpl.in (original)
+++ couchdb/branches/rep_security/bin/couchdb.tpl.in Thu Mar 5 06:14:36 2009
@@ -20,6 +20,7 @@
KILL_BOOLEAN=false
SHUTDOWN_BOOLEAN=false
RECURSED_BOOLEAN=false
+RESET_CONFIG_BOOLEAN=true
RESPAWN_TIMEOUT=0
@@ -70,6 +71,7 @@
-h display a short help message and exit
-V display version information and exit
-c FILE use configuration FILE (chainable, resets system default)
+ -C FILE use configuration FILE (chainable, does not reset system default)
-i use the interactive Erlang shell
-b spawn as a background process
-p FILE set the background PID FILE (overrides system default)
@@ -168,7 +170,11 @@
interactive_option="+Bd -noinput"
fi
if test -n "$INI_FILES"; then
- ini_files="$INI_FILES"
+ if test "$RESET_CONFIG_BOOLEAN" = "true"; then
+ ini_files="$INI_FILES"
+ else
+ ini_files="$DEFAULT_INI_FILE $INI_FILES"
+ fi
else
ini_files="$DEFAULT_INI_FILE $LOCAL_INI_FILE"
fi
@@ -258,7 +264,7 @@
parse_script_option_list () {
set +e
- options=`getopt hVc:ibp:r:Ro:e:skd $@`
+ options=`getopt hVc:C:ibp:r:Ro:e:skd $@`
if test ! $? -eq 0; then
display_error
fi
@@ -269,6 +275,7 @@
-h) shift; display_help; exit $SCRIPT_OK;;
-V) shift; display_version; exit $SCRIPT_OK;;
-c) shift; INI_FILES="$INI_FILES $1"; shift;;
+ -C) shift; RESET_CONFIG_BOOLEAN=false; INI_FILES="$INI_FILES $1"; shift;;
-i) shift; INTERACTIVE_BOOLEAN=true;;
-b) shift; BACKGROUND_BOOLEAN=true;;
-r) shift; RESPAWN_TIMEOUT=$1; shift;;
Modified: couchdb/branches/rep_security/configure.ac
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/configure.ac?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/configure.ac (original)
+++ couchdb/branches/rep_security/configure.ac Thu Mar 5 06:14:36 2009
@@ -76,7 +76,7 @@
AC_ARG_VAR([FLAGS], [general flags to prepend to LDFLAGS and CPPFLAGS])
-LIB_FLAGS="-L/usr/local/lib -L/opt/local/lib $JS_LIB_FLAGS"
+LIB_FLAGS="$JS_LIB_FLAGS -L/usr/local/lib -L/opt/local/lib"
LIBS="$LIB_FLAGS $LIBS"
# XP_UNIX required for jsapi.h and has been tested to work on Linux and Darwin.
FLAGS="$LIB_FLAGS $ERLANG_FLAGS $JS_FLAGS -DXP_UNIX $FLAGS"
Modified: couchdb/branches/rep_security/etc/couchdb/default.ini.tpl.in
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/etc/couchdb/default.ini.tpl.in?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/etc/couchdb/default.ini.tpl.in (original)
+++ couchdb/branches/rep_security/etc/couchdb/default.ini.tpl.in Thu Mar 5 06:14:36 2009
@@ -4,8 +4,10 @@
[couchdb]
database_dir = %localstatelibdir%
+view_index_dir = %localstatelibdir%
util_driver_dir = %couchprivlibdir%
max_document_size = 4294967296 ; 4 GB
+max_attachment_chunk_size = 4294967296 ; 4GB
view_timeout = 5000 ; 5 seconds
max_dbs_open = 100
@@ -33,6 +35,8 @@
db_update_notifier={couch_db_update_notifier_sup, start_link, []}
query_servers={couch_query_servers, start_link, []}
httpd={couch_httpd, start_link, []}
+stats_aggregator={couch_stats_aggregator, start, []}
+stats_collector={couch_stats_collector, start, []}
[httpd_global_handlers]
/ = {couch_httpd_misc_handlers, handle_welcome_req, <<"Welcome">>}
@@ -40,12 +44,12 @@
_utils = {couch_httpd_misc_handlers, handle_utils_dir_req, "%localdatadir%/www"}
_all_dbs = {couch_httpd_misc_handlers, handle_all_dbs_req}
-_stats = {couch_httpd_misc_handlers, handle_stats_req}
_active_tasks = {couch_httpd_misc_handlers, handle_task_status_req}
_config = {couch_httpd_misc_handlers, handle_config_req}
_replicate = {couch_httpd_misc_handlers, handle_replicate_req}
_uuids = {couch_httpd_misc_handlers, handle_uuids_req}
_restart = {couch_httpd_misc_handlers, handle_restart_req}
+_stats = {couch_httpd_stats_handlers, handle_stats_req}
[httpd_db_handlers]
_view = {couch_httpd_view, handle_view_req}
Propchange: couchdb/branches/rep_security/etc/default/couchdb
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Mar 5 06:14:36 2009
@@ -1,2 +1,3 @@
/couchdb/branches/form/etc/default/couchdb:729440-730015
+/couchdb/trunk/etc/default/couchdb:741843-750305
/incubator/couchdb/trunk/etc/default/couchdb:642419-694440
Modified: couchdb/branches/rep_security/etc/init/couchdb.tpl.in
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/etc/init/couchdb.tpl.in?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/etc/init/couchdb.tpl.in (original)
+++ couchdb/branches/rep_security/etc/init/couchdb.tpl.in Thu Mar 5 06:14:36 2009
@@ -63,6 +63,9 @@
# Start Apache CouchDB as a background process.
command="$COUCHDB -b"
+ if test -n "$COUCHDB_PID_FILE"; then
+ command="$command -p $COUCHDB_PID_FILE"
+ fi
if test -n "$COUCHDB_STDOUT_FILE"; then
command="$command -o $COUCHDB_STDOUT_FILE"
fi
Modified: couchdb/branches/rep_security/share/Makefile.am
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/Makefile.am?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/Makefile.am (original)
+++ couchdb/branches/rep_security/share/Makefile.am Thu Mar 5 06:14:36 2009
@@ -71,4 +71,46 @@
www/script/jquery.resizer.js \
www/script/jquery.suggest.js \
www/script/json2.js \
+ www/script/test/basics.js \
+ www/script/test/delayed_commits.js \
+ www/script/test/all_docs.js \
+ www/script/test/conflicts.js \
+ www/script/test/recreate_doc.js \
+ www/script/test/copy_move_doc.js \
+ www/script/test/uuids.js \
+ www/script/test/bulk_docs.js \
+ www/script/test/lots_of_docs.js \
+ www/script/test/reduce.js \
+ www/script/test/reduce_false.js \
+ www/script/test/design_options.js \
+ www/script/test/multiple_rows.js \
+ www/script/test/large_docs.js \
+ www/script/test/utf8.js \
+ www/script/test/attachments.js \
+ www/script/test/attachment_paths.js \
+ www/script/test/attachment_views.js \
+ www/script/test/design_paths.js \
+ www/script/test/content_negotiation.js \
+ www/script/test/design_docs.js \
+ www/script/test/invalid_docids.js \
+ www/script/test/view_collation.js \
+ www/script/test/view_conflicts.js \
+ www/script/test/view_errors.js \
+ www/script/test/view_include_docs.js \
+ www/script/test/view_multi_key_all_docs.js \
+ www/script/test/view_multi_key_design.js \
+ www/script/test/view_multi_key_temp.js \
+ www/script/test/view_pagination.js \
+ www/script/test/view_sandboxing.js \
+ www/script/test/view_xml.js \
+ www/script/test/replication.js \
+ www/script/test/etags_head.js \
+ www/script/test/etags_views.js \
+ www/script/test/show_documents.js \
+ www/script/test/list_views.js \
+ www/script/test/compact.js \
+ www/script/test/purge.js \
+ www/script/test/config.js \
+ www/script/test/security_validation.js \
+ www/script/test/stats.js \
www/style/layout.css
Modified: couchdb/branches/rep_security/share/server/main.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/server/main.js?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/server/main.js [utf-8] (original)
+++ couchdb/branches/rep_security/share/server/main.js [utf-8] Thu Mar 5 06:14:36 2009
@@ -142,7 +142,7 @@
// this function provides a shortcut for managing responses by Accept header
respondWith = function(req, responders) {
var bestKey = null, accept = req.headers["Accept"];
- if (accept) {
+ if (accept && !req.query.format) {
var provides = [];
for (key in responders) {
if (mimesByKey[key]) {
@@ -151,6 +151,8 @@
}
var bestMime = Mimeparse.bestMatch(provides, accept);
bestKey = keysByMime[bestMime];
+ } else {
+ bestKey = req.query.format;
}
var rFunc = responders[bestKey || responders.fallback || "html"];
if (rFunc) {
@@ -352,25 +354,32 @@
var listFun = funs[0];
var head = cmd[1];
var req = cmd[2];
- row_line[listFun] = 0;
+ row_line[listFun] = { first_key: null, row_number: 0, prev_key: null };
runRenderFunction(listFun, [head, null, req, null]);
break;
case "list_row":
var listFun = funs[0];
var row = cmd[1];
var req = cmd[2];
- runRenderFunction(listFun, [null, row, req, row_line[listFun]]);
- row_line[listFun]++;
+ var row_info = row_line[listFun];
+ runRenderFunction(listFun, [null, row, req, row_info]);
+ if (row_info.first_key == null) {
+ row_info.first_key = row.key;
+ } else {
+ row_info.prev_key = row.key;
+ }
+ row_info.row_number++;
+ row_line[listFun] = row_info;
break;
case "list_tail":
var listFun = funs[0];
var req = cmd[1];
- var row_number = null;
+ var row_info = null;
try {
- row_number = row_line[listFun];
+ row_info = row_line[listFun];
delete row_line[listFun];
} catch (e) {}
- runRenderFunction(listFun, [null, null, req, row_number]);
+ runRenderFunction(listFun, [null, null, req, row_info]);
break;
default:
print(toJSON({error: "query_server_error",
Modified: couchdb/branches/rep_security/share/www/couch_tests.html
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/couch_tests.html?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/couch_tests.html [utf-8] (original)
+++ couchdb/branches/rep_security/share/www/couch_tests.html [utf-8] Thu Mar 5 06:14:36 2009
@@ -34,7 +34,7 @@
});
});
var testsPath = document.location.toString().split('?')[1];
- loadTests(testsPath||"script/couch_tests.js")
+ loadScript(testsPath||"script/couch_tests.js")
</script>
</head>
<body><div id="wrap">
Modified: couchdb/branches/rep_security/share/www/index.html
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/index.html?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/index.html [utf-8] (original)
+++ couchdb/branches/rep_security/share/www/index.html [utf-8] Thu Mar 5 06:14:36 2009
@@ -63,6 +63,7 @@
<tr>
<th>Name</th>
<th class="size">Size</th>
+ <th class="apps">Applications</th>
<th class="count">Number of Documents</th>
<th class="seq">Update Seq</th>
</tr>
@@ -71,7 +72,7 @@
</tbody>
<tbody class="footer">
<tr>
- <td colspan="4">
+ <td colspan="5">
<div id="paging">
<a class="prev">← Previous Page</a> |
<label>Rows per page: <select id="perpage">
Modified: couchdb/branches/rep_security/share/www/script/couch.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/couch.js?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/couch.js [utf-8] (original)
+++ couchdb/branches/rep_security/share/www/script/couch.js [utf-8] Thu Mar 5 06:14:36 2009
@@ -177,6 +177,10 @@
CouchDB.maybeThrowError(this.last_req);
return JSON.parse(this.last_req.responseText);
}
+
+ this.designDocs = function() {
+ return this.allDocs({startkey:"_design", endkey:"_design0"});
+ };
this.allDocsBySeq = function(options,keys) {
var req = null;
@@ -263,6 +267,15 @@
return JSON.parse(CouchDB.last_req.responseText);
}
+CouchDB.allDesignDocs = function() {
+ var ddocs = {}, dbs = CouchDB.allDbs();
+ for (var i=0; i < dbs.length; i++) {
+ var db = new CouchDB(dbs[i]);
+ ddocs[dbs[i]] = db.designDocs();
+ };
+ return ddocs;
+};
+
CouchDB.getVersion = function() {
CouchDB.last_req = CouchDB.request("GET", "/");
CouchDB.maybeThrowError(CouchDB.last_req);
@@ -300,6 +313,16 @@
return req;
}
+CouchDB.requestStats = function(module, key, test) {
+ var query_arg = "";
+ if(test !== null) {
+ query_arg = "?flush=true";
+ }
+
+ var stat = CouchDB.request("GET", "/_stats/" + module + "/" + key + query_arg).responseText;
+ return JSON.parse(stat)[module][key];
+}
+
CouchDB.uuids_cache = [];
CouchDB.newUuids = function(n) {
@@ -313,7 +336,7 @@
}
return uuids;
} else {
- CouchDB.last_req = CouchDB.request("POST", "/_uuids?count=" + (100 + n));
+ CouchDB.last_req = CouchDB.request("GET", "/_uuids?count=" + (100 + n));
CouchDB.maybeThrowError(CouchDB.last_req);
var result = JSON.parse(CouchDB.last_req.responseText);
CouchDB.uuids_cache =
@@ -332,3 +355,13 @@
throw result;
}
}
+
+CouchDB.params = function(options) {
+ options = options || {};
+ var returnArray = [];
+ for(var key in options) {
+ var value = options[key];
+ returnArray.push(key + "=" + value);
+ }
+ return returnArray.join("&");
+}
\ No newline at end of file
Modified: couchdb/branches/rep_security/share/www/script/couch_test_runner.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/couch_test_runner.js?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/couch_test_runner.js (original)
+++ couchdb/branches/rep_security/share/www/script/couch_test_runner.js Thu Mar 5 06:14:36 2009
@@ -12,10 +12,6 @@
// *********************** Test Framework of Sorts ************************* //
-function loadTests(url) {
- document.write('<script src="'+url+'"></script>');
-};
-
function loadScript(url) {
if (typeof document != "undefined") document.write('<script src="'+url+'"></script>');
};
@@ -114,7 +110,7 @@
var name = $(cell).text();
var win = window.open("", name, "width=700,height=500,resizable=yes,scrollbars=yes");
win.document.title = name;
- $("<pre></pre>").text(tests[name].toString()).appendTo(win.document.body).fadeIn();
+ $("<pre></pre>").text(couchTests[name].toString()).appendTo(win.document.body).fadeIn();
}
function updateTestsListing() {
@@ -156,13 +152,13 @@
// display the line that failed.
// Example:
// T(MyValue==1);
-function T(arg1, arg2) {
+function T(arg1, arg2, testName) {
if (!arg1) {
if (currentRow) {
if ($("td.details ol", currentRow).length == 0) {
$("<ol></ol>").appendTo($("td.details", currentRow));
}
- $("<li><b>Assertion failed:</b> <code class='failure'></code></li>")
+ $("<li><b>Assertion " + (testName ? "'" + testName + "'" : "") + " failed:</b> <code class='failure'></code></li>")
.find("code").text((arg2 != null ? arg2 : arg1).toString()).end()
.appendTo($("td.details ol", currentRow));
}
@@ -170,6 +166,10 @@
}
}
+function TEquals(expected, actual, testName) {
+ T(equals(expected, actual), "expected '" + expected + "', got '" + actual + "'", testName);
+}
+
function equals(a,b) {
if (a === b) return true;
try {
Modified: couchdb/branches/rep_security/share/www/script/futon.browse.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/futon.browse.js?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/futon.browse.js [utf-8] (original)
+++ couchdb/branches/rep_security/share/www/script/futon.browse.js [utf-8] Thu Mar 5 06:14:36 2009
@@ -52,9 +52,16 @@
$("#databases tbody.content").append("<tr>" +
"<th><a href='database.html?" + encodeURIComponent(dbName) + "'>" +
dbName + "</a></th>" +
- "<td class='size'></td><td class='count'></td>" +
+ "<td class='size'></td><td class='apps'></td><td class='count'></td>" +
"<td class='seq'></td></tr>");
- $.couch.db(dbName).info({
+ var db = $.couch.db(dbName);
+ db.allApps({
+ eachApp : function(name, path) {
+ $("#databases tbody.content tr:eq(" + idx + ")")
+ .find("td.apps").append('<a href="'+path+'">'+name+'</a> ');
+ }
+ });
+ db.info({
success: function(info) {
$("#databases tbody.content tr:eq(" + idx + ")")
.find("td.size").text($.futon.formatSize(info.disk_size)).end()
Modified: couchdb/branches/rep_security/share/www/script/jquery.couch.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/jquery.couch.js?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/jquery.couch.js [utf-8] (original)
+++ couchdb/branches/rep_security/share/www/script/jquery.couch.js [utf-8] Thu Mar 5 06:14:36 2009
@@ -173,6 +173,38 @@
}
});
},
+ allDesignDocs: function(options) {
+ options = options || {};
+ this.allDocs($.extend({startkey:"_design", endkey:"_design0"}, options));
+ },
+ allApps: function(options) {
+ options = options || {};
+ var self = this;
+ if (options.eachApp) {
+ this.allDesignDocs({
+ success: function(resp) {
+ $.each(resp.rows, function() {
+ self.openDoc(this.id, {
+ success: function(ddoc) {
+ var index, appPath, appName = ddoc._id.split('/');
+ appName.shift();
+ appName = appName.join('/');
+ index = ddoc.couchapp && ddoc.couchapp.index;
+ if (index) {
+ appPath = ['', name, index[0], appName, index[1]].join('/');
+ } else if (ddoc._attachments && ddoc._attachments["index.html"]) {
+ appPath = ['', name, '_design', appName, "index.html"].join('/');
+ }
+ if (appPath) options.eachApp(appName, appPath, ddoc);
+ }
+ });
+ });
+ }
+ });
+ } else {
+ alert("please provide an eachApp function for allApps()");
+ }
+ },
openDoc: function(docId, options) {
options = options || {};
$.ajax({
Propchange: couchdb/branches/rep_security/share/www/script/test/
------------------------------------------------------------------------------
svn:mergeinfo =
Modified: couchdb/branches/rep_security/share/www/script/test/attachments.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/test/attachments.js?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/test/attachments.js (original)
+++ couchdb/branches/rep_security/share/www/script/test/attachments.js Thu Mar 5 06:14:36 2009
@@ -33,7 +33,7 @@
T(xhr.responseText == "This is a base64 encoded text");
T(xhr.getResponseHeader("Content-Type") == "text/plain");
T(xhr.getResponseHeader("Etag") == '"' + save_response.rev + '"');
-
+
// empty attachment
var binAttDoc2 = {
_id: "bin_doc2",
Modified: couchdb/branches/rep_security/share/www/script/test/basics.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/test/basics.js?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/test/basics.js (original)
+++ couchdb/branches/rep_security/share/www/script/test/basics.js Thu Mar 5 06:14:36 2009
@@ -141,4 +141,4 @@
var locs = loc.split('/');
T(locs[4] == resp.id);
T(locs[3] == "test_suite_db");
- };
\ No newline at end of file
+ };
Modified: couchdb/branches/rep_security/share/www/script/test/content_negotiation.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/test/content_negotiation.js?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/test/content_negotiation.js (original)
+++ couchdb/branches/rep_security/share/www/script/test/content_negotiation.js Thu Mar 5 06:14:36 2009
@@ -20,6 +20,10 @@
xhr = CouchDB.request("GET", "/test_suite_db/");
T(xhr.getResponseHeader("Content-Type") == "text/plain;charset=utf-8");
+ // make sure JSON responses end in a newline
+ var text = xhr.responseText;
+ T(text[text.length-1] == "\n");
+
xhr = CouchDB.request("GET", "/test_suite_db/", {
headers: {"Accept": "text/html;text/plain;*/*"}
});
Copied: couchdb/branches/rep_security/share/www/script/test/etags_views.js (from r750305, couchdb/trunk/share/www/script/test/etags_views.js)
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/test/etags_views.js?p2=couchdb/branches/rep_security/share/www/script/test/etags_views.js&p1=couchdb/trunk/share/www/script/test/etags_views.js&r1=750305&r2=750332&rev=750332&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/test/etags_views.js (original)
+++ couchdb/branches/rep_security/share/www/script/test/etags_views.js Thu Mar 5 06:14:36 2009
@@ -42,8 +42,7 @@
T(db.save(designDoc).ok);
var xhr;
var docs = makeDocs(0, 10);
- var saveResult = db.bulkSave(docs);
- T(saveResult.ok);
+ db.bulkSave(docs);
// verify get w/Etag on map view
xhr = CouchDB.request("GET", "/test_suite_db/_view/etags/basicView");
Copied: couchdb/branches/rep_security/share/www/script/test/invalid_docids.js (from r750305, couchdb/trunk/share/www/script/test/invalid_docids.js)
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/test/invalid_docids.js?p2=couchdb/branches/rep_security/share/www/script/test/invalid_docids.js&p1=couchdb/trunk/share/www/script/test/invalid_docids.js&r1=750305&r2=750332&rev=750332&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/test/invalid_docids.js (original)
+++ couchdb/branches/rep_security/share/www/script/test/invalid_docids.js Thu Mar 5 06:14:36 2009
@@ -23,32 +23,32 @@
//Test non-string
try {
db.save({"_id": 1});
- T(1 == 0);
+ T(1 == 0, "doc id must be string");
} catch(e) {
T(db.last_req.status == 400);
- T(e.error == "invalid_doc");
+ T(e.error == "bad_request");
}
// Test invalid _prefix
try {
db.save({"_id": "_invalid"});
- T(1 == 0);
+ T(1 == 0, "doc id may not start with underscore");
} catch(e) {
T(db.last_req.status == 400);
- T(e.error == "invalid_doc");
+ T(e.error == "bad_request");
}
// Test _bulk_docs explicitly.
var docs = [{"_id": "_design/foo"}, {"_id": "_local/bar"}];
- T(db.bulkSave(docs).ok);
+ db.bulkSave(docs);
docs.forEach(function(d) {T(db.open(d._id)._id == d._id);});
docs = [{"_id": "_invalid"}];
try {
db.bulkSave(docs);
- T(1 == 0);
+ T(1 == 0, "doc id may not start with underscore, even in bulk docs");
} catch(e) {
T(db.last_req.status == 400);
- T(e.error == "invalid_doc");
+ T(e.error == "bad_request");
}
};
Copied: couchdb/branches/rep_security/share/www/script/test/list_views.js (from r750305, couchdb/trunk/share/www/script/test/list_views.js)
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/test/list_views.js?p2=couchdb/branches/rep_security/share/www/script/test/list_views.js&p1=couchdb/trunk/share/www/script/test/list_views.js&r1=750305&r2=750332&rev=750332&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/test/list_views.js (original)
+++ couchdb/branches/rep_security/share/www/script/test/list_views.js Thu Mar 5 06:14:36 2009
@@ -137,8 +137,7 @@
T(db.save(designDoc).ok);
var docs = makeDocs(0, 10);
- var saveResult = db.bulkSave(docs);
- T(saveResult.ok);
+ db.bulkSave(docs);
var view = db.view('lists/basicView');
T(view.total_rows == 10);
@@ -207,8 +206,7 @@
// verify the etags expire correctly
var docs = makeDocs(11, 12);
- var saveResult = db.bulkSave(docs);
- T(saveResult.ok);
+ db.bulkSave(docs);
xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/simpleForm/withReduce?group=true", {
headers: {"if-none-match": etag}
Modified: couchdb/branches/rep_security/share/www/script/test/security_validation.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/test/security_validation.js?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/test/security_validation.js (original)
+++ couchdb/branches/rep_security/share/www/script/test/security_validation.js Thu Mar 5 06:14:36 2009
@@ -11,236 +11,236 @@
// the License.
couchTests.security_validation = function(debug) {
- // This tests couchdb's security and validation features. This does
- // not test authentication, except to use test authentication code made
- // specifically for this testing. It is a WWWW-Authenticate scheme named
- // X-Couch-Test-Auth, and the user names and passwords are hard coded
- // on the server-side.
- //
- // We could have used Basic authentication, however the XMLHttpRequest
- // implementation for Firefox and Safari, and probably other browsers are
- // broken (Firefox always prompts the user on 401 failures, Safari gives
- // odd security errors when using different name/passwords, perhaps due
- // to cross site scripting prevention). These problems essentially make Basic
- // authentication testing in the browser impossible. But while hard to
- // test automated in the browser, Basic auth may still useful for real
- // world use where these bugs/behaviors don't matter.
- //
- // So for testing purposes we are using this custom X-Couch-Test-Auth.
- // It's identical to Basic auth, except it doesn't even base64 encode
- // the "username:password" string, it's sent completely plain text.
- // Firefox and Safari both deal with this correctly (which is to say
- // they correctly do nothing special).
-
-
- var db = new CouchDB("test_suite_db");
- db.deleteDb();
- db.createDb();
- if (debug) debugger;
-
- run_on_modified_server(
+ // This tests couchdb's security and validation features. This does
+ // not test authentication, except to use test authentication code made
+ // specifically for this testing. It is a WWWW-Authenticate scheme named
+ // X-Couch-Test-Auth, and the user names and passwords are hard coded
+ // on the server-side.
+ //
+ // We could have used Basic authentication, however the XMLHttpRequest
+ // implementation for Firefox and Safari, and probably other browsers are
+ // broken (Firefox always prompts the user on 401 failures, Safari gives
+ // odd security errors when using different name/passwords, perhaps due
+ // to cross site scripting prevention). These problems essentially make Basic
+ // authentication testing in the browser impossible. But while hard to
+ // test automated in the browser, Basic auth may still useful for real
+ // world use where these bugs/behaviors don't matter.
+ //
+ // So for testing purposes we are using this custom X-Couch-Test-Auth.
+ // It's identical to Basic auth, except it doesn't even base64 encode
+ // the "username:password" string, it's sent completely plain text.
+ // Firefox and Safari both deal with this correctly (which is to say
+ // they correctly do nothing special).
+
+
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ run_on_modified_server(
[{section: "httpd",
key: "authentication_handler",
value: "{couch_httpd, special_test_authentication_handler}"},
{section:"httpd",
key: "WWW-Authenticate",
value: "X-Couch-Test-Auth"}],
-
+
function () {
- // try saving document usin the wrong credentials
- var wrongPasswordDb = new CouchDB("test_suite_db",
- {"WWW-Authenticate": "X-Couch-Test-Auth Damien Katz:foo"}
- );
-
- try {
- wrongPasswordDb.save({foo:1,author:"Damien Katz"});
- T(false && "Can't get here. Should have thrown an error 1");
- } catch (e) {
- T(e.error == "unauthorized");
- T(wrongPasswordDb.last_req.status == 401);
- }
-
-
- // Create the design doc that will run custom validation code
- var designDoc = {
- _id:"_design/test",
- language: "javascript",
- validate_doc_update: "(" + (function (newDoc, oldDoc, userCtx) {
- // docs should have an author field.
- if (!newDoc._deleted && !newDoc.author) {
- throw {forbidden:
- "Documents must have an author field"};
- }
- if (oldDoc && oldDoc.author != userCtx.name) {
- throw {unauthorized:
- "You are not the author of this document. You jerk."};
- }
- }).toString() + ")"
- }
-
- // Save a document normally
- var userDb = new CouchDB("test_suite_db",
- {"WWW-Authenticate": "X-Couch-Test-Auth Damien Katz:pecan pie"}
- );
-
- T(userDb.save({_id:"testdoc", foo:1, author:"Damien Katz"}).ok);
-
- // Attempt to save the design as a non-admin
- try {
- userDb.save(designDoc);
- T(false && "Can't get here. Should have thrown an error on design doc");
- } catch (e) {
- T(e.error == "unauthorized");
- T(userDb.last_req.status == 401);
- }
-
- // add user as admin
- db.setAdmins(["Damien Katz"]);
-
- T(userDb.save(designDoc).ok);
-
- // update the document
- var doc = userDb.open("testdoc");
- doc.foo=2;
- T(userDb.save(doc).ok);
-
- // Save a document that's missing an author field.
- try {
- userDb.save({foo:1});
- T(false && "Can't get here. Should have thrown an error 2");
- } catch (e) {
- T(e.error == "forbidden");
- T(userDb.last_req.status == 403);
- }
-
- // Now attempt to update the document as a different user, Jan
- var user2Db = new CouchDB("test_suite_db",
- {"WWW-Authenticate": "X-Couch-Test-Auth Jan Lehnardt:apple"}
- );
-
- var doc = user2Db.open("testdoc");
- doc.foo=3;
- try {
- user2Db.save(doc);
- T(false && "Can't get here. Should have thrown an error 3");
- } catch (e) {
- T(e.error == "unauthorized");
- T(user2Db.last_req.status == 401);
- }
-
- // Now have Damien change the author to Jan
- doc = userDb.open("testdoc");
- doc.author="Jan Lehnardt";
- T(userDb.save(doc).ok);
-
- // Now update the document as Jan
- doc = user2Db.open("testdoc");
- doc.foo = 3;
- T(user2Db.save(doc).ok);
-
- // Damien can't delete it
- try {
- userDb.deleteDoc(doc);
- T(false && "Can't get here. Should have thrown an error 4");
- } catch (e) {
- T(e.error == "unauthorized");
- T(userDb.last_req.status == 401);
- }
-
- // Now delete document
- T(user2Db.deleteDoc(doc).ok);
-
-
- // Now test replication
- var AuthHeaders = {"WWW-Authenticate": "X-Couch-Test-Auth Christopher Lenz:dog food"};
- var host = CouchDB.host;
- var dbPairs = [
- {source:"test_suite_db_a",
- target:"test_suite_db_b",
- options:{}},
-
- {source:"test_suite_db_a",
- target:"http://" + host + "/test_suite_db_b",
- options: {target_headers: AuthHeaders}},
-
- {source:"http://" + host + "/test_suite_db_a",
- target:"test_suite_db_b",
- options: {source_headers: AuthHeaders}},
-
- {source:"http://" + host + "/test_suite_db_a",
- target:"http://" + host + "/test_suite_db_b",
- options:{source_headers: AuthHeaders, target_headers: AuthHeaders}},
- ]
- var adminDbA = new CouchDB("test_suite_db_a");
- var adminDbB = new CouchDB("test_suite_db_b");
- var dbA = new CouchDB("test_suite_db_a",
- {"WWW-Authenticate": "X-Couch-Test-Auth Christopher Lenz:dog food"});
- var dbB = new CouchDB("test_suite_db_b",
- {"WWW-Authenticate": "X-Couch-Test-Auth Christopher Lenz:dog food"});
- var xhr;
- for (var testPair = 0; testPair < dbPairs.length; testPair++) {
- var A = dbPairs[testPair].source
- var B = dbPairs[testPair].target
- var Options = dbPairs[testPair].options
-
- adminDbA.deleteDb();
- adminDbA.createDb();
- adminDbB.deleteDb();
- adminDbB.createDb();
-
- // save and replicate a documents that will and will not pass our design
- // doc validation function.
- dbA.save({_id:"foo1",value:"a",author:"Noah Slater"});
- dbA.save({_id:"foo2",value:"a",author:"Christopher Lenz"});
- dbA.save({_id:"bad1",value:"a"});
-
- T(CouchDB.replicate(A, B).ok);
- T(CouchDB.replicate(B, A).ok);
-
- T(dbA.open("foo1"));
- T(dbB.open("foo1"));
- T(dbA.open("foo2"));
- T(dbB.open("foo2"));
-
- // save the design doc to dbA
- delete designDoc._rev; // clear rev from previous saves
- adminDbA.save(designDoc);
-
- // no affect on already saved docs
- T(dbA.open("bad1"));
-
- // Update some docs on dbB. Since the design hasn't replicated, anything
- // is allowed.
-
- // this edit will fail validation on replication to dbA (no author)
- T(dbB.save({_id:"bad2",value:"a"}).ok);
-
- // this edit will fail security on replication to dbA (wrong author
- // replicating the change)
- var foo1 = dbB.open("foo1");
- foo1.value = "b";
- dbB.save(foo1);
-
- // this is a legal edit
- var foo2 = dbB.open("foo2");
- foo2.value = "b";
- dbB.save(foo2);
-
- var results = CouchDB.replicate(B, A);
-
- T(results.ok);
-
- T(results.history[0].docs_written == 2);
- T(results.history[0].doc_write_failures == 1);
-
- // bad2 should not be on dbA
- T(dbA.open("bad2") == null);
-
- // The edit to foo1 should not have replicated.
- T(dbA.open("foo1").value == "a");
-
- // The edit to foo2 should have replicated.
- T(dbA.open("foo2").value == "a");
- }
+ // try saving document usin the wrong credentials
+ var wrongPasswordDb = new CouchDB("test_suite_db",
+ {"WWW-Authenticate": "X-Couch-Test-Auth Damien Katz:foo"}
+ );
+
+ try {
+ wrongPasswordDb.save({foo:1,author:"Damien Katz"});
+ T(false && "Can't get here. Should have thrown an error 1");
+ } catch (e) {
+ T(e.error == "unauthorized");
+ T(wrongPasswordDb.last_req.status == 401);
+ }
+
+
+ // Create the design doc that will run custom validation code
+ var designDoc = {
+ _id:"_design/test",
+ language: "javascript",
+ validate_doc_update: "(" + (function (newDoc, oldDoc, userCtx) {
+ // docs should have an author field.
+ if (!newDoc._deleted && !newDoc.author) {
+ throw {forbidden:
+ "Documents must have an author field"};
+ }
+ if (oldDoc && oldDoc.author != userCtx.name) {
+ throw {unauthorized:
+ "You are not the author of this document. You jerk."};
+ }
+ }).toString() + ")"
+ }
+
+ // Save a document normally
+ var userDb = new CouchDB("test_suite_db",
+ {"WWW-Authenticate": "X-Couch-Test-Auth Damien Katz:pecan pie"}
+ );
+
+ T(userDb.save({_id:"testdoc", foo:1, author:"Damien Katz"}).ok);
+
+ // Attempt to save the design as a non-admin
+ try {
+ userDb.save(designDoc);
+ T(false && "Can't get here. Should have thrown an error on design doc");
+ } catch (e) {
+ T(e.error == "unauthorized");
+ T(userDb.last_req.status == 401);
+ }
+
+ // add user as admin
+ db.setAdmins(["Damien Katz"]);
+
+ T(userDb.save(designDoc).ok);
+
+ // update the document
+ var doc = userDb.open("testdoc");
+ doc.foo=2;
+ T(userDb.save(doc).ok);
+
+ // Save a document that's missing an author field.
+ try {
+ userDb.save({foo:1});
+ T(false && "Can't get here. Should have thrown an error 2");
+ } catch (e) {
+ T(e.error == "forbidden");
+ T(userDb.last_req.status == 403);
+ }
+
+ // Now attempt to update the document as a different user, Jan
+ var user2Db = new CouchDB("test_suite_db",
+ {"WWW-Authenticate": "X-Couch-Test-Auth Jan Lehnardt:apple"}
+ );
+
+ var doc = user2Db.open("testdoc");
+ doc.foo=3;
+ try {
+ user2Db.save(doc);
+ T(false && "Can't get here. Should have thrown an error 3");
+ } catch (e) {
+ T(e.error == "unauthorized");
+ T(user2Db.last_req.status == 401);
+ }
+
+ // Now have Damien change the author to Jan
+ doc = userDb.open("testdoc");
+ doc.author="Jan Lehnardt";
+ T(userDb.save(doc).ok);
+
+ // Now update the document as Jan
+ doc = user2Db.open("testdoc");
+ doc.foo = 3;
+ T(user2Db.save(doc).ok);
+
+ // Damien can't delete it
+ try {
+ userDb.deleteDoc(doc);
+ T(false && "Can't get here. Should have thrown an error 4");
+ } catch (e) {
+ T(e.error == "unauthorized");
+ T(userDb.last_req.status == 401);
+ }
+
+ // Now delete document
+ T(user2Db.deleteDoc(doc).ok);
+
+
+ // Now test replication
+ var AuthHeaders = {"WWW-Authenticate": "X-Couch-Test-Auth Christopher Lenz:dog food"};
+ var host = CouchDB.host;
+ var dbPairs = [
+ {source:"test_suite_db_a",
+ target:"test_suite_db_b",
+ options:{}},
+
+ {source:"test_suite_db_a",
+ target:"http://" + host + "/test_suite_db_b",
+ options: {target_headers: AuthHeaders}},
+
+ {source:"http://" + host + "/test_suite_db_a",
+ target:"test_suite_db_b",
+ options: {source_headers: AuthHeaders}},
+
+ {source:"http://" + host + "/test_suite_db_a",
+ target:"http://" + host + "/test_suite_db_b",
+ options:{source_headers: AuthHeaders, target_headers: AuthHeaders}},
+ ]
+ var adminDbA = new CouchDB("test_suite_db_a");
+ var adminDbB = new CouchDB("test_suite_db_b");
+ var dbA = new CouchDB("test_suite_db_a",
+ {"WWW-Authenticate": "X-Couch-Test-Auth Christopher Lenz:dog food"});
+ var dbB = new CouchDB("test_suite_db_b",
+ {"WWW-Authenticate": "X-Couch-Test-Auth Christopher Lenz:dog food"});
+ var xhr;
+ for (var testPair = 0; testPair < dbPairs.length; testPair++) {
+ var A = dbPairs[testPair].source
+ var B = dbPairs[testPair].target
+ var Options = dbPairs[testPair].options
+
+ adminDbA.deleteDb();
+ adminDbA.createDb();
+ adminDbB.deleteDb();
+ adminDbB.createDb();
+
+ // save and replicate a documents that will and will not pass our design
+ // doc validation function.
+ dbA.save({_id:"foo1",value:"a",author:"Noah Slater"});
+ dbA.save({_id:"foo2",value:"a",author:"Christopher Lenz"});
+ dbA.save({_id:"bad1",value:"a"});
+
+ T(CouchDB.replicate(A, B).ok);
+ T(CouchDB.replicate(B, A).ok);
+
+ T(dbA.open("foo1"));
+ T(dbB.open("foo1"));
+ T(dbA.open("foo2"));
+ T(dbB.open("foo2"));
+
+ // save the design doc to dbA
+ delete designDoc._rev; // clear rev from previous saves
+ adminDbA.save(designDoc);
+
+ // no affect on already saved docs
+ T(dbA.open("bad1"));
+
+ // Update some docs on dbB. Since the design hasn't replicated, anything
+ // is allowed.
+
+ // this edit will fail validation on replication to dbA (no author)
+ T(dbB.save({_id:"bad2",value:"a"}).ok);
+
+ // this edit will fail security on replication to dbA (wrong author
+ // replicating the change)
+ var foo1 = dbB.open("foo1");
+ foo1.value = "b";
+ dbB.save(foo1);
+
+ // this is a legal edit
+ var foo2 = dbB.open("foo2");
+ foo2.value = "b";
+ dbB.save(foo2);
+
+ var results = CouchDB.replicate(B, A);
+
+ T(results.ok);
+
+ T(results.history[0].docs_written == 2);
+ T(results.history[0].doc_write_failures == 1);
+
+ // bad2 should not be on dbA
+ T(dbA.open("bad2") == null);
+
+ // The edit to foo1 should not have replicated.
+ T(dbA.open("foo1").value == "a");
+
+ // The edit to foo2 should have replicated.
+ T(dbA.open("foo2").value == "a");
+ }
});
-};
\ No newline at end of file
+};
Modified: couchdb/branches/rep_security/share/www/script/test/uuids.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/test/uuids.js?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/test/uuids.js (original)
+++ couchdb/branches/rep_security/share/www/script/test/uuids.js Thu Mar 5 06:14:36 2009
@@ -11,20 +11,33 @@
// the License.
couchTests.uuids = function(debug) {
+ var testHashBustingHeaders = function(xhr) {
+ T(xhr.getResponseHeader("Cache-Control").match(/no-cache/));
+ T(xhr.getResponseHeader("Pragma") == "no-cache");
+
+ var currentTime = new Date();
+ var expiresHeader = Date.parse(xhr.getResponseHeader("Expires"));
+ var dateHeader = Date.parse(xhr.getResponseHeader("Date"));
+
+ T(expiresHeader < currentTime);
+ T(currentTime - dateHeader < 3000);
+ };
+
var db = new CouchDB("test_suite_db");
db.deleteDb();
db.createDb();
if (debug) debugger;
// a single UUID without an explicit count
- var xhr = CouchDB.request("POST", "/_uuids");
+ var xhr = CouchDB.request("GET", "/_uuids");
T(xhr.status == 200);
var result = JSON.parse(xhr.responseText);
T(result.uuids.length == 1);
var first = result.uuids[0];
+ testHashBustingHeaders(xhr);
// a single UUID with an explicit count
- xhr = CouchDB.request("POST", "/_uuids?count=1");
+ xhr = CouchDB.request("GET", "/_uuids?count=1");
T(xhr.status == 200);
result = JSON.parse(xhr.responseText);
T(result.uuids.length == 1);
@@ -32,7 +45,7 @@
T(first != second);
// no collisions with 1,000 UUIDs
- xhr = CouchDB.request("POST", "/_uuids?count=1000");
+ xhr = CouchDB.request("GET", "/_uuids?count=1000");
T(xhr.status == 200);
result = JSON.parse(xhr.responseText);
T( result.uuids.length == 1000 );
@@ -43,5 +56,7 @@
seen[id] = 1;
}
- // check our library
+ // ensure we return a 405 on POST
+ xhr = CouchDB.request("POST", "/_uuids?count=1000");
+ T(xhr.status == 405);
};
Modified: couchdb/branches/rep_security/share/www/script/test/view_errors.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/test/view_errors.js?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/test/view_errors.js (original)
+++ couchdb/branches/rep_security/share/www/script/test/view_errors.js Thu Mar 5 06:14:36 2009
@@ -40,4 +40,13 @@
emit([doc._id, doc.undef], null);
});
T(results.total_rows == 0);
+
+ // querying a view with invalid params should give a resonable error message
+ var xhr = CouchDB.request("POST", "/test_suite_db/_temp_view?startkey=foo", {
+ headers: {"Content-Type": "application/json"},
+ body: JSON.stringify({language: "javascript",
+ map : "function(doc){emit(doc.integer)}"
+ })
+ });
+ T(JSON.parse(xhr.responseText).error == "invalid_json");
};
Modified: couchdb/branches/rep_security/share/www/style/layout.css
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/style/layout.css?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/style/layout.css (original)
+++ couchdb/branches/rep_security/share/www/style/layout.css Thu Mar 5 06:14:36 2009
@@ -336,8 +336,8 @@
/* Database table */
-#databases thead th.size, #databases thead th.count, #databases thead th.seq,
-#databases tbody td.size, #databases tbody td.count, #databases tbody td.seq {
+#databases thead th.apps, #databases thead th.size, #databases thead th.count, #databases thead th.seq,
+#databases thead th.apps, #databases tbody td.size, #databases tbody td.count, #databases tbody td.seq {
text-align: right;
}
Modified: couchdb/branches/rep_security/src/couchdb/Makefile.am
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/Makefile.am?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/Makefile.am (original)
+++ couchdb/branches/rep_security/src/couchdb/Makefile.am Thu Mar 5 06:14:36 2009
@@ -51,20 +51,23 @@
couch_external_manager.erl \
couch_external_server.erl \
couch_file.erl \
- couch_file_stats.erl \
couch_httpd.erl \
couch_httpd_db.erl \
couch_httpd_external.erl \
couch_httpd_show.erl \
couch_httpd_view.erl \
couch_httpd_misc_handlers.erl \
+ couch_httpd_stats_handlers.erl \
couch_key_tree.erl \
couch_log.erl \
couch_os_process.erl \
couch_query_servers.erl \
+ couch_ref_counter.erl \
couch_rep.erl \
couch_server.erl \
couch_server_sup.erl \
+ couch_stats_aggregator.erl \
+ couch_stats_collector.erl \
couch_stream.erl \
couch_task_status.erl \
couch_util.erl \
@@ -73,7 +76,7 @@
couch_view_group.erl \
couch_db_updater.erl
-EXTRA_DIST = $(source_files) couch_db.hrl
+EXTRA_DIST = $(source_files) couch_db.hrl couch_stats.hrl
compiled_files = \
couch.app \
@@ -88,20 +91,23 @@
couch_external_manager.beam \
couch_external_server.beam \
couch_file.beam \
- couch_file_stats.beam \
couch_httpd.beam \
couch_httpd_db.beam \
couch_httpd_external.beam \
couch_httpd_show.beam \
couch_httpd_view.beam \
couch_httpd_misc_handlers.beam \
+ couch_httpd_stats_handlers.beam \
couch_key_tree.beam \
couch_log.beam \
couch_os_process.beam \
couch_query_servers.beam \
+ couch_ref_counter.beam \
couch_rep.beam \
couch_server.beam \
couch_server_sup.beam \
+ couch_stats_aggregator.beam \
+ couch_stats_collector.beam \
couch_stream.beam \
couch_task_status.beam \
couch_util.beam \
@@ -150,7 +156,7 @@
# $(ERL) -noshell -run edoc_run files [\"$<\"]
%.beam: %.erl couch_db.hrl
- $(ERLC) $<
+ $(ERLC) ${TEST} $<;
install-data-hook:
if test -f "$(DESTDIR)/$(couchprivlibdir)/couch_erl_driver"; then \
Modified: couchdb/branches/rep_security/src/couchdb/couch_db.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/couch_db.erl?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/couch_db.erl (original)
+++ couchdb/branches/rep_security/src/couchdb/couch_db.erl Thu Mar 5 06:14:36 2009
@@ -14,8 +14,8 @@
-behaviour(gen_server).
-export([open/2,close/1,create/2,start_compact/1,get_db_info/1]).
--export([open_ref_counted/2,num_refs/1,monitor/1,count_changes_since/2]).
--export([update_doc/3,update_docs/4,update_docs/2,update_docs/3]).
+-export([open_ref_counted/2,is_idle/1,monitor/1,count_changes_since/2]).
+-export([update_doc/3,update_docs/4,update_docs/2,update_docs/3,delete_doc/3]).
-export([get_doc_info/2,open_doc/2,open_doc/3,open_doc_revs/4]).
-export([get_missing_revs/2,name/1,doc_to_tree/1,get_update_seq/1,get_committed_update_seq/1]).
-export([enum_docs/4,enum_docs/5,enum_docs_since/4,enum_docs_since/5]).
@@ -24,7 +24,6 @@
-export([start_link/3,make_doc/2,set_admins/2,get_admins/1,ensure_full_commit/1]).
-export([init/1,terminate/2,handle_call/3,handle_cast/2,code_change/3,handle_info/2]).
-
-include("couch_db.hrl").
@@ -68,15 +67,15 @@
ok = gen_server:call(UpdatePid, full_commit, infinity),
{ok, StartTime}.
-close(#db{fd=Fd}) ->
- couch_file:drop_ref(Fd).
+close(#db{fd_ref_counter=RefCntr}) ->
+ couch_ref_counter:drop(RefCntr).
open_ref_counted(MainPid, UserCtx) ->
- {ok, Db} = gen_server:call(MainPid, {open_ref_counted_instance, self()}),
+ {ok, Db} = gen_server:call(MainPid, {open_ref_count, self()}),
{ok, Db#db{user_ctx=UserCtx}}.
-num_refs(MainPid) ->
- gen_server:call(MainPid, num_refs).
+is_idle(MainPid) ->
+ gen_server:call(MainPid, is_idle).
monitor(#db{main_pid=MainPid}) ->
erlang:monitor(process, MainPid).
@@ -84,10 +83,16 @@
start_compact(#db{update_pid=Pid}) ->
gen_server:cast(Pid, start_compact).
+delete_doc(Db, Id, Revisions) ->
+ DeletedDocs = [#doc{id=Id, revs=[Rev], deleted=true} || Rev <- Revisions],
+ {ok, [Result]} = update_docs(Db, DeletedDocs, []),
+ {ok, Result}.
+
open_doc(Db, IdOrDocInfo) ->
open_doc(Db, IdOrDocInfo, []).
open_doc(Db, Id, Options) ->
+ couch_stats_collector:increment({couchdb, database_reads}),
case open_doc_int(Db, Id, Options) of
{ok, #doc{deleted=true}=Doc} ->
case lists:member(deleted, Options) of
@@ -101,6 +106,7 @@
end.
open_doc_revs(Db, Id, Revs, Options) ->
+ couch_stats_collector:increment({couchdb, database_reads}),
[Result] = open_doc_revs_int(Db, [{Id, Revs}], Options),
Result.
@@ -398,6 +404,7 @@
end.
update_docs(Db, Docs, Options, replicated_changes) ->
+ couch_stats_collector:increment({couchdb, database_writes}),
DocBuckets = group_alike_docs(Docs),
case should_validate(Db, Docs) of
@@ -416,6 +423,7 @@
{ok, DocErrors};
update_docs(Db, Docs, Options, interactive_edit) ->
+ couch_stats_collector:increment({couchdb, database_writes}),
% go ahead and generate the new revision ids for the documents.
Docs2 = lists:map(
fun(#doc{id=Id,revs={Start, RevIds}}=Doc) ->
@@ -501,8 +509,14 @@
% written to a different file
SizeAcc + Len;
{_Key, {_Type, Bin}} when is_binary(Bin) ->
+ % we have a new binary to write
SizeAcc + size(Bin);
+ {_Key, {_Type, {Fun, undefined}}} when is_function(Fun) ->
+ % function without a known length
+ % we'll have to alloc as we go with this one, for now, nothing
+ SizeAcc;
{_Key, {_Type, {Fun, Len}}} when is_function(Fun) ->
+ % function to yield binary data with known length
SizeAcc + Len
end
end,
@@ -510,7 +524,6 @@
{ok, OutputStream} = couch_stream:open(Fd),
ok = couch_stream:ensure_buffer(OutputStream, PreAllocSize),
-
NewBins = lists:map(
fun({Key, {Type, BinValue}}) ->
NewBinValue =
@@ -537,6 +550,17 @@
Bin when is_binary(Bin) ->
{ok, StreamPointer} = couch_stream:write(OutputStream, Bin),
{Fd, StreamPointer, size(Bin)};
+ {StreamFun, undefined} when is_function(StreamFun) ->
+ % max_attachment_chunk_size control the max we buffer in memory
+ MaxChunkSize = list_to_integer(couch_config:get("couchdb",
+ "max_attachment_chunk_size","4294967296")),
+ WriterFun = make_writer_fun(OutputStream),
+ % StreamFun(MaxChunkSize, WriterFun)
+ % will call our WriterFun
+ % once for each chunk of the attachment.
+ {ok, {TotalLength, NewStreamPointer}} =
+ StreamFun(MaxChunkSize, WriterFun, {0, nil}),
+ {Fd, NewStreamPointer, TotalLength};
{Fun, Len} when is_function(Fun) ->
{ok, StreamPointer} =
write_streamed_attachment(OutputStream, Fun, Len, nil),
@@ -546,8 +570,27 @@
end, Bins),
{ok, _FinalPos} = couch_stream:close(OutputStream),
-
Doc#doc{attachments = NewBins}.
+
+
+make_writer_fun(Stream) ->
+ % WriterFun({Length, Binary}, State)
+ % WriterFun({0, _Footers}, State)
+ % Called with Length == 0 on the last time.
+ % WriterFun returns NewState.
+ fun
+ ({0, _Footers}, {FinalLen, SpFin}) ->
+ % last block, return the final tuple
+ {ok, {FinalLen, SpFin}};
+ ({Length, Bin}, {Total, nil}) ->
+ % save StreamPointer
+ {ok, StreamPointer} = couch_stream:write(Stream, Bin),
+ {Total+Length, StreamPointer};
+ ({Length, Bin}, {Total, SpAcc}) ->
+ % write the Bin to disk
+ {ok, _Sp} = couch_stream:write(Stream, Bin),
+ {Total+Length, SpAcc}
+ end.
write_streamed_attachment(_Stream, _F, 0, SpAcc) ->
{ok, SpAcc};
@@ -597,23 +640,28 @@
init({DbName, Filepath, Fd, Options}) ->
{ok, UpdaterPid} = gen_server:start_link(couch_db_updater, {self(), DbName, Filepath, Fd, Options}, []),
- ok = couch_file:add_ref(Fd),
- gen_server:call(UpdaterPid, get_db).
+ {ok, #db{fd_ref_counter=RefCntr}=Db} = gen_server:call(UpdaterPid, get_db),
+ couch_ref_counter:add(RefCntr),
+ {ok, Db}.
terminate(_Reason, _Db) ->
ok.
-handle_call({open_ref_counted_instance, OpenerPid}, _From, #db{fd=Fd}=Db) ->
- ok = couch_file:add_ref(Fd, OpenerPid),
+handle_call({open_ref_count, OpenerPid}, _, #db{fd_ref_counter=RefCntr}=Db) ->
+ ok = couch_ref_counter:add(RefCntr, OpenerPid),
{reply, {ok, Db}, Db};
-handle_call(num_refs, _From, #db{fd=Fd}=Db) ->
- {reply, couch_file:num_refs(Fd) - 1, Db};
-handle_call({db_updated, #db{fd=NewFd}=NewDb}, _From, #db{fd=OldFd}) ->
- case NewFd == OldFd of
+handle_call(is_idle, _From,
+ #db{fd_ref_counter=RefCntr, compactor_pid=Compact}=Db) ->
+ % Idle means no referrers. Unless in the middle of a compaction file switch,
+ % there are always at least 2 referrers, couch_db_updater and us.
+ {reply, (Compact == nil) and (couch_ref_counter:count(RefCntr) == 2), Db};
+handle_call({db_updated, #db{fd_ref_counter=NewRefCntr}=NewDb}, _From,
+ #db{fd_ref_counter=OldRefCntr}) ->
+ case NewRefCntr == OldRefCntr of
true -> ok;
false ->
- couch_file:add_ref(NewFd),
- couch_file:drop_ref(OldFd)
+ couch_ref_counter:add(NewRefCntr),
+ couch_ref_counter:drop(OldRefCntr)
end,
{reply, ok, NewDb}.
@@ -763,4 +811,4 @@
}.
-
\ No newline at end of file
+
Modified: couchdb/branches/rep_security/src/couchdb/couch_db.hrl
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/couch_db.hrl?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/couch_db.hrl (original)
+++ couchdb/branches/rep_security/src/couchdb/couch_db.hrl Thu Mar 5 06:14:36 2009
@@ -122,6 +122,7 @@
compactor_pid=nil,
instance_start_time, % number of microsecs since jan 1 1970 as a binary string
fd,
+ fd_ref_counter,
header = #db_header{},
summary_stream,
fulldocinfo_by_id_btree,
@@ -160,15 +161,21 @@
send_row
}).
+-record(reduce_fold_helper_funs, {
+ start_response,
+ send_row
+}).
+
-record(extern_resp_args, {
code = 200,
+ stop = false,
data = <<>>,
ctype = "application/json",
headers = []
}).
-record(group,
- {type=view, % can also be slow_view
+ {type=view, % can also be temp_view
sig=nil,
db=nil,
fd=nil,
Modified: couchdb/branches/rep_security/src/couchdb/couch_db_updater.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/couch_db_updater.erl?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/couch_db_updater.erl (original)
+++ couchdb/branches/rep_security/src/couchdb/couch_db_updater.erl Thu Mar 5 06:14:36 2009
@@ -22,7 +22,6 @@
-define(HEADER_SIG, <<$g, $m, $k, 0>>).
init({MainPid, DbName, Filepath, Fd, Options}) ->
- link(Fd),
case lists:member(create, Options) of
true ->
% create a new header and writes it to the file
@@ -38,8 +37,8 @@
Db2 = refresh_validate_doc_funs(Db),
{ok, Db2#db{main_pid=MainPid}}.
-terminate(_Reason, Db) ->
- close_db(Db).
+terminate(_Reason, _Db) ->
+ ok.
handle_call(get_db, _From, Db) ->
{reply, {ok, Db}, Db};
@@ -173,7 +172,7 @@
ok = file:rename(CompactFilepath, Filepath),
couch_stream:close(Db#db.summary_stream),
- couch_file:close_maybe(Db#db.fd),
+ couch_ref_counter:drop(Db#db.fd_ref_counter),
ok = gen_server:call(Db#db.main_pid, {db_updated, NewDb2}),
?LOG_INFO("Compaction for db \"~s\" completed.", [Db#db.name]),
@@ -282,10 +281,11 @@
{MegaSecs, Secs, MicroSecs} = now(),
StartTime = ?l2b(io_lib:format("~p",
[(MegaSecs*1000000*1000000) + (Secs*1000000) + MicroSecs])),
-
+ {ok, RefCntr} = couch_ref_counter:start([Fd]),
#db{
update_pid=self(),
fd=Fd,
+ fd_ref_counter = RefCntr,
header=Header,
summary_stream = SummaryStream,
fulldocinfo_by_id_btree = IdBtree,
@@ -300,10 +300,6 @@
}.
-close_db(#db{fd=Fd,summary_stream=Ss}) ->
- couch_file:close(Fd),
- couch_stream:close(Ss).
-
refresh_validate_doc_funs(Db) ->
{ok, DesignDocs} = get_design_docs(Db),
ProcessDocFuns = lists:flatmap(
@@ -632,8 +628,7 @@
ok = couch_file:write_header(Fd, ?HEADER_SIG, Header=#db_header{})
end,
NewDb = init_db(Name, CompactFile, Fd, Header),
- NewDb2 = copy_compact(Db, NewDb, Retry),
- close_db(NewDb2),
+ _NewDb2 = copy_compact(Db, NewDb, Retry),
gen_server:cast(Db#db.update_pid, {compact_done, CompactFile}).
Modified: couchdb/branches/rep_security/src/couchdb/couch_doc.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/couch_doc.erl?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/couch_doc.erl (original)
+++ couchdb/branches/rep_security/src/couchdb/couch_doc.erl Thu Mar 5 06:14:36 2009
@@ -112,7 +112,7 @@
transfer_fields(Props, #doc{body=[]});
from_json_obj(_Other) ->
- throw({invalid_json_object, "Document must be a JSON object"}).
+ throw({bad_request, "Document must be a JSON object"}).
parse_rev(Rev) when is_binary(Rev) ->
parse_rev(?b2l(Rev));
@@ -131,11 +131,18 @@
Doc#doc{body={lists:reverse(Fields)}};
transfer_fields([{<<"_id">>, Id} | Rest], Doc) when is_binary(Id) ->
+ case Id of
+ <<"_design/", _/binary>> -> ok;
+ <<"_local/", _/binary>> -> ok;
+ <<"_", _/binary>> ->
+ throw({bad_request, <<"Only reserved document ids may start with underscore.">>});
+ _Else -> ok
+ end,
transfer_fields(Rest, Doc#doc{id=Id});
transfer_fields([{<<"_id">>, Id} | _Rest], _Doc) ->
?LOG_DEBUG("Document id is not a string: ~p", [Id]),
- throw({invalid_document_id, "Document id is not a string"});
+ throw({bad_request, <<"Document id must be a string">>});
transfer_fields([{<<"_rev">>, Rev} | Rest], #doc{revs={0, []}}=Doc) ->
{Pos, RevId} = parse_rev(Rev),
Modified: couchdb/branches/rep_security/src/couchdb/couch_file.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/couch_file.erl?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/couch_file.erl (original)
+++ couchdb/branches/rep_security/src/couchdb/couch_file.erl Thu Mar 5 06:14:36 2009
@@ -20,7 +20,6 @@
-export([open/1, open/2, close/1, pread/3, pwrite/3, expand/2, bytes/1, sync/1]).
-export([append_term/2, pread_term/2,write_header/3, read_header/2, truncate/2]).
-export([init/1, terminate/2, handle_call/3, handle_cast/2, code_change/3, handle_info/2]).
--export([close_maybe/1,drop_ref/1,drop_ref/2,add_ref/1,add_ref/2,num_refs/1]).
%%----------------------------------------------------------------------
%% Args: Valid Options are [create] and [create,overwrite].
@@ -36,7 +35,6 @@
case gen_server:start_link(couch_file,
{Filepath, Options, self(), Ref = make_ref()}, []) of
{ok, Fd} ->
- couch_file_stats:track_file(Fd),
{ok, Fd};
ignore ->
% get the error
@@ -168,26 +166,6 @@
Result = gen_server:cast(Fd, close),
catch unlink(Fd),
Result.
-
-close_maybe(Fd) ->
- catch unlink(Fd),
- catch gen_server:cast(Fd, close_maybe).
-
-drop_ref(Fd) ->
- drop_ref(Fd, self()).
-
-drop_ref(Fd, Pid) ->
- gen_server:cast(Fd, {drop_ref, Pid}).
-
-
-add_ref(Fd) ->
- add_ref(Fd, self()).
-
-add_ref(Fd, Pid) ->
- gen_server:call(Fd, {add_ref, Pid}).
-
-num_refs(Fd) ->
- gen_server:call(Fd, num_refs).
write_header(Fd, Prefix, Data) ->
@@ -307,12 +285,14 @@
true ->
{ok, 0} = file:position(Fd, 0),
ok = file:truncate(Fd),
+ couch_stats_collector:increment({couchdb, open_os_files}),
{ok, Fd};
false ->
ok = file:close(Fd),
init_status_error(ReturnPid, Ref, file_exists)
end;
false ->
+ couch_stats_collector:increment({couchdb, open_os_files}),
{ok, Fd}
end;
Error ->
@@ -324,6 +304,7 @@
{ok, Fd_Read} ->
{ok, Fd} = file:open(Filepath, [read, write, raw, binary]),
ok = file:close(Fd_Read),
+ couch_stats_collector:increment({couchdb, open_os_files}),
{ok, Fd};
Error ->
init_status_error(ReturnPid, Ref, Error)
@@ -332,6 +313,7 @@
terminate(_Reason, _Fd) ->
+ couch_stats_collector:decrement({couchdb, open_os_files}),
ok.
@@ -357,66 +339,15 @@
handle_call({pread_bin, Pos}, _From, Fd) ->
{ok, <<TermLen:32>>} = file:pread(Fd, Pos, 4),
{ok, Bin} = file:pread(Fd, Pos + 4, TermLen),
- {reply, {ok, Bin}, Fd};
-handle_call({add_ref, Pid},_From, Fd) ->
- case get(Pid) of
- undefined ->
- put(Pid, {erlang:monitor(process, Pid), 1});
- {MonRef, RefCnt} ->
- put(Pid, {MonRef, RefCnt + 1})
- end,
- {reply, ok, Fd};
-handle_call(num_refs, _From, Fd) ->
- {monitors, Monitors} = process_info(self(), monitors),
- {reply, length(Monitors), Fd}.
+ {reply, {ok, Bin}, Fd}.
handle_cast(close, Fd) ->
- {stop,normal,Fd};
-handle_cast(close_maybe, Fd) ->
- maybe_close_async(Fd);
-handle_cast({drop_ref, Pid}, Fd) ->
- case get(Pid) of
- {MonRef, 1} ->
- erase(Pid),
- % don't check return of demonitor. The process could haved crashed causing
- % the {'DOWN', ...} message to be sent and the process unmonitored.
- erlang:demonitor(MonRef, [flush]);
- {MonRef, Num} ->
- put(Pid, {MonRef, Num-1})
- end,
- maybe_close_async(Fd).
+ {stop,normal,Fd}.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
-handle_info({'EXIT', _Pid, Reason}, Fd) ->
- {stop, Reason, Fd};
-handle_info({'DOWN', MonitorRef, _Type, Pid, _Info}, Fd) ->
- {MonitorRef, _RefCount} = erase(Pid),
- maybe_close_async(Fd).
-
-
-
-should_close(_Fd) ->
- case process_info(self(), links) of
- {links, [_]} ->
- % no linkers left (except our fd port). What about monitors?
- case process_info(self(), monitors) of
- {monitors, []} ->
- true;
- _ ->
- false
- end;
- {links, [_|_]} ->
- false
- end.
-
-maybe_close_async(Fd) ->
- case should_close(Fd) of
- true ->
- {stop,normal,Fd};
- false ->
- {noreply,Fd}
- end.
+handle_info({'EXIT', _, Reason}, Fd) ->
+ {stop, Reason, Fd}.
Modified: couchdb/branches/rep_security/src/couchdb/couch_httpd.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/couch_httpd.erl?rev=750332&r1=750331&r2=750332&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/couch_httpd.erl (original)
+++ couchdb/branches/rep_security/src/couchdb/couch_httpd.erl Thu Mar 5 06:14:36 2009
@@ -16,12 +16,12 @@
-export([start_link/0, stop/0, handle_request/3]).
-export([header_value/2,header_value/3,qs_value/2,qs_value/3,qs/1,path/1,absolute_uri/2]).
--export([verify_is_server_admin/1,unquote/1,quote/1,recv/2,error_info/1]).
+-export([verify_is_server_admin/1,unquote/1,quote/1,recv/2,recv_chunked/4,error_info/1]).
-export([parse_form/1,json_body/1,body/1,doc_etag/1, make_etag/1, etag_respond/3]).
-export([primary_header_value/2,partition/1,serve_file/3]).
-export([start_chunked_response/3,send_chunk/2]).
-export([start_json_response/2, start_json_response/3, end_json_response/1]).
--export([send_response/4,send_method_not_allowed/2,send_error/4]).
+-export([send_response/4,send_method_not_allowed/2,send_error/4, send_redirect/2]).
-export([send_json/2,send_json/3,send_json/4]).
-export([default_authentication_handler/1,special_test_authentication_handler/1]).
@@ -102,6 +102,7 @@
handle_request(MochiReq, UrlHandlers, DbUrlHandlers) ->
+ statistics(runtime), % prepare request_time counter, see end of function
AuthenticationFun = make_arity_1_fun(
couch_config:get("httpd", "authentication_handler")),
% for the path, use the raw path with the query string and fragment
@@ -123,11 +124,8 @@
mochiweb_headers:to_list(MochiReq:get(headers))
]),
- Method =
+ Method1 =
case MochiReq:get(method) of
- % alias HEAD to GET as mochiweb takes care of stripping the body
- 'HEAD' -> 'GET';
-
% already an atom
Meth when is_atom(Meth) -> Meth;
@@ -135,6 +133,15 @@
% possible (if any module references the atom, then it's existing).
Meth -> couch_util:to_existing_atom(Meth)
end,
+
+ increment_method_stats(Method1),
+
+ % alias HEAD to GET as mochiweb takes care of stripping the body
+ Method = case Method1 of
+ 'HEAD' -> 'GET';
+ Other -> Other
+ end,
+
HttpReq = #httpd{
mochi_req = MochiReq,
method = Method,
@@ -151,7 +158,7 @@
catch
throw:Error ->
send_error(HttpReq, Error);
- Tag:Error when Error == foo ->
+ Tag:Error ->
?LOG_ERROR("Uncaught error in HTTP request: ~p",[{Tag, Error}]),
?LOG_DEBUG("Stacktrace: ~p",[erlang:get_stacktrace()]),
send_error(HttpReq, Error)
@@ -163,8 +170,13 @@
RawUri,
Resp:get(code)
]),
+ {_TotalRuntime, RequestTime} = statistics(runtime),
+ couch_stats_collector:record({couchdb, request_time}, RequestTime),
+ couch_stats_collector:increment({httpd, requests}),
{ok, Resp}.
+increment_method_stats(Method) ->
+ couch_stats_collector:increment({httpd_request_methods, Method}).
special_test_authentication_handler(Req) ->
case header_value(Req, "WWW-Authenticate") of
@@ -260,6 +272,12 @@
recv(#httpd{mochi_req=MochiReq}, Len) ->
MochiReq:recv(Len).
+recv_chunked(#httpd{mochi_req=MochiReq}, MaxChunkSize, ChunkFun, InitState) ->
+ % Fun is called once with each chunk
+ % Fun({Length, Binary}, State)
+ % called with Length == 0 on the last time.
+ MochiReq:stream_body(MaxChunkSize, ChunkFun, InitState).
+
body(#httpd{mochi_req=MochiReq}) ->
% Maximum size of document PUT request body (4GB)
MaxSize = list_to_integer(
@@ -319,6 +337,7 @@
start_chunked_response(#httpd{mochi_req=MochiReq}, Code, Headers) ->
+ couch_stats_collector:increment({httpd_status_codes, Code}),
{ok, MochiReq:respond({Code, Headers ++ server_header(), chunked})}.
send_chunk(Resp, Data) ->
@@ -326,6 +345,7 @@
{ok, Resp}.
send_response(#httpd{mochi_req=MochiReq}, Code, Headers, Body) ->
+ couch_stats_collector:increment({httpd_status_codes, Code}),
if Code >= 400 ->
?LOG_DEBUG("HTTPd ~p error response:~n ~s", [Code, Body]);
true -> ok
@@ -346,7 +366,8 @@
{"Content-Type", negotiate_content_type(Req)},
{"Cache-Control", "must-revalidate"}
],
- send_response(Req, Code, DefaultHeaders ++ Headers, ?JSON_ENCODE(Value)).
+ send_response(Req, Code, DefaultHeaders ++ Headers,
+ list_to_binary([?JSON_ENCODE(Value), $\n])).
start_json_response(Req, Code) ->
start_json_response(Req, Code, []).
@@ -359,6 +380,7 @@
start_chunked_response(Req, Code, DefaultHeaders ++ Headers).
end_json_response(Resp) ->
+ send_chunk(Resp, [$\n]),
send_chunk(Resp, []).
@@ -407,6 +429,9 @@
{[{<<"error">>, ErrorStr},
{<<"reason">>, ReasonStr}]}).
+ send_redirect(Req, Path) ->
+ Headers = [{"Location", couch_httpd:absolute_uri(Req, Path)}],
+ send_response(Req, 301, Headers, <<>>).
negotiate_content_type(#httpd{mochi_req=MochiReq}) ->
%% Determine the appropriate Content-Type header for a JSON response