[ 
https://issues.apache.org/jira/browse/COUCHDB-769?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15103789#comment-15103789
 ] 

ASF GitHub Bot commented on COUCHDB-769:
----------------------------------------

Github user gilv commented on a diff in the pull request:

    https://github.com/apache/couchdb-fabric/pull/33#discussion_r49948952
  
    --- Diff: src/fabric_swift_driver.erl ---
    @@ -0,0 +1,269 @@
    +% Licensed under the Apache License, Version 2.0 (the "License"); you may 
not
    +% use this file except in compliance with the License. You may obtain a 
copy of
    +% the License at
    +%
    +%   http://www.apache.org/licenses/LICENSE-2.0
    +%
    +% Unless required by applicable law or agreed to in writing, software
    +% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    +% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    +% License for the specific language governing permissions and limitations 
under
    +% the License.
    +
    +-module(fabric_swift_driver).
    +
    +-export([put_object/5, delete_object/2, get_object/2, head_object/2]).
    +-export([store_id/0, create_container/1, delete_container/1 ]).
    +%% ====================================================================
    +%% OpenStack Swift implementation
    +%% ====================================================================
    +
    +store_id() ->
    +    "swift".
    +
    +put_object(Container, ObjName, ContextType, CustomHeaders, Data) ->
    +    couch_log:debug("Swift: PUT ~p/~s object ~n", [Container, ObjName]),
    +    case authenticate() of
    +        {ok, {Url, Storage_Token}} ->
    +            ObjNameEncoded = couch_util:url_encode(ObjName),
    +            Headers = CustomHeaders ++ [{"X-Auth-Token", Storage_Token},
    +                                        {"Content-Type",
    +                                         
unicode:characters_to_list(ContextType)}],
    +            Method = put,
    +            couch_log:debug("Swift: PUT : ~p ~p ~p ~p~n",
    +                            [Url,ContextType, ObjNameEncoded, Container]),
    +            NewUrl = Url ++ "/" ++ unicode:characters_to_list(Container) 
++ "/" ++ unicode:characters_to_list(ObjNameEncoded),
    +            couch_log:debug("Swift: PUT url: ~p~n",[NewUrl]),
    +            R = ibrowse:send_req(NewUrl, Headers, Method, Data),
    +            case R of
    +                {ok, ReturnCode, _, _} ->
    +                    {ok, {ReturnCode, NewUrl}};    
    +                Error ->
    +                    couch_log:debug("PUT object failed  ~p ~n", 
[element(2, Error)]),
    +                    {error, "PUT object failed"}   
    +            end;
    +        {not_authenticated, _} ->
    +            {error, "Not authenticated"}
    +    end.
    +
    +delete_object(Container, ObjName) ->
    +    %TO-DO: should be called during database compaction. 
    +    couch_log:debug("Swift: Delete ~p/~p ~n", [Container, ObjName]),
    +    case authenticate() of
    +        {ok, {Url, Storage_Token}} ->
    +            Header = [{"X-Auth-Token", Storage_Token}],
    +            ObjNameEncoded = couch_util:url_encode(ObjName),
    +            Method = delete,
    +            NewUrl = Url  ++ "/" ++ unicode:characters_to_list(Container) 
++ "/"
    +                ++ unicode:characters_to_list(ObjNameEncoded),
    +            couch_log:debug("Swift: url ~p~n", [NewUrl]),
    +            R = ibrowse:send_req(NewUrl, Header, Method),
    +            case R of
    +                {ok, ReturnCode, _, _} ->
    +                    couch_log:debug("Swift: Delete ~p. Return code ~p ~n",
    +                                    [NewUrl, ReturnCode]),           
    +                    {ok, ReturnCode};
    +                Error ->
    +                    couch_log:debug("Swift: Delete ~p failed. ~n", 
[NewUrl]),
    +                    couch_log:debug("Swift: ~p ~n", [element(2, Error)]),
    +                    {error, "Delete object failed"}
    +            end;
    +        {not_authenticated, _} ->
    +            {error, "Not authenticated"}
    +    end.
    +
    +get_object(Container, ObjName) ->
    +    couch_log:debug("Swift: get object ~p/~p ~n", [Container, ObjName]),
    +    case authenticate() of
    +        {ok, {Url, Storage_Token}} ->
    +            Header = [{"X-Auth-Token", Storage_Token}],
    +            ObjNameEncoded = couch_util:url_encode(ObjName),
    +            Method = get,
    +            NewUrl = Url  ++ "/" ++ unicode:characters_to_list(Container) 
