Damien, the new files share/www/script/test/auth_cache.js and src/couchdb/couch_js_functions.hrl are missing in the diff.
cheers On Wed, Jun 23, 2010 at 8:11 PM, <[email protected]> wrote: > Author: damien > Date: Wed Jun 23 19:11:50 2010 > New Revision: 957314 > > URL: http://svn.apache.org/viewvc?rev=957314&view=rev > Log: > Authentication caching, to avoid repeated opening and closing of the users > database for each request requiring authentication. COUCHDB-807 > > Modified: > couchdb/trunk/etc/couchdb/default.ini.tpl.in > couchdb/trunk/share/Makefile.am > couchdb/trunk/share/www/script/couch_tests.js > couchdb/trunk/share/www/script/test/users_db.js > couchdb/trunk/src/couchdb/Makefile.am > couchdb/trunk/src/couchdb/couch_db.erl > couchdb/trunk/src/couchdb/couch_db.hrl > couchdb/trunk/src/couchdb/couch_db_updater.erl > couchdb/trunk/src/couchdb/couch_file.erl > couchdb/trunk/src/couchdb/couch_httpd_auth.erl > couchdb/trunk/src/couchdb/couch_httpd_db.erl > couchdb/trunk/src/couchdb/couch_httpd_oauth.erl > couchdb/trunk/src/couchdb/couch_server.erl > couchdb/trunk/src/couchdb/priv/stat_descriptions.cfg.in > > Modified: couchdb/trunk/etc/couchdb/default.ini.tpl.in > URL: > http://svn.apache.org/viewvc/couchdb/trunk/etc/couchdb/default.ini.tpl.in?rev=957314&r1=957313&r2=957314&view=diff > > ============================================================================== > --- couchdb/trunk/etc/couchdb/default.ini.tpl.in (original) > +++ couchdb/trunk/etc/couchdb/default.ini.tpl.in Wed Jun 23 19:11:50 2010 > @@ -31,6 +31,7 @@ include_sasl = true > authentication_db = _users > require_valid_user = false > timeout = 600 ; number of seconds before automatic logout > +auth_cache_size = 50 ; size is number of cache entries > > [query_servers] > javascript = %bindir%/%couchjs_command_name% > %localbuilddatadir%/server/main.js > @@ -55,6 +56,7 @@ httpd={couch_httpd, start_link, []} > stats_aggregator={couch_stats_aggregator, start, []} > stats_collector={couch_stats_collector, start, []} > uuids={couch_uuids, start, []} > +auth_cache={couch_auth_cache, start_link, []} > > [httpd_global_handlers] > / = {couch_httpd_misc_handlers, handle_welcome_req, <<"Welcome">>} > > Modified: couchdb/trunk/share/Makefile.am > URL: > http://svn.apache.org/viewvc/couchdb/trunk/share/Makefile.am?rev=957314&r1=957313&r2=957314&view=diff > > ============================================================================== > --- couchdb/trunk/share/Makefile.am (original) > +++ couchdb/trunk/share/Makefile.am Wed Jun 23 19:11:50 2010 > @@ -110,6 +110,7 @@ nobase_dist_localdata_DATA = \ > www/script/test/attachment_names.js \ > www/script/test/attachment_paths.js \ > www/script/test/attachment_views.js \ > + www/script/test/auth_cache.js \ > www/script/test/basics.js \ > www/script/test/batch_save.js \ > www/script/test/bulk_docs.js \ > > Modified: couchdb/trunk/share/www/script/couch_tests.js > URL: > http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/couch_tests.js?rev=957314&r1=957313&r2=957314&view=diff > > ============================================================================== > --- couchdb/trunk/share/www/script/couch_tests.js [utf-8] (original) > +++ couchdb/trunk/share/www/script/couch_tests.js [utf-8] Wed Jun 23 > 19:11:50 2010 > @@ -35,6 +35,7 @@ loadTest("attachments_multipart.js"); > loadTest("attachment_names.js"); > loadTest("attachment_paths.js"); > loadTest("attachment_views.js"); > +loadTest("auth_cache.js"); > loadTest("batch_save.js"); > loadTest("bulk_docs.js"); > loadTest("changes.js"); > > Modified: couchdb/trunk/share/www/script/test/users_db.js > URL: > http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/users_db.js?rev=957314&r1=957313&r2=957314&view=diff > > ============================================================================== > --- couchdb/trunk/share/www/script/test/users_db.js (original) > +++ couchdb/trunk/share/www/script/test/users_db.js Wed Jun 23 19:11:50 > 2010 > @@ -24,8 +24,6 @@ couchTests.users_db = function(debug) { > // to determine the actual users db name. > > function testFun() { > - usersDb.deleteDb(); > - > // test that the validation function is installed > var ddoc = usersDb.open("_design/_auth"); > T(ddoc.validate_doc_update); > @@ -89,10 +87,12 @@ couchTests.users_db = function(debug) { > > }; > > + usersDb.deleteDb(); > run_on_modified_server( > [{section: "couch_httpd_auth", > - key: "authentication_db", value: "test_suite_users"}], > + key: "authentication_db", value: usersDb.name}], > testFun > ); > + usersDb.deleteDb(); // cleanup > > } > \ No newline at end of file > > Modified: couchdb/trunk/src/couchdb/Makefile.am > URL: > http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/Makefile.am?rev=957314&r1=957313&r2=957314&view=diff > > ============================================================================== > --- couchdb/trunk/src/couchdb/Makefile.am (original) > +++ couchdb/trunk/src/couchdb/Makefile.am Wed Jun 23 19:11:50 2010 > @@ -17,7 +17,7 @@ couchlibdir = $(localerlanglibdir)/couch > couchincludedir = $(couchlibdir)/include > couchebindir = $(couchlibdir)/ebin > > -couchinclude_DATA = couch_db.hrl > +couchinclude_DATA = couch_db.hrl couch_js_functions.hrl > couchebin_DATA = $(compiled_files) > > # dist_devdoc_DATA = $(doc_base) $(doc_modules) > @@ -29,6 +29,7 @@ CLEANFILES = $(compiled_files) $(doc_bas > source_files = \ > couch.erl \ > couch_app.erl \ > + couch_auth_cache.erl \ > couch_btree.erl \ > couch_changes.erl \ > couch_config.erl \ > @@ -80,12 +81,13 @@ source_files = \ > couch_db_updater.erl \ > couch_work_queue.erl > > -EXTRA_DIST = $(source_files) couch_db.hrl > +EXTRA_DIST = $(source_files) couch_db.hrl couch_js_functions.hrl > > compiled_files = \ > couch.app \ > couch.beam \ > couch_app.beam \ > + couch_auth_cache.beam \ > couch_btree.beam \ > couch_changes.beam \ > couch_config.beam \ > @@ -194,6 +196,6 @@ endif > > # $(ERL) -noshell -run edoc_run files [\"$<\"] > > -%.beam: %.erl couch_db.hrl > +%.beam: %.erl couch_db.hrl couch_js_functions.hrl > $(ERLC) $(ERLC_FLAGS) ${TEST} $<; > > > Modified: couchdb/trunk/src/couchdb/couch_db.erl > URL: > http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_db.erl?rev=957314&r1=957313&r2=957314&view=diff > > ============================================================================== > --- couchdb/trunk/src/couchdb/couch_db.erl (original) > +++ couchdb/trunk/src/couchdb/couch_db.erl Wed Jun 23 19:11:50 2010 > @@ -114,7 +114,7 @@ open_doc(Db, IdOrDocInfo) -> > open_doc(Db, IdOrDocInfo, []). > > open_doc(Db, Id, Options) -> > - couch_stats_collector:increment({couchdb, database_reads}), > + increment_stat(Db, {couchdb, database_reads}), > case open_doc_int(Db, Id, Options) of > {ok, #doc{deleted=true}=Doc} -> > case lists:member(deleted, Options) of > @@ -157,7 +157,7 @@ find_ancestor_rev_pos({RevPos, [RevId|Re > end. > > open_doc_revs(Db, Id, Revs, Options) -> > - couch_stats_collector:increment({couchdb, database_reads}), > + increment_stat(Db, {couchdb, database_reads}), > [{ok, Results}] = open_doc_revs_int(Db, [{Id, Revs}], Options), > {ok, [apply_open_options(Result, Options) || Result <- Results]}. > > @@ -621,7 +621,7 @@ check_dup_atts2(_) -> > > > update_docs(Db, Docs, Options, replicated_changes) -> > - couch_stats_collector:increment({couchdb, database_writes}), > + increment_stat(Db, {couchdb, database_writes}), > DocBuckets = group_alike_docs(Docs), > > case (Db#db.validate_doc_funs /= []) orelse > @@ -647,7 +647,7 @@ update_docs(Db, Docs, Options, replicate > {ok, DocErrors}; > > update_docs(Db, Docs, Options, interactive_edit) -> > - couch_stats_collector:increment({couchdb, database_writes}), > + increment_stat(Db, {couchdb, database_writes}), > AllOrNothing = lists:member(all_or_nothing, Options), > % go ahead and generate the new revision ids for the documents. > % separate out the NonRep documents from the rest of the documents > @@ -959,7 +959,12 @@ init({DbName, Filepath, Fd, Options}) -> > {ok, UpdaterPid} = gen_server:start_link(couch_db_updater, {self(), > DbName, Filepath, Fd, Options}, []), > {ok, #db{fd_ref_counter=RefCntr}=Db} = gen_server:call(UpdaterPid, > get_db), > couch_ref_counter:add(RefCntr), > - couch_stats_collector:track_process_count({couchdb, open_databases}), > + case lists:member(sys_db, Options) of > + true -> > + ok; > + false -> > + couch_stats_collector:track_process_count({couchdb, > open_databases}) > + end, > process_flag(trap_exit, true), > {ok, Db}. > > @@ -983,7 +988,9 @@ handle_call({db_updated, NewDb}, _From, > couch_ref_counter:add(NewRefCntr), > couch_ref_counter:drop(OldRefCntr) > end, > - {reply, ok, NewDb}. > + {reply, ok, NewDb}; > +handle_call(get_db, _From, Db) -> > + {reply, {ok, Db}, Db}. > > > handle_cast(Msg, Db) -> > @@ -1178,4 +1185,7 @@ make_doc(#db{fd=Fd}=Db, Id, Deleted, Bp, > }. > > > - > +increment_stat(#db{is_sys_db = true}, _Stat) -> > + ok; > +increment_stat(#db{}, Stat) -> > + couch_stats_collector:increment(Stat). > > Modified: couchdb/trunk/src/couchdb/couch_db.hrl > URL: > http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_db.hrl?rev=957314&r1=957313&r2=957314&view=diff > > ============================================================================== > --- couchdb/trunk/src/couchdb/couch_db.hrl (original) > +++ couchdb/trunk/src/couchdb/couch_db.hrl Wed Jun 23 19:11:50 2010 > @@ -173,7 +173,8 @@ > user_ctx = #user_ctx{}, > waiting_delayed_commit = nil, > revs_limit = 1000, > - fsync_options = [] > + fsync_options = [], > + is_sys_db = false > }). > > > > Modified: couchdb/trunk/src/couchdb/couch_db_updater.erl > URL: > http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_db_updater.erl?rev=957314&r1=957313&r2=957314&view=diff > > ============================================================================== > --- couchdb/trunk/src/couchdb/couch_db_updater.erl (original) > +++ couchdb/trunk/src/couchdb/couch_db_updater.erl Wed Jun 23 19:11:50 2010 > @@ -35,7 +35,7 @@ init({MainPid, DbName, Filepath, Fd, Opt > > Db = init_db(DbName, Filepath, Fd, Header), > Db2 = refresh_validate_doc_funs(Db), > - {ok, Db2#db{main_pid=MainPid}}. > + {ok, Db2#db{main_pid = MainPid, is_sys_db = lists:member(sys_db, > Options)}}. > > > terminate(_Reason, Db) -> > > Modified: couchdb/trunk/src/couchdb/couch_file.erl > URL: > http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_file.erl?rev=957314&r1=957313&r2=957314&view=diff > > ============================================================================== > --- couchdb/trunk/src/couchdb/couch_file.erl (original) > +++ couchdb/trunk/src/couchdb/couch_file.erl Wed Jun 23 19:11:50 2010 > @@ -231,16 +231,14 @@ init({Filepath, Options, ReturnPid, Ref} > {ok, 0} = file:position(Fd, 0), > ok = file:truncate(Fd), > ok = file:sync(Fd), > - couch_stats_collector:track_process_count( > - {couchdb, open_os_files}), > + maybe_track_open_os_files(Options), > {ok, #file{fd=Fd}}; > false -> > ok = file:close(Fd), > init_status_error(ReturnPid, Ref, file_exists) > end; > false -> > - couch_stats_collector:track_process_count( > - {couchdb, open_os_files}), > + maybe_track_open_os_files(Options), > {ok, #file{fd=Fd}} > end; > Error -> > @@ -252,7 +250,7 @@ init({Filepath, Options, ReturnPid, Ref} > {ok, Fd_Read} -> > {ok, Fd} = file:open(Filepath, [read, append, raw, binary]), > ok = file:close(Fd_Read), > - couch_stats_collector:track_process_count({couchdb, > open_os_files}), > + maybe_track_open_os_files(Options), > {ok, Length} = file:position(Fd, eof), > {ok, #file{fd=Fd, eof=Length}}; > Error -> > @@ -260,6 +258,13 @@ init({Filepath, Options, ReturnPid, Ref} > end > end. > > +maybe_track_open_os_files(FileOptions) -> > + case lists:member(sys_db, FileOptions) of > + true -> > + ok; > + false -> > + couch_stats_collector:track_process_count({couchdb, > open_os_files}) > + end. > > terminate(_Reason, _Fd) -> > ok. > > Modified: couchdb/trunk/src/couchdb/couch_httpd_auth.erl > URL: > http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd_auth.erl?rev=957314&r1=957313&r2=957314&view=diff > > ============================================================================== > --- couchdb/trunk/src/couchdb/couch_httpd_auth.erl (original) > +++ couchdb/trunk/src/couchdb/couch_httpd_auth.erl Wed Jun 23 19:11:50 2010 > @@ -19,7 +19,6 @@ > -export([proxy_authentification_handler/1]). > -export([cookie_auth_header/2]). > -export([handle_session_req/1]). > --export([ensure_users_db_exists/1, get_user/1]). > > -import(couch_httpd, [header_value/2, send_json/2,send_json/4, > send_method_not_allowed/2]). > > @@ -66,7 +65,7 @@ basic_name_pw(Req) -> > default_authentication_handler(Req) -> > case basic_name_pw(Req) of > {User, Pass} -> > - case get_user(?l2b(User)) of > + case couch_auth_cache:get_user_creds(User) of > nil -> > throw({unauthorized, <<"Name or password is > incorrect.">>}); > UserProps -> > @@ -156,149 +155,6 @@ proxy_auth_user(Req) -> > end > end. > > -% maybe we can use hovercraft to simplify running this view query > -% rename to get_user_from_users_db > -get_user(UserName) -> > - case couch_config:get("admins", ?b2l(UserName)) of > - "-hashed-" ++ HashedPwdAndSalt -> > - % the name is an admin, now check to see if there is a user doc > - % which has a matching name, salt, and password_sha > - [HashedPwd, Salt] = string:tokens(HashedPwdAndSalt, ","), > - case get_user_props_from_db(UserName) of > - nil -> > - [{<<"roles">>, [<<"_admin">>]}, > - {<<"salt">>, ?l2b(Salt)}, > - {<<"password_sha">>, ?l2b(HashedPwd)}]; > - UserProps when is_list(UserProps) -> > - DocRoles = couch_util:get_value(<<"roles">>, UserProps), > - [{<<"roles">>, [<<"_admin">> | DocRoles]}, > - {<<"salt">>, ?l2b(Salt)}, > - {<<"password_sha">>, ?l2b(HashedPwd)}] > - end; > - _Else -> > - get_user_props_from_db(UserName) > - end. > - > -get_user_props_from_db(UserName) -> > - DbName = couch_config:get("couch_httpd_auth", "authentication_db"), > - {ok, Db} = ensure_users_db_exists(?l2b(DbName)), > - DocId = <<"org.couchdb.user:", UserName/binary>>, > - try couch_httpd_db:couch_doc_open(Db, DocId, nil, [conflicts]) of > - #doc{meta=Meta}=Doc -> > - % check here for conflict state and throw error if conflicted > - case couch_util:get_value(conflicts,Meta,[]) of > - [] -> > - {DocProps} = couch_query_servers:json_doc(Doc), > - case couch_util:get_value(<<"type">>, DocProps) of > - <<"user">> -> > - DocProps; > - _Else -> > - ?LOG_ERROR("Invalid user doc. Id: > ~p",[DocId]), > - nil > - end; > - _Else -> > - throw({unauthorized, <<"User document conflict must be > resolved before login.">>}) > - end > - catch > - throw:_Throw -> > - nil > - after > - couch_db:close(Db) > - end. > - > -% this should handle creating the ddoc > -ensure_users_db_exists(DbName) -> > - case couch_db:open(DbName, [{user_ctx, > #user_ctx{roles=[<<"_admin">>]}}]) of > - {ok, Db} -> > - ensure_auth_ddoc_exists(Db, <<"_design/_auth">>), > - {ok, Db}; > - _Error -> > - {ok, Db} = couch_db:create(DbName, [{user_ctx, > #user_ctx{roles=[<<"_admin">>]}}]), > - ensure_auth_ddoc_exists(Db, <<"_design/_auth">>), > - {ok, Db} > - end. > - > -ensure_auth_ddoc_exists(Db, DDocId) -> > - try couch_httpd_db:couch_doc_open(Db, DDocId, nil, []) of > - _Foo -> ok > - catch > - _:_Error -> > - % create the design document > - {ok, AuthDesign} = auth_design_doc(DDocId), > - {ok, _Rev} = couch_db:update_doc(Db, AuthDesign, []), > - ok > - end. > - > -% add the validation function here > -auth_design_doc(DocId) -> > - DocProps = [ > - {<<"_id">>, DocId}, > - {<<"language">>,<<"javascript">>}, > - { > - <<"validate_doc_update">>, > - <<"function(newDoc, oldDoc, userCtx) { > - if ((oldDoc || newDoc).type != 'user') { > - throw({forbidden : 'doc.type must be user'}); > - } // we only validate user docs for now > - if (newDoc._deleted === true) { > - // allow deletes by admins and matching users > - // without checking the other fields > - if ((userCtx.roles.indexOf('_admin') != -1) || > (userCtx.name == oldDoc.name)) { > - return; > - } else { > - throw({forbidden : 'Only admins may delete other > user docs.'}); > - } > - } > - if (!newDoc.name) { > - throw({forbidden : 'doc.name is required'}); > - } > - if (!(newDoc.roles && (typeof newDoc.roles.length != > 'undefined') )) { > - throw({forbidden : 'doc.roles must be an array'}); > - } > - if (newDoc._id != 'org.couchdb.user:'+newDoc.name) { > - throw({forbidden : 'Docid must be of the form > org.couchdb.user:name'}); > - } > - if (oldDoc) { // validate all updates > - if (oldDoc.name != newDoc.name) { > - throw({forbidden : 'Usernames may not be > changed.'}); > - } > - } > - if (newDoc.password_sha && !newDoc.salt) { > - throw({forbidden : 'Users with password_sha must have > a salt. See /_utils/script/couch.js for example code.'}); > - } > - if (userCtx.roles.indexOf('_admin') == -1) { // not an > admin > - if (oldDoc) { // validate non-admin updates > - if (userCtx.name != newDoc.name) { > - throw({forbidden : 'You may only update your own > user document.'}); > - } > - // validate role updates > - var oldRoles = oldDoc.roles.sort(); > - var newRoles = newDoc.roles.sort(); > - if (oldRoles.length != newRoles.length) { > - throw({forbidden : 'Only _admin may edit > roles'}); > - } > - for (var i=0; i < oldRoles.length; i++) { > - if (oldRoles[i] != newRoles[i]) { > - throw({forbidden : 'Only _admin may edit > roles'}); > - } > - }; > - } else if (newDoc.roles.length > 0) { > - throw({forbidden : 'Only _admin may set roles'}); > - } > - } > - // no system roles in users db > - for (var i=0; i < newDoc.roles.length; i++) { > - if (newDoc.roles[i][0] == '_') { > - throw({forbidden : 'No system roles (starting with > underscore) in users db.'}); > - } > - }; > - // no system names as names > - if (newDoc.name[0] == '_') { > - throw({forbidden : 'Username may not start with > underscore.'}); > - } > - }">> > - }], > - {ok, couch_doc:from_json_obj({DocProps})}. > > cookie_authentication_handler(#httpd{mochi_req=MochiReq}=Req) -> > case MochiReq:get_cookie_value("AuthSession") of > @@ -321,7 +177,7 @@ cookie_authentication_handler(#httpd{moc > Req; > SecretStr -> > Secret = ?l2b(SecretStr), > - case get_user(?l2b(User)) of > + case couch_auth_cache:get_user_creds(User) of > nil -> Req; > UserProps -> > UserSalt = couch_util:get_value(<<"salt">>, UserProps, > <<"">>), > @@ -403,7 +259,7 @@ handle_session_req(#httpd{method='POST', > UserName = ?l2b(couch_util:get_value("name", Form, "")), > Password = ?l2b(couch_util:get_value("password", Form, "")), > ?LOG_DEBUG("Attempt Login: ~s",[UserName]), > - User = case get_user(UserName) of > + User = case couch_auth_cache:get_user_creds(UserName) of > nil -> []; > Result -> Result > end, > > Modified: couchdb/trunk/src/couchdb/couch_httpd_db.erl > URL: > http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd_db.erl?rev=957314&r1=957313&r2=957314&view=diff > > ============================================================================== > --- couchdb/trunk/src/couchdb/couch_httpd_db.erl (original) > +++ couchdb/trunk/src/couchdb/couch_httpd_db.erl Wed Jun 23 19:11:50 2010 > @@ -160,23 +160,13 @@ handle_design_info_req(Req, _Db, _DDoc) > > create_db_req(#httpd{user_ctx=UserCtx}=Req, DbName) -> > ok = couch_httpd:verify_is_server_admin(Req), > - LDbName = ?b2l(DbName), > - case couch_config:get("couch_httpd_auth", "authentication_db") of > - LDbName -> > - % make sure user's db always has the auth ddoc > - {ok, Db} = couch_httpd_auth:ensure_users_db_exists(DbName), > - couch_db:close(Db), > - DbUrl = absolute_uri(Req, "/" ++ > couch_util:url_encode(DbName)), > - send_json(Req, 201, [{"Location", DbUrl}], {[{ok, true}]}); > - _Else -> > - case couch_server:create(DbName, [{user_ctx, UserCtx}]) of > - {ok, Db} -> > - couch_db:close(Db), > - DbUrl = absolute_uri(Req, "/" ++ > couch_util:url_encode(DbName)), > - send_json(Req, 201, [{"Location", DbUrl}], {[{ok, > true}]}); > - Error -> > - throw(Error) > - end > + case couch_server:create(DbName, [{user_ctx, UserCtx}]) of > + {ok, Db} -> > + couch_db:close(Db), > + DbUrl = absolute_uri(Req, "/" ++ couch_util:url_encode(DbName)), > + send_json(Req, 201, [{"Location", DbUrl}], {[{ok, true}]}); > + Error -> > + throw(Error) > end. > > delete_db_req(#httpd{user_ctx=UserCtx}=Req, DbName) -> > @@ -189,15 +179,6 @@ delete_db_req(#httpd{user_ctx=UserCtx}=R > end. > > do_db_req(#httpd{user_ctx=UserCtx,path_parts=[DbName|_]}=Req, Fun) -> > - LDbName = ?b2l(DbName), > - % I hope this lookup is cheap. > - case couch_config:get("couch_httpd_auth", "authentication_db") of > - LDbName -> > - % make sure user's db always has the auth ddoc > - {ok, ADb} = couch_httpd_auth:ensure_users_db_exists(DbName), > - couch_db:close(ADb); > - _Else -> ok > - end, > case couch_db:open(DbName, [{user_ctx, UserCtx}]) of > {ok, Db} -> > try > > Modified: couchdb/trunk/src/couchdb/couch_httpd_oauth.erl > URL: > http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd_oauth.erl?rev=957314&r1=957313&r2=957314&view=diff > > ============================================================================== > --- couchdb/trunk/src/couchdb/couch_httpd_oauth.erl (original) > +++ couchdb/trunk/src/couchdb/couch_httpd_oauth.erl Wed Jun 23 19:11:50 > 2010 > @@ -41,7 +41,7 @@ set_user_ctx(Req, AccessToken) -> > undefined -> throw({bad_request, unknown_oauth_token}); > Value -> ?l2b(Value) > end, > - case couch_httpd_auth:get_user(Name) of > + case couch_auth_cache:get_user_creds(Name) of > nil -> Req; > User -> > Roles = couch_util:get_value(<<"roles">>, User, []), > > Modified: couchdb/trunk/src/couchdb/couch_server.erl > URL: > http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_server.erl?rev=957314&r1=957313&r2=957314&view=diff > > ============================================================================== > --- couchdb/trunk/src/couchdb/couch_server.erl (original) > +++ couchdb/trunk/src/couchdb/couch_server.erl Wed Jun 23 19:11:50 2010 > @@ -141,6 +141,7 @@ init([]) -> > ets:new(couch_dbs_by_name, [set, private, named_table]), > ets:new(couch_dbs_by_pid, [set, private, named_table]), > ets:new(couch_dbs_by_lru, [ordered_set, private, named_table]), > + ets:new(couch_sys_dbs, [set, private, named_table]), > process_flag(trap_exit, true), > {ok, #server{root_dir=RootDir, > dbname_regexp=RegExp, > @@ -180,7 +181,7 @@ maybe_close_lru_db(#server{dbs_open=NumO > end. > > try_close_lru(StartTime) -> > - LruTime = ets:first(couch_dbs_by_lru), > + LruTime = get_lru(), > if LruTime > StartTime -> > % this means we've looped through all our opened dbs and found them > % all in use. > @@ -194,6 +195,7 @@ try_close_lru(StartTime) -> > true = ets:delete(couch_dbs_by_lru, LruTime), > true = ets:delete(couch_dbs_by_name, DbName), > true = ets:delete(couch_dbs_by_pid, MainPid), > + true = ets:delete(couch_sys_dbs, DbName), > ok; > false -> > % this still has referrers. Go ahead and give it a current lru > time > @@ -207,11 +209,31 @@ try_close_lru(StartTime) -> > end > end. > > +get_lru() -> > + get_lru(ets:first(couch_dbs_by_lru)). > + > +get_lru(LruTime) -> > + [{LruTime, DbName}] = ets:lookup(couch_dbs_by_lru, LruTime), > + case ets:member(couch_sys_dbs, DbName) of > + false -> > + LruTime; > + true -> > + [{_, {opened, MainPid, _}}] = ets:lookup(couch_dbs_by_name, > DbName), > + case couch_db:is_idle(MainPid) of > + true -> > + LruTime; > + false -> > + get_lru(ets:next(couch_dbs_by_lru, LruTime)) > + end > + end. > + > open_async(Server, From, DbName, Filepath, Options) -> > Parent = self(), > Opener = spawn_link(fun() -> > Res = couch_db:start_link(DbName, Filepath, Options), > - gen_server:call(Parent, {open_result, DbName, Res}, infinity), > + gen_server:call( > + Parent, {open_result, DbName, Res, Options}, infinity > + ), > unlink(Parent), > case Res of > {ok, DbReader} -> > @@ -222,13 +244,20 @@ open_async(Server, From, DbName, Filepat > end), > true = ets:insert(couch_dbs_by_name, {DbName, {opening, Opener, > [From]}}), > true = ets:insert(couch_dbs_by_pid, {Opener, DbName}), > - Server#server{dbs_open=Server#server.dbs_open + 1}. > + DbsOpen = case lists:member(sys_db, Options) of > + true -> > + true = ets:insert(couch_sys_dbs, {DbName, true}), > + Server#server.dbs_open; > + false -> > + Server#server.dbs_open + 1 > + end, > + Server#server{dbs_open = DbsOpen}. > > handle_call({set_max_dbs_open, Max}, _From, Server) -> > {reply, ok, Server#server{max_dbs_open=Max}}; > handle_call(get_server, _From, Server) -> > {reply, {ok, Server}, Server}; > -handle_call({open_result, DbName, {ok, OpenedDbPid}}, _From, Server) -> > +handle_call({open_result, DbName, {ok, OpenedDbPid}, Options}, _From, > Server) -> > link(OpenedDbPid), > [{DbName, {opening,Opener,Froms}}] = ets:lookup(couch_dbs_by_name, > DbName), > lists:foreach(fun({FromPid,_}=From) -> > @@ -241,15 +270,28 @@ handle_call({open_result, DbName, {ok, O > true = ets:delete(couch_dbs_by_pid, Opener), > true = ets:insert(couch_dbs_by_pid, {OpenedDbPid, DbName}), > true = ets:insert(couch_dbs_by_lru, {LruTime, DbName}), > + case lists:member(create, Options) of > + true -> > + couch_db_update_notifier:notify({created, DbName}); > + false -> > + ok > + end, > {reply, ok, Server}; > -handle_call({open_result, DbName, Error}, _From, Server) -> > +handle_call({open_result, DbName, Error, Options}, _From, Server) -> > [{DbName, {opening,Opener,Froms}}] = ets:lookup(couch_dbs_by_name, > DbName), > lists:foreach(fun(From) -> > gen_server:reply(From, Error) > end, Froms), > true = ets:delete(couch_dbs_by_name, DbName), > true = ets:delete(couch_dbs_by_pid, Opener), > - {reply, ok, Server#server{dbs_open=Server#server.dbs_open - 1}}; > + DbsOpen = case lists:member(sys_db, Options) of > + true -> > + true = ets:delete(couch_sys_dbs, DbName), > + Server#server.dbs_open; > + false -> > + Server#server.dbs_open - 1 > + end, > + {reply, ok, Server#server{dbs_open = DbsOpen}}; > handle_call({open, DbName, Options}, {FromPid,_}=From, Server) -> > LruTime = now(), > case ets:lookup(couch_dbs_by_name, DbName) of > @@ -257,12 +299,17 @@ handle_call({open, DbName, Options}, {Fr > DbNameList = binary_to_list(DbName), > case check_dbname(Server, DbNameList) of > ok -> > - case maybe_close_lru_db(Server) of > - {ok, Server2} -> > - Filepath = get_full_filename(Server, DbNameList), > - {noreply, open_async(Server2, From, DbName, Filepath, > Options)}; > - CloseError -> > - {reply, CloseError, Server} > + Path = get_full_filename(Server, DbNameList), > + case lists:member(sys_db, Options) of > + true -> > + {noreply, open_async(Server, From, DbName, Path, > Options)}; > + false -> > + case maybe_close_lru_db(Server) of > + {ok, Server2} -> > + {noreply, open_async(Server2, From, DbName, Path, > Options)}; > + CloseError -> > + {reply, CloseError, Server} > + end > end; > Error -> > {reply, Error, Server} > @@ -301,21 +348,34 @@ handle_call({delete, DbName, _Options}, > case check_dbname(Server, DbNameList) of > ok -> > FullFilepath = get_full_filename(Server, DbNameList), > - Server2 = > + UpdateState = > case ets:lookup(couch_dbs_by_name, DbName) of > - [] -> Server; > + [] -> false; > [{_, {opening, Pid, Froms}}] -> > couch_util:shutdown_sync(Pid), > true = ets:delete(couch_dbs_by_name, DbName), > true = ets:delete(couch_dbs_by_pid, Pid), > [gen_server:send_result(F, not_found) || F <- Froms], > - Server#server{dbs_open=Server#server.dbs_open - 1}; > + true; > [{_, {opened, Pid, LruTime}}] -> > couch_util:shutdown_sync(Pid), > true = ets:delete(couch_dbs_by_name, DbName), > true = ets:delete(couch_dbs_by_pid, Pid), > true = ets:delete(couch_dbs_by_lru, LruTime), > - Server#server{dbs_open=Server#server.dbs_open - 1} > + true > + end, > + Server2 = case UpdateState of > + true -> > + DbsOpen = case ets:member(couch_sys_dbs, DbName) of > + true -> > + true = ets:delete(couch_sys_dbs, DbName), > + Server#server.dbs_open; > + false -> > + Server#server.dbs_open - 1 > + end, > + Server#server{dbs_open = DbsOpen}; > + false -> > + Server > end, > > %% Delete any leftover .compact files. If we don't do this a > subsequent > > Modified: couchdb/trunk/src/couchdb/priv/stat_descriptions.cfg.in > URL: > http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/priv/stat_descriptions.cfg.in?rev=957314&r1=957313&r2=957314&view=diff > > ============================================================================== > --- couchdb/trunk/src/couchdb/priv/stat_descriptions.cfg.in (original) > +++ couchdb/trunk/src/couchdb/priv/stat_descriptions.cfg.in Wed Jun 23 > 19:11:50 2010 > @@ -19,6 +19,8 @@ > {couchdb, open_databases, "number of open databases"}. > {couchdb, open_os_files, "number of file descriptors CouchDB has open"}. > {couchdb, request_time, "length of a request inside CouchDB without > MochiWeb"}. > +{couchdb, auth_cache_hits, "number of authentication cache hits"}. > +{couchdb, auth_cache_misses, "number of authentication cache misses"}. > > {httpd, bulk_requests, "number of bulk requests"}. > {httpd, requests, "number of HTTP requests"}. > > > -- Filipe David Manana, [email protected] "Reasonable men adapt themselves to the world. Unreasonable men adapt the world to themselves. That's why all progress depends on unreasonable men."
