diff options
| author | Christopher Lenz <cmlenz@apache.org> | 2008-08-30 10:26:51 +0000 | 
|---|---|---|
| committer | Christopher Lenz <cmlenz@apache.org> | 2008-08-30 10:26:51 +0000 | 
| commit | fae1935ffc8ee0c4096bbb327f69a24c7b58c2c1 (patch) | |
| tree | 14d23f0de4a0868decd1b0055f44a1cd0e7f3e05 | |
| parent | 39902f39104e3ba33b7fc8c825e7b49136bb104d (diff) | |
Some cosmetic cleanup (removed trailing whitespace, fixed indentation, make the test runner script executable).
git-svn-id: https://svn.apache.org/repos/asf/incubator/couchdb/trunk@690487 13f79535-47bb-0310-9956-ffa450edef68
| -rw-r--r-- | src/couchdb/couch_config.erl | 28 | ||||
| -rw-r--r-- | src/couchdb/couch_config_writer.erl | 20 | ||||
| -rw-r--r-- | src/couchdb/couch_httpd.erl | 237 | ||||
| -rwxr-xr-x[-rw-r--r--] | test/runner.sh | 0 | 
4 files changed, 141 insertions, 144 deletions
diff --git a/src/couchdb/couch_config.erl b/src/couchdb/couch_config.erl index 07d47dff..c8c803fe 100644 --- a/src/couchdb/couch_config.erl +++ b/src/couchdb/couch_config.erl @@ -11,9 +11,9 @@  % the License.  %% @doc Reads CouchDB's ini file and gets queried for configuration parameters. -%%      This module is initialized with a list of ini files that it  -%%      consecutively reads Key/Value pairs from and saves them in an ets  -%%      table. If more an one ini file is specified, the last one is used to  +%%      This module is initialized with a list of ini files that it +%%      consecutively reads Key/Value pairs from and saves them in an ets +%%      table. If more an one ini file is specified, the last one is used to  %%      write changes that are made with store/2 back to that ini file.  -module(couch_config). @@ -21,13 +21,13 @@  -behaviour(gen_server).  -export([start_link/1, init/1, -    handle_call/3, handle_cast/2, handle_info/2,  +    handle_call/3, handle_cast/2, handle_info/2,      terminate/2, code_change/3]). --export([store/2, register/1, register/2,  +-export([store/2, register/1, register/2,      get/1, get/2,      lookup_match/1, lookup_match/2,      all/0, unset/1, load_ini_file/1]). -     +  -record(config,      {notify_funs=[],      writeback_filename="" @@ -37,7 +37,7 @@  %% @type etstable() = integer(). -start_link(IniFiles) -> gen_server:start_link({local, ?MODULE}, ?MODULE, IniFiles, []).   +start_link(IniFiles) -> gen_server:start_link({local, ?MODULE}, ?MODULE, IniFiles, []).  %% @spec store(Key::any(), Value::any()) -> {ok, Tab::etsatable()}  %% @doc Public API function that triggers storage of a Key/Value pair into the @@ -57,12 +57,12 @@ get(Key, Default) ->      fix_lookup_result(ets:lookup(?MODULE, Key), Default).  %% @spec lookup_match(Key::any()) -> Value::any() | undefined:atom() -%% @doc Lets you look for a Key's Value specifying a pattern that gets passed  +%% @doc Lets you look for a Key's Value specifying a pattern that gets passed  %%      to ets::match(). Returns undefined::atom() if no Key is found.  lookup_match(Key) -> gen_server:call(?MODULE, {lookup_match, Key}).  %% @spec lookup_match(Key::any(), Default::any()) -> Value::any() | Default -%% @doc Lets you look for a Key's Value specifying a pattern that gets passed  +%% @doc Lets you look for a Key's Value specifying a pattern that gets passed  %%      to ets::match(). Returns Default::any() if no Key is found  lookup_match(Key, Default) -> gen_server:call(?MODULE, {lookup_match, Key, Default}). @@ -74,7 +74,7 @@ register(Fun) -> gen_server:call(?MODULE, {register, Fun, self()}).  register(Fun, Pid) -> gen_server:call(?MODULE, {register, Fun, Pid}).  %% @spec unset(Key::any) -> ok -%% @doc Public API call to remove the configuration entry from the internal  +%% @doc Public API call to remove the configuration entry from the internal  %%      ets table. This change is _not_ written to the storage ini file.  unset(Key) -> gen_server:call(?MODULE, {unset, Key}). @@ -115,7 +115,7 @@ handle_call(all, _From, Config) ->  handle_call({register, Fun, Pid}, _From, #config{notify_funs=PidFuns}=Config) ->      erlang:monitor(process, Pid),      {reply, ok, Config#config{notify_funs=[{Pid, Fun}|PidFuns]}}. -     +  fix_lookup_result([{_Key, Value}], _Default) ->      Value; @@ -125,7 +125,7 @@ fix_lookup_result(Values, _Default) ->      [list_to_tuple(Value) || Value <- Values].  %% @spec insert_and_commit(Tab::etstable(), Config::any()) -> ok -%% @doc Inserts a Key/Value pair into the ets table, writes it to the storage  +%% @doc Inserts a Key/Value pair into the ets table, writes it to the storage  %%      ini file and calls all registered callback functions for Key.  insert_and_commit(Config, KV) ->      true = ets:insert(?MODULE, KV), @@ -146,7 +146,7 @@ load_ini_file(IniFile) ->             io:format("~s~n", [Msg]),             throw({startup_error, Msg})      end, -     +      {ok, Lines} = regexp:split(binary_to_list(IniBin), "\r\n|\n|\r|\032"),      {_, ParsedIniValues} =      lists:foldl(fun(Line, {AccSectionName, AccValues}) -> @@ -173,7 +173,7 @@ load_ini_file(IniFile) ->                  end              end          end, {"", []}, Lines), -         +          [ets:insert(?MODULE, {Key, Value}) || {Key, Value} <- ParsedIniValues],      ok. diff --git a/src/couchdb/couch_config_writer.erl b/src/couchdb/couch_config_writer.erl index 6e93c131..6a56c96e 100644 --- a/src/couchdb/couch_config_writer.erl +++ b/src/couchdb/couch_config_writer.erl @@ -24,24 +24,24 @@  -export([save_to_file/2]).  %% @spec save_to_file( -%%           Config::{{Module::string(), Variable::string()}, Value::string()},  +%%           Config::{{Module::string(), Variable::string()}, Value::string()},  %%           File::filename()) -> ok  %% @doc Saves a Module/Key/Value triple to the ini file File::filename()  save_to_file({{Module, Variable}, Value}, File) -> -     +      ?LOG_DEBUG("saving to file '~s', Congif: '~p'", [File, {{Module, Variable}, Value}]), -     +      % open file and create a list of lines      {ok, Stream} = file:read_file(File),      OldFileContents = binary_to_list(Stream),      {ok, Lines} = regexp:split(OldFileContents, "\r\n|\n|\r|\032"), -     +      % prepare input variables      ModuleName = "[" ++ Module ++ "]",      VariableList = Variable, -     +      % produce the contents for the config file -    NewFileContents =  +    NewFileContents =      case NewFileContents2 = save_loop({{ModuleName, VariableList}, Value}, Lines, "", "", []) of          % we didn't change anything, that means we couldn't find a matching          % [ini section] in which case we just append a new one. @@ -50,7 +50,7 @@ save_to_file({{Module, Variable}, Value}, File) ->          _ ->              NewFileContents2      end, -     +      % do the save, close the config file and get out      save_file(File, NewFileContents),      file:close(Stream), @@ -102,7 +102,7 @@ save_loop({{Module, Variable}, Value}, [Line|Rest], OldCurrentModule, Contents,      % go to next line      save_loop({{Module, Variable}, Value}, Rest, NewCurrentModule, Contents2 ++ NewContents, DoneVariables2); -     +  save_loop(_Config, [], _OldModule, NewFileContents, _DoneVariable) ->      % we're out of new lines, just return the new file's contents      NewFileContents. @@ -111,7 +111,7 @@ append_new_ini_section({{ModuleName, Variable}, Value}, OldFileContents) ->      OldFileContents ++ "\n\n" ++ ModuleName ++ "\n" ++  Variable ++ "=" ++ Value ++ "\n".  %% @spec parse_module(Lins::string(), OldModule::string()) -> string() -%% @doc Tries to match a line against a pattern specifying a ini module or  +%% @doc Tries to match a line against a pattern specifying a ini module or  %%      section ("[Module]"). Returns OldModule if no match is found.  parse_module(Line, OldModule) ->      case regexp:match(Line, "^\\[([a-zA-Z0-9_-]*)\\]$") of @@ -140,7 +140,7 @@ parse_variable(Line, Variable, Value) ->              Variable ++ "=" ++ Value      end. -%% @spec save_file(File::filename(), Contents::string()) ->  +%% @spec save_file(File::filename(), Contents::string()) ->  %%           ok | {error, Reason::string()}  %% @doc Writes Contents to File  save_file(File, Contents) -> diff --git a/src/couchdb/couch_httpd.erl b/src/couchdb/couch_httpd.erl index 51959d7d..1d420ffc 100644 --- a/src/couchdb/couch_httpd.erl +++ b/src/couchdb/couch_httpd.erl @@ -40,14 +40,14 @@  start_link() ->      % read config and register for configuration changes -     +      % just stop if one of the config settings change. couch_server_sup      % will restart us and then we will pick up the new settings. -     +      BindAddress = couch_config:get({"HTTPd", "BindAddress"}, any),      Port = couch_config:get({"HTTPd", "Port"}, "5984"),      DocumentRoot = couch_config:get({"HTTPd", "DocumentRoot"}, "../../share/www"), -     +      % and off we go      Loop = fun (Req) -> apply(couch_httpd, handle_request, [Req, DocumentRoot]) end,      {ok, Pid} = mochiweb_http:start([ @@ -64,7 +64,7 @@ start_link() ->          ({"HTTPd", "DocumentRoot"}) ->              ?MODULE:stop()          end, Pid), -     +      {ok, Pid}.  stop() -> @@ -77,7 +77,7 @@ handle_request(Req, DocumentRoot) ->      % alias HEAD to GET as mochiweb takes care of stripping the body      Method = case Req:get(method) of          'HEAD' -> 'GET'; -        Other ->  +        Other ->            % handling of non standard HTTP verbs. Should be fixe din gen_tcp:recv()            case Other of              "COPY" -> 'COPY'; @@ -110,7 +110,7 @@ handle_request(Req, DocumentRoot) ->          Path,          Resp:get(code)      ]). -     +  handle_request(Req, DocumentRoot, Method, Path) ->      % Start = erlang:now(),      X = handle_request0(Req, DocumentRoot, Method, Path), @@ -222,11 +222,11 @@ handle_db_request(Req, 'DELETE', {DbName, []}) ->      Error ->          throw(Error)      end; -     +  handle_db_request(Req, Method, {DbName, Rest}) ->      case couch_db:open(DbName, []) of          {ok, Db} -> -            try  +            try                  handle_db_request(Req, Method, {DbName, Db, Rest})              after                  couch_db:close(Db) @@ -526,8 +526,8 @@ output_reduce_view(Req, View) ->              Resp:write_chunk(AccSeparator ++ Json),              {ok, {",",0,AccCount-1}};          (Key, Red, {AccSeparator,0,AccCount}) -                when is_integer(GroupLevel)  -                andalso is_tuple(Key)  +                when is_integer(GroupLevel) +                andalso is_tuple(Key)                  andalso element(1, Key) /= obj  ->              Json = lists:flatten(cjson:encode(                  {obj, [{key, list_to_tuple(lists:sublist(tuple_to_list(Key), GroupLevel))}, @@ -641,57 +641,57 @@ handle_doc_request(Req, 'PUT', _DbName, Db, DocId) ->      ]});  handle_doc_request(Req, 'COPY', _DbName, Db, SourceDocId) -> -  SourceRev = case extract_header_rev(Req) of -    missing_rev -> []; -    Rev -> Rev -  end, -   -  {TargetDocId, TargetRev} = parse_copy_destination_header(Req), -   -  % open revision Rev or Current -  {Doc, _DocRev} = couch_doc_open(Db, SourceDocId, SourceRev, []), - -  % save new doc -  {ok, NewTargetRev} = couch_db:update_doc(Db, Doc#doc{id=TargetDocId, revs=TargetRev}, []), - -  send_json(Req, 201, [{"Etag", "\"" ++ NewTargetRev ++ "\""}], {obj, [ -      {ok, true}, -      {id, TargetDocId}, -      {rev, NewTargetRev} -  ]}); +    SourceRev = case extract_header_rev(Req) of +      missing_rev -> []; +      Rev -> Rev +    end, + +    {TargetDocId, TargetRev} = parse_copy_destination_header(Req), + +    % open revision Rev or Current +    {Doc, _DocRev} = couch_doc_open(Db, SourceDocId, SourceRev, []), + +    % save new doc +    {ok, NewTargetRev} = couch_db:update_doc(Db, Doc#doc{id=TargetDocId, revs=TargetRev}, []), + +    send_json(Req, 201, [{"Etag", "\"" ++ NewTargetRev ++ "\""}], {obj, [ +        {ok, true}, +        {id, TargetDocId}, +        {rev, NewTargetRev} +    ]});  handle_doc_request(Req, 'MOVE', _DbName, Db, SourceDocId) -> -  SourceRev = case extract_header_rev(Req) of -    missing_rev ->  -      throw({ -        bad_request,  -        "MOVE requires a specified rev parameter for the origin resource."} -      ); -    Rev -> Rev -  end, -   -  {TargetDocId, TargetRev} = parse_copy_destination_header(Req), - -  % open revision Rev or Current -  {Doc, _DocRev} = couch_doc_open(Db, SourceDocId, SourceRev, []), - -  % save new doc & delete old doc in one operation -  Docs = [ -    Doc#doc{id=TargetDocId, revs=TargetRev}, -    #doc{id=SourceDocId, revs=[SourceRev], deleted=true} -  ], - -  {ok, ResultRevs} = couch_db:update_docs(Db, Docs, []), - -  DocResults = lists:zipwith( -      fun(FDoc, NewRev) -> -          {obj, [{"id", FDoc#doc.id}, {"rev", NewRev}]} -      end, -      Docs, ResultRevs), -  send_json(Req, 201, {obj, [ -      {ok, true}, -      {new_revs, list_to_tuple(DocResults)} -  ]}); +    SourceRev = case extract_header_rev(Req) of +      missing_rev -> +        throw({ +          bad_request, +          "MOVE requires a specified rev parameter for the origin resource."} +        ); +      Rev -> Rev +    end, + +    {TargetDocId, TargetRev} = parse_copy_destination_header(Req), + +    % open revision Rev or Current +    {Doc, _DocRev} = couch_doc_open(Db, SourceDocId, SourceRev, []), + +    % save new doc & delete old doc in one operation +    Docs = [ +      Doc#doc{id=TargetDocId, revs=TargetRev}, +      #doc{id=SourceDocId, revs=[SourceRev], deleted=true} +    ], + +    {ok, ResultRevs} = couch_db:update_docs(Db, Docs, []), + +    DocResults = lists:zipwith( +        fun(FDoc, NewRev) -> +            {obj, [{"id", FDoc#doc.id}, {"rev", NewRev}]} +        end, +        Docs, ResultRevs), +    send_json(Req, 201, {obj, [ +        {ok, true}, +        {new_revs, list_to_tuple(DocResults)} +    ]});  handle_doc_request(_Req, _Method, _DbName, _Db, _DocId) ->      throw({method_not_allowed, "DELETE,GET,HEAD,PUT,COPY,MOVE"}). @@ -699,35 +699,24 @@ handle_doc_request(_Req, _Method, _DbName, _Db, _DocId) ->  % Useful for debugging  % couch_doc_open(Db, DocId) ->  %   couch_doc_open(Db, DocId, [], []). -   -couch_doc_open(Db, DocId, Rev, Options) -> -  case Rev of -  "" -> % open most recent rev -      case couch_db:open_doc(Db, DocId, Options) of -          {ok, #doc{revs=[DocRev|_]}=Doc} -> -              {Doc, DocRev}; -          Error -> -              throw(Error) -      end; -  _ -> % open a specific rev (deletions come back as stubs) -      case couch_db:open_doc_revs(Db, DocId, [Rev], Options) of -          {ok, [{ok, Doc}]} -> -              {Doc, Rev}; -          {ok, [Else]} -> -              throw(Else) -      end -  end. -parse_copy_destination_header(Req) -> -  Destination = Req:get_header_value("Destination"), -  case regexp:match(Destination, "\\?") of -    nomatch ->  -      {Destination, []}; -    {match, _, _} -> -      {ok, [DocId, RevQueryOptions]} = regexp:split(Destination, "\\?"), -      {ok, [_RevQueryKey, Rev]} = regexp:split(RevQueryOptions, "="), -      {DocId, [Rev]} -  end. +couch_doc_open(Db, DocId, Rev, Options) -> +    case Rev of +    "" -> % open most recent rev +        case couch_db:open_doc(Db, DocId, Options) of +            {ok, #doc{revs=[DocRev|_]}=Doc} -> +                {Doc, DocRev}; +            Error -> +                throw(Error) +        end; +    _ -> % open a specific rev (deletions come back as stubs) +        case couch_db:open_doc_revs(Db, DocId, [Rev], Options) of +            {ok, [{ok, Doc}]} -> +                {Doc, Rev}; +            {ok, [Else]} -> +                throw(Else) +        end +    end.  % Attachment request handlers @@ -761,7 +750,7 @@ handle_attachment_request(Req, Method, _DbName, Db, DocId, FileName)      when (Method == 'PUT') or (Method == 'DELETE') ->      Rev = extract_header_rev(Req), -     +      NewAttachment = case Method of          'DELETE' ->              []; @@ -772,20 +761,20 @@ handle_attachment_request(Req, Method, _DbName, Db, DocId, FileName)              }}]      end, -    Doc = -    case Rev of -    missing_rev -> % make the new doc -        #doc{id=DocId}; -    _ -> -        case couch_db:open_doc_revs(Db, DocId, [Rev], []) of -        {ok, [{ok, Doc0}]}   -> Doc0#doc{revs=[Rev]}; -        {ok, [Error]}       -> throw(Error) -        end +    Doc = case Rev of +        missing_rev -> % make the new doc +            #doc{id=DocId}; +        _ -> +            case couch_db:open_doc_revs(Db, DocId, [Rev], []) of +            {ok, [{ok, Doc0}]}   -> Doc0#doc{revs=[Rev]}; +            {ok, [Error]}       -> throw(Error) +            end      end, -     +      #doc{attachments=Attachments} = Doc,      DocEdited = Doc#doc{ -        attachments = NewAttachment ++ proplists:delete(FileName, Attachments)}, +        attachments = NewAttachment ++ proplists:delete(FileName, Attachments) +    },      {ok, UpdatedRev} = couch_db:update_doc(Db, DocEdited, []),      send_json(Req, case Method of 'DELETE' -> 200; _ -> 201 end, {obj, [          {ok, true}, @@ -796,28 +785,12 @@ handle_attachment_request(Req, Method, _DbName, Db, DocId, FileName)  handle_attachment_request(_Req, _Method, _DbName, _Db, _DocId, _FileName) ->      throw({method_not_allowed, "GET,HEAD,DELETE,PUT"}). -extract_header_rev(Req) -> -    QueryRev = proplists:get_value("rev", Req:parse_qs()), -    Etag = case Req:get_header_value("If-Match") of -        undefined -> undefined; -        Tag -> string:strip(Tag, both, $") -    end, -    case {QueryRev, Etag} of -    {undefined, undefined} -> missing_rev; -    {_, undefined} -> QueryRev; -    {undefined, _} -> Etag; -    _ when QueryRev == Etag -> Etag; -    _ -> -        throw({bad_request, "Document rev and etag have different values"}) -    end. -  % Config request handlers  handle_config_request(_Req, Method, {config, Config}) ->      [Module, Key] = string:tokens(Config, "/"),      handle_config_request(_Req, Method, {[Module, Key]}); -  % PUT /_config/Module/Key  % "value"  handle_config_request(_Req, 'PUT', {[Module, Key]}) -> @@ -825,7 +798,6 @@ handle_config_request(_Req, 'PUT', {[Module, Key]}) ->  % POST,PUT /_config/Module/Key  % "value" -   handle_config_request(Req, 'POST', {[Module, Key]}) ->      Value = binary_to_list(Req:recv_body()),      ok = couch_config:store({Module, Key}, Value), @@ -835,7 +807,7 @@ handle_config_request(Req, 'POST', {[Module, Key]}) ->          {key, Key},          {value, Value}      ]}); -     +  % GET /_config/Module/Key  handle_config_request(Req, 'GET', {[Module, Key]}) ->      case couch_config:get({Module, Key},null) of @@ -850,8 +822,7 @@ handle_config_request(Req, 'GET', {[Module, Key]}) ->           ]})      end; -     -% DELETE /_config/Key +% DELETE /_config/Module/Key  handle_config_request(Req, 'DELETE', {[Module, Key]}) ->      case couch_config:get({Module, Key}, null) of      null -> @@ -870,7 +841,7 @@ handle_config_request(Req, 'DELETE', {[Module, Key]}) ->  % TODO:  % POST,PUT /_config/  % [{Key, Value}, {K2, V2}, {K3, V3}] -%  +%  % POST,PUT/_config/Key?value=Value @@ -1141,6 +1112,32 @@ error_to_json0({Id, Reason}) when is_atom(Id) ->  error_to_json0(Error) ->      {500, error, Error}. +extract_header_rev(Req) -> +    QueryRev = proplists:get_value("rev", Req:parse_qs()), +    Etag = case Req:get_header_value("If-Match") of +        undefined -> undefined; +        Tag -> string:strip(Tag, both, $") +    end, +    case {QueryRev, Etag} of +    {undefined, undefined} -> missing_rev; +    {_, undefined} -> QueryRev; +    {undefined, _} -> Etag; +    _ when QueryRev == Etag -> Etag; +    _ -> +        throw({bad_request, "Document rev and etag have different values"}) +    end. + +parse_copy_destination_header(Req) -> +    Destination = Req:get_header_value("Destination"), +    case regexp:match(Destination, "\\?") of +        nomatch -> +            {Destination, []}; +        {match, _, _} -> +            {ok, [DocId, RevQueryOptions]} = regexp:split(Destination, "\\?"), +            {ok, [_RevQueryKey, Rev]} = regexp:split(RevQueryOptions, "="), +            {DocId, [Rev]} +    end. +  send_error(Req, {method_not_allowed, Methods}) ->      {ok, Req:respond({405, [{"Allow", Methods}] ++ server_header(), <<>>})};  send_error(Req, {modified, Etag}) -> diff --git a/test/runner.sh b/test/runner.sh index ae0f1ef8..ae0f1ef8 100644..100755 --- a/test/runner.sh +++ b/test/runner.sh  | 
