[
https://issues.apache.org/jira/browse/COUCHDB-769?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15103796#comment-15103796
]
ASF GitHub Bot commented on COUCHDB-769:
----------------------------------------
Github user kxepal commented on a diff in the pull request:
https://github.com/apache/couchdb-fabric/pull/33#discussion_r49949144
--- 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 --
@gilv If service accepts ASCII only passwords I'm in doubt if it's safe to
use it.
I'm not aware about such code, but all what you need to do is to construct
proper property list and encode it to JSON. That's all.
> 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)