Anonymous avatar Anonymous committed 276425e Merge

Merge

Comments (0)

Files changed (7)

client_lib/jiak.py

     def list_bucket(self, Bucket):
         return self._expect(200,
                  self._do_req("GET", self.JKP + urllib.quote_plus(Bucket)))
-    def store(self, JObj):
+    def store(self, JObj, W=2,DW=2):
         NewData = self._expect(200,
                      self._do_req("PUT",
                                   self.JKP
                                   + urllib.quote_plus(JObj.bucket) + "/"
                                   + urllib.quote_plus(JObj.key)
-                                  + "?returnbody=true",
+                                  + "?returnbody=true"
+                                  + "&w=" + str(W)
+                                  + "&dw=" + str(DW),
                                   JObj.to_json(),
                                   {"Content-Type": "application/json"}))
         JObj.update(NewData)
-    def fetch(self, bucket, key):
+    def fetch(self, bucket, key, R=2):
         Resp = self._do_req("GET",
                             self.JKP + urllib.quote_plus(bucket)
-                            + "/" + urllib.quote_plus(key))
+                            + "/" + urllib.quote_plus(key)
+                            + "?r=" + str(R))
         if Resp.status == 404:
             return None
         Data = self._expect(200,Resp)
         Obj = JiakObject(bucket, key)
         Obj.update(Data)
         return Obj
-    def delete(self, bucket, key):
+    def delete(self, bucket, key, DW=2):
         Resp = self._do_req("DELETE",
                             self.JKP + urllib.quote_plus(bucket)
-                            + "/" + urllib.quote_plus(key))
+                            + "/" + urllib.quote_plus(key)
+                            + "?dw=" + str(DW))
         if Resp.status == 404:
             return None
         elif Resp.status == 204:

src/jiak_object.erl

 %%      by mochijson2.  Thus, a simple object looks something like:
 %%```
 %%      {struct,
-%%       [{<<"bucket">>, foo},
+%%       [{<<"bucket">>, <<"foo">>},
 %%        {<<"key">>, <<"123">>},
 %%        {<<"object">>,
 %%         {struct,
 %%           {<<"bazField">>, 42},
 %%          ]}},
 %%        {<<"links">>,
-%%         [[quuxLink, <<"quuxKey">>, <<"quuxTag">>],
-%%          [abcLink, <<"abcKey">>, <<"abcTag">>]
+%%         [[<<"quuxLink">>, <<"quuxKey">>, <<"quuxTag">>],
+%%          [<<"abcLink">>, <<"abcKey">>, <<"abcTag">>]
 %%         ]},
 %%        {<<"vclock">>, <<"opaque-riak-vclock">>},
 %%        {<<"lastmod">>, <<"Mon, 03 Aug 2009 18:49:42 GMT">>}
 %%       <<"barValue">> = jiak_object:getp(O, <<"barField">>).
 %%       3 = jiak_object:getp(
 %%             jiak_object:setp(O, <<"bazField">>, 3)).
-%%       [[linkBucket, <<"linkKey">>, <<"linkTag">>]] =
-%%         jiak_object:links(O, linkBucket).
+%%       [[<<"linkBucket">>, <<"linkKey">>, <<"linkTag">>]] =
+%%         jiak_object:links(O, <<"linkBucket">>).
 %%'''
 %%       are all true.
 -module(jiak_object).
 %%            -> [{{atom(), binary()}, binary()}]
 %% @type link_tag() = term()|'_'
 %% @type link_bucket() = riak_object:bucket()|'_'
-%% @doc This function implements the map phase to which link map/reduce
-%%      specs are mapped.  The atom '_' means "match all", so for example,
-%%      {foo, '_'} would match all links to bucket 'foo' with any tag, while
-%%      {foo, bar} would match only links to bucket 'foo' with tag 'bar'.
-%%      The tags of the links will be included as the "KeyData" for the
-%%      bucket-key pair returned.
-%%      Keys that were inputs to this phase that reference non-existent
-%%      objects are ignored (i.e. {error,notfound} => []).
+%% @doc This function implements the map phase to which link
+%%      map/reduce specs are mapped.  The atom '_' means "match all",
+%%      so for example, {<<"foo">>, '_'} would match all links to
+%%      bucket 'foo' with any tag, while {<<"foo">>, <<"bar">>} would
+%%      match only links to bucket 'foo' with tag 'bar'.  The tags of
+%%      the links will be included as the "KeyData" for the bucket-key
+%%      pair returned.  Keys that were inputs to this phase that
+%%      reference non-existent objects are ignored
+%%      (i.e. {error,notfound} => []).
 mapreduce_linkfun({error, notfound}, _, _) -> [];
 mapreduce_linkfun(RiakObject, _, {Bucket, Tag}) ->
     %% TODO: could just pull links out of riak object directly, if that

src/jiak_resource.erl

         {ok, _SchemaObj={struct, SchemaPL0}} ->
             ReqProps = [list_to_binary(atom_to_list(P)) || 
                            P <- jiak_util:jiak_required_props()],
-            {struct, SchemaPL} = proplists:get_value(<<"schema">>,SchemaPL0),
-            case lists:filter(
-                   fun(I) -> 
-                           proplists:get_value(I, SchemaPL) =:= undefined
-                   end, 
-                   ReqProps) of
-                [] ->
-                    {false, ReqData, Context#ctx{incoming=SchemaPL}};
-                L ->
-                    {true, 
-                     wrq:append_to_response_body(
-                     io_lib:format("missing required schema fields: ~p~n",[L]),
-                       ReqData),
-                     Context}
+            case proplists:get_value(<<"schema">>,SchemaPL0) of
+                {struct, SchemaPL} ->
+                    case lists:filter(
+                           fun(I) -> 
+                                   proplists:get_value(I, SchemaPL) =:= undefined
+                           end, 
+                           ReqProps) of
+                        [] ->
+                            {false, ReqData, Context#ctx{incoming=SchemaPL}};
+                        L ->
+                            {true, 
+                             wrq:append_to_response_body(
+                               io_lib:format("missing required schema fields: ~p~n",[L]),
+                               ReqData),
+                             Context}
+                    end;
+                undefined ->
+                    case proplists:get_value(<<"bucket_mod">>, SchemaPL0) of
+                        BMStr when is_binary(BMStr) ->
+                            case catch list_to_existing_atom(binary_to_list(BMStr)) of
+                                BM when is_atom(BM) ->
+                                    {false, ReqData,
+                                     Context#ctx{incoming=[{<<"bucket_mod">>, BM}]}};
+                                _ ->
+                                    {true,
+                                     wrq:append_to_response_body(
+                                       io_lib:format("no module '~s' found", [BMStr]),
+                                       ReqData),
+                                     Context}
+                            end;
+                        undefined ->
+                            {true, 
+                             wrq:append_to_response_body(
+                               io_lib:format("missing required schema fields: ~p~n",
+                                             [ReqProps]),
+                               ReqData),
+                             Context}
+                    end
             end;
         Err ->
             {true,

src/jiak_util.erl

 jiak_module_for_bucket(BucketName) when is_binary(BucketName) ->
     BucketProps = riak_bucket:get_bucket(BucketName),
     case proplists:lookup(bucket_mod, BucketProps) of
-        {bucket_mod, Module} ->
+        {bucket_mod, Module} when Module /= undefined ->
             Module;
-        none ->
+        _ ->
             case bucket_props_defined(BucketProps) of
                 true ->
                     jiak_default:new(BucketProps);
     riak_ring_manager:stop(),
     riak_eventer:stop().
 
+%% just like dynamic_bucket_test, but ensuring that
+%% {bucket_mod, undefined} gets treated as if bucket_mod
+%% were not set.
+dynamic_bucket_undefined_test() ->
+    riak_ring_manager:start_link(test),
+    riak_eventer:start_link(test),    
+    BucketProps = [{bucket_mod, undefined},
+                   {allowed_fields, [<<"test">>]},
+                   {required_fields, []},
+                   {read_mask, [<<"test">>]},
+                   {write_mask, [<<"test">>]}],
+    riak_bucket:set_bucket(<<"dynamic_bucket_test">>, BucketProps),
+    Mod = jiak_module_for_bucket(<<"dynamic_bucket_test">>),
+    ?assertEqual([<<"test">>], Mod:allowed_fields()),
+    ?assertEqual([], Mod:required_fields()),
+    ?assertEqual([<<"test">>], Mod:read_mask()),
+    ?assertEqual([<<"test">>], Mod:write_mask()),
+    riak_ring_manager:stop(),
+    riak_eventer:stop().
+
 module_bucket_test() ->
     riak_ring_manager:start_link(test),
     riak_eventer:start_link(test),    
 {application, 
  riak,
  [{description,  "riak"},
-  {vsn,          "0.5"},
+  {vsn,          "0.6"},
   {modules,      [__MODULES__]},
   {registered,   []},
   {mod,          {riak_app, []}},

src/riak_get_fsm.erl

 -record(state, {client :: {pid(), reference()},
                 n :: pos_integer(), 
                 r :: pos_integer(), 
-                allowmult :: bool(), 
+                allowmult :: boolean(), 
                 preflist :: [{pos_integer(), atom()}], 
                 waiting_for :: [{pos_integer(), atom(), atom()}],
                 req_id :: pos_integer(), 

src/riak_ring_manager.erl

             Cluster = riak:get_app_env(cluster_name),
             case file:list_dir(Dir) of
                 {error,enoent} -> ok;
+                {ok, []} -> ok;
                 {ok, Filenames} ->
                     Timestamps = [TS || {"riak_ring", C1, TS} <- 
                      [list_to_tuple(string:tokens(FN, ".")) || FN <- Filenames],
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.