@@ -191,6 +191,19 @@ run2(delete, KeyGen, _ValueGen, #state{bucket = Bucket} = State) ->
191191 {error , Reason } ->
192192 {error , Reason , S2 }
193193 end ;
194+ run2 (copy , KeyGen , _ValueGen , # state {bucket = Bucket } = State ) ->
195+ {NextHost , S2 } = next_host (State ),
196+ {Host , Port } = NextHost ,
197+ SourceKey = KeyGen (),
198+ DestKey = SourceKey ++ basho_bench_config :get (cs_copy_suffix , " -copy" ),
199+ Url = url (Host , Port , Bucket , DestKey ),
200+ Headers = [{" x-amz-copy-source" , " /" ++ Bucket ++ " /" ++ SourceKey }],
201+ case do_copy ({Host , Port }, Url , Headers , State ) of
202+ ok ->
203+ {ok , S2 };
204+ {error , Reason } ->
205+ {error , Reason , S2 }
206+ end ;
194207run2 (Op , _KeyGen , _ValueGen , State ) ->
195208 {error , {unknown_op , Op }, State }.
196209
@@ -422,6 +435,16 @@ do_delete(Host, Url, Headers, State) ->
422435 {error , Reason }
423436 end .
424437
438+ do_copy (Host , Url , Headers , State ) ->
439+ case send_request (Host , Url , Headers , put , <<>>, proxy_opts (State )) of
440+ {ok , " 200" , _Header , _Body } ->
441+ ok ;
442+ {ok , Code , _Header , _Body } ->
443+ {error , {http_error , Code }};
444+ {error , Reason } ->
445+ {error , Reason }
446+ end .
447+
425448do_get_first_unit (Host , Url , Headers , State ) ->
426449 BufSize = 128 * 1024 ,
427450 Opts = [{max_pipeline_size , 9999999 },
@@ -516,19 +539,40 @@ initiate_request(Host, Url, Headers0, Method, Body, Options) ->
516539 'Content-Type' , Headers0 ,
517540 'application/octet-stream' )),
518541 Date = httpd_util :rfc1123_date (),
542+ Uri = element (7 , Url ),
519543 Headers = [{'Content-Type' , ContentTypeStr },
520544 {'Date' , Date }|lists :keydelete ('Content-Type' , 1 , Headers0 )],
521- Uri = element (7 , Url ),
522- Sig = stanchion_auth :request_signature (
523- uppercase_verb (Method ), Headers , Uri ,
524- basho_bench_config :get (cs_secret_key , " undefined" )),
525- AuthStr = [" AWS " , basho_bench_config :get (cs_access_key , " undefined" ), " :" , Sig ],
526- HeadersWithAuth = [{'Authorization' , AuthStr }|Headers ],
545+ HeadersWithAuth =
546+ case basho_bench_config :get (cs_access_key , undefined ) of
547+ undefined ->
548+ Headers ;
549+ AccessKey ->
550+ AuthSig = auth_sig (AccessKey , basho_bench_config :get (cs_secret_key ),
551+ uppercase_verb (Method ), ContentTypeStr , Date ,
552+ Headers , Uri ),
553+ [{'Authorization' , AuthSig }|Headers ]
554+ end ,
527555 Timeout = basho_bench_config :get (cs_request_timeout , 5000 ),
528556 ibrowse_http_client :send_req (Pid , Url , HeadersWithAuth , Method ,
529557 Body , Options , Timeout ).
530558
531- % % Setup user, not related to load operations
559+ % % S3 utilities
560+
561+ auth_sig (AccessKey , SecretKey , Method , ContentType , Date , Headers , Resource ) ->
562+ AmzHeaders = lists :filter (fun ({" x-amz-" ++ _ , V }) when V =/= undefined -> true ; (_ ) -> false end , Headers ),
563+ CanonizedAmzHeaders =
564+ [[Name , $: , Value , $\n ] || {Name , Value } <- lists :sort (AmzHeaders )],
565+ StringToSign = [string :to_upper (atom_to_list (Method )), $\n ,
566+ " " , $\n , % Content-MD5
567+ ContentType , $\n ,
568+ Date , $\n ,
569+ CanonizedAmzHeaders ,
570+ Resource
571+ ],
572+ Signature = base64 :encode (stanchion_utils :sha_mac (SecretKey , StringToSign )),
573+ [" AWS " , AccessKey , $: , Signature ].
574+
575+ % % CS utilities
532576
533577setup_user_and_bucket (State ) ->
534578 case basho_bench_config :get (cs_access_key , undefined ) of
0 commit comments