++ "/"
    +                ++ unicode:characters_to_list(ObjNameEncoded),
    +            couch_log:debug("Swift: url ~p~n", [NewUrl]),
    +            R = ibrowse:send_req(NewUrl, Header, Method),
    +            case R of
    +                {ok, ReturnCode, _, Body} ->
    +                    couch_log:debug("Swift: GET ~p with return code ~p 
~n", [NewUrl, ReturnCode]),                 
    +                    Body;
    +                Error ->
    +                    couch_log:debug("Swift: GET ~p failed. ~n", [NewUrl]),
    +                    couch_log:debug("Swift: ~p ~n", [element(2, Error)]),
    +                    {error, "Get object failed"}
    +            end;
    +        {not_authenticated, _} ->
    +            {error, "Not authenticated"}
    +    end.
    +
    +head_object(Container, ObjName) ->
    +    couch_log:debug("Swift: head object ~p/~p ~n", [Container, ObjName]),
    +    case authenticate() of
    +        {ok, {Url, Storage_Token}} ->
    +            Header = [{"X-Auth-Token", Storage_Token}],
    +            Method = head,
    +            ObjNameEncoded = couch_util:url_encode(ObjName),
    +            NewUrl = Url  ++ "/" ++ unicode:characters_to_list(Container)
    +                ++ "/" ++ unicode:characters_to_list(ObjNameEncoded),
    +            couch_log:debug("Swift: url ~p~n", [NewUrl]),
    +            R = ibrowse:send_req(NewUrl, Header, Method),
    +            case R of
    +                {ok, ReturnCode, Head, _} ->
    +                    couch_log:debug("Swift: ~p~p~n", [ReturnCode, Head]),  
    +                    ObjectSize = lists:filter(fun ({"Content-Length", _}) 
-> true; (_) -> false end, Head),
    +                    EtagHeader = lists:filter(fun ({"Etag", _}) -> true ; 
(_) -> false end, Head),
    +                    Etag = element(2, lists:nth(1, EtagHeader)),
    +                    {ObjectSizeNumeric, _} = string:to_integer(element(2, 
lists:nth(1, ObjectSize))),
    +                    couch_log:debug("Swift: Object size is: ~p and Etag: 
~p~n",
    +                                    [ObjectSizeNumeric, Etag]),
    +                    EtagDecode = hex_to_bin(Etag),
    +                    EtagMD5 = base64:encode(EtagDecode),
    +                    couch_log:debug("Etag in base64 ~p~n", [EtagMD5]),
    +                    {ok, {ObjectSizeNumeric, EtagMD5}};
    +                Error ->
    +                    couch_log:debug("Swift: Head ~p failed ~n", [NewUrl]),
    +                    couch_log:debug("Swift: ~p ~n", [element(2, Error)]),
    +                    {error,"HEAD object failed"}
    +            end;
    +        {not_authenticated, _} ->
    +            {error, "Not authenticated"}
    +    end.
    +
    +create_container(DbName) ->
    +    couch_log:debug("Swift : create container ~p~n", [DbName]),
    +    case authenticate() of
    +        {ok, {Url, Storage_Token}} ->
    +            Header = [{"X-Auth-Token",Storage_Token}],
    +            Method = put,
    +            Container = DbName,
    +            NewUrl = Url ++ "/" ++ unicode:characters_to_list(Container) 
++"/",
    +            couch_log:debug("Swift: url ~p ~n",[NewUrl]),
    +            R = ibrowse:send_req(NewUrl, Header, Method),
    +            case R of
    +                {ok, ReturnCode, _, _} ->
    +                    couch_log:debug("Swift: container ~p created with code 
: ~p~n",[Container, ReturnCode]),
    +                    {ok,{ReturnCode,Container}};   
    +                Error ->
    +                    couch_log:debug("Swift: container ~p creation failed : 
~p~n",[Container, element(2,Error)]),
    +                    {error, "Failed to create container"}  
    +            end;
    +        {not_authenticated,_} ->
    +            {error, "Failed to create container. Not authenticated"}
    +    end.
    +
    +delete_container(Container) ->
    +    case authenticate() of
    +        {ok,{Url,Storage_Token}} ->
    +        Header = [{"X-Auth-Token",Storage_Token}],
    +        Method = delete,
    +        NewUrl = Url ++ "/" ++ Container ++"/",
    +        R = ibrowse:send_req(NewUrl, Header, Method),
    +        case R of
    +            {ok, ReturnCode, _, _} ->
    +                    {ok,{ReturnCode,Container}};   
    +                Error ->
    +                    {error,{element(2,Error),Container}}   
    +        end;
    +        {not_authenticated, _} ->
    +            {error, "Not authenticated"};
    +        {not_supported, Error} ->
    +            {error,{element(2,Error),""}}
    +    end.
    +
    +%% ====================================================================
    +%% Internal functions
    +%% ====================================================================
    +
    +hex_to_bin(Str) -> << << (erlang:list_to_integer([H], 16)):4 >> || H <- 
Str >>.
    +
    +authenticate() ->
    +    couch_log:debug("Going to authenticate in Swift",[]),
    +    case config:get("swift", "auth_model", "tempauth") of
    +        "tempauth" ->
    +            swift_v1_auth();
    +        "keystone" ->
    +            keystone_auth();
    +        Error ->
    +            couch_log:debug("Authentication method is not supported: ~p", 
element(2,Error)),
    +            {not_authenticated, ""}
    +    end.
    +
    +keystone_auth() ->
    +    Method = post,
    +    URL = config:get("swift", "auth_url"),
    +    Header = [{"Content-Type", "application/json"}],
    +    Tenant = config:get("swift", "account_tenant"),
    +    User = config:get("swift", "username"),
    +    Psw = config:get("swift", "password"),
    +    Body = "{\"auth\": {\"tenantName\": \"" ++ Tenant
    +            ++ "\", \"passwordCredentials\": {\"username\": \""
    +            ++ User ++ "\", \"password\": \"" ++ Psw ++ "\"}}}",
    --- End diff --
    
    @kxepal I didn't mean to ask users to manually encode password. In any case 
"who is the user" here that should encode or not encode password? The "user" is 
actually CouchDB administrator that also own the Keystone account in Swift. I 
assume that his account already has ASCII password.  Anyway, it's not the 
point. I can gladly add encoding here. I assume CouchDB already has similar 
code fragments to encode double quotes or non ASCII characters. Can you please 
point me to the existing code where i can find something like this?


> Store large attachments external to the .couch file
> ---------------------------------------------------
>
>                 Key: COUCHDB-769
>                 URL: https://issues.apache.org/jira/browse/COUCHDB-769
>             Project: CouchDB
>          Issue Type: New Feature
>          Components: Database Core
>            Reporter: Robert Newson
>            Assignee: Adam Kocoloski
>         Attachments: external_attachments_alpha.patch
>
>
> For attachment-heavy applications storing the attachments in separate files 
> significantly eases compaction problems.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to