Skip to content
This repository
Browse code

Initial commit

  • Loading branch information...
commit 18ddc875fe9ebd2a9219f328a16a4976c3677073 0 parents
Louis-Philippe Gauthier authored February 24, 2011
5  .gitignore
... ...
@@ -0,0 +1,5 @@
  1
+.eunit
  2
+deps
  3
+priv
  4
+*.o
  5
+*.beam
24  LICENSE
... ...
@@ -0,0 +1,24 @@
  1
+Copyright (c) 2011, BLOOM Digital Platforms, Louis-Philippe Gauthier
  2
+All rights reserved.
  3
+
  4
+Redistribution and use in source and binary forms, with or without
  5
+modification, are permitted provided that the following conditions are met:
  6
+    * Redistributions of source code must retain the above copyright
  7
+      notice, this list of conditions and the following disclaimer.
  8
+    * Redistributions in binary form must reproduce the above copyright
  9
+      notice, this list of conditions and the following disclaimer in the
  10
+      documentation and/or other materials provided with the distribution.
  11
+    * Neither the name of the BLOOM Digital Platforms nor the
  12
+      names of its contributors may be used to endorse or promote products
  13
+      derived from this software without specific prior written permission.
  14
+
  15
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  16
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  17
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18
+DISCLAIMED. IN NO EVENT SHALL BLOOM DIGITAL PLATFORMS BE LIABLE FOR ANY
  19
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  21
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  22
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  24
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  Makefile
... ...
@@ -0,0 +1,24 @@
  1
+PREFIX:=../
  2
+DEST:=$(PREFIX)$(PROJECT)
  3
+
  4
+REBAR=./rebar
  5
+
  6
+all:
  7
+	@$(REBAR) get-deps compile
  8
+
  9
+edoc:
  10
+	@$(REBAR) doc
  11
+
  12
+test:
  13
+	@rm -rf .eunit
  14
+	@mkdir -p .eunit
  15
+	@$(REBAR) skip_deps=true eunit
  16
+
  17
+clean:
  18
+	@$(REBAR) clean
  19
+
  20
+build_plt:
  21
+	@$(REBAR) build-plt
  22
+
  23
+dialyzer:
  24
+	@$(REBAR) dialyze
7  README
... ...
@@ -0,0 +1,7 @@
  1
+WORK IN PROGRESS
  2
+
  3
+1> cassanderl_app:start([],[]).
  4
+{ok,<0.33.0>}
  5
+2> cassanderl:call(describe_version, []).
  6
+{ok,<<"2.1.0">>
  7
+
9  ebin/cassanderl.app
... ...
@@ -0,0 +1,9 @@
  1
+{application,cassanderl,
  2
+             [{description,"A simple Cassandra client"},
  3
+              {vsn,"0.1"},
  4
+              {registered,[]},
  5
+              {applications,[kernel,stdlib]},
  6
+              {mod,{cassanderl,[]}},
  7
+              {env,[]},
  8
+              {modules,[cassanderl,cassanderl_app,cassanderl_deps,
  9
+                        cassanderl_worker]}]}.
BIN  rebar
Binary file not shown
7  rebar.config
... ...
@@ -0,0 +1,7 @@
  1
+%% -*- erlang -*-
  2
+{erl_opts, [debug_info]}.
  3
+{deps, [
  4
+  {poolboy, "0.2", {git, "https://github.com/lpgauth/poolboy.git", "master"}},
  5
+  {cassandra_thrift, "2.2.0", {git, "https://github.com/lpgauth/cassandra-thrift-erlang.git", "2.2.0"}},
  6
+  {thrift, "0.5.0", {git, "https://github.com/lpgauth/thrift-erlang.git", "master"}}
  7
+]}.
8  src/cassanderl.app.src
... ...
@@ -0,0 +1,8 @@
  1
+{application, cassanderl, [
  2
+    {description, "A simple Cassandra client"},
  3
+    {vsn, "0.1"},
  4
+    {registered, []},
  5
+    {applications, [kernel, stdlib]},
  6
+    {mod, {cassanderl, []}},
  7
+    {env, []}
  8
+]}.
51  src/cassanderl.erl
... ...
@@ -0,0 +1,51 @@
  1
+-module(cassanderl).
  2
+
  3
+-behaviour(supervisor).
  4
+
  5
+%% API
  6
+-export([start_link/0]).
  7
+
  8
+%% Supervisor callbacks
  9
+-export([init/1]).
  10
+
  11
+%% Internal API
  12
+-export([call/2]).
  13
+
  14
+%% Helper macro for declaring children of supervisor
  15
+-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
  16
+
  17
+%% ===================================================================
  18
+%% API functions
  19
+%% ===================================================================
  20
+
  21
+start_link() ->
  22
+    supervisor:start_link({local, ?MODULE}, ?MODULE, []).
  23
+
  24
+%% ===================================================================
  25
+%% Supervisor callbacks
  26
+%% ===================================================================
  27
+
  28
+init([]) ->
  29
+    PoolSpecs = [{cassandra,
  30
+                    {poolboy, start_link,
  31
+                        [[{name,
  32
+                            {local, cassandra}},
  33
+                            {worker_module, cassanderl_worker},
  34
+                            {pool_size, 10},
  35
+                            {max_overflow, 20},
  36
+                            {hostname, "127.0.0.1"},
  37
+                            {port, 9160}
  38
+                        ]]},
  39
+                permanent, 5000, worker, [poolboy]}],
  40
+    {ok, {{one_for_all, 10, 10}, PoolSpecs}}.
  41
+
  42
+%% ===================================================================
  43
+%% Internal API
  44
+%% ===================================================================
  45
+
  46
+call(Function, Args) ->
  47
+    Worker = poolboy:checkout(cassandra),
  48
+    Reply = gen_server:call(Worker, {call, Function, Args}),
  49
+    poolboy:checkin(cassandra, Worker),
  50
+    Reply.
  51
+
17  src/cassanderl_app.erl
... ...
@@ -0,0 +1,17 @@
  1
+-module(cassanderl_app).
  2
+
  3
+-behaviour(application).
  4
+
  5
+%% Application callbacks
  6
+-export([start/2, stop/1]).
  7
+
  8
+%% ===================================================================
  9
+%% Application callbacks
  10
+%% ===================================================================
  11
+
  12
+start(_StartType, _StartArgs) ->
  13
+    cassanderl_deps:ensure(),
  14
+    cassanderl:start_link().
  15
+
  16
+stop(_State) ->
  17
+    ok.
81  src/cassanderl_deps.erl
... ...
@@ -0,0 +1,81 @@
  1
+%% @doc Ensure that the relatively-installed dependencies are on the code
  2
+%%      loading path, and locate resources relative
  3
+%%      to this application's path.
  4
+
  5
+-module(cassanderl_deps).
  6
+
  7
+-export([ensure/0, ensure/1]).
  8
+-export([get_base_dir/0, get_base_dir/1]).
  9
+-export([local_path/1, local_path/2]).
  10
+-export([deps_on_path/0, new_siblings/1]).
  11
+
  12
+%% @spec deps_on_path() -> [ProjNameAndVers]
  13
+%% @doc List of project dependencies on the path.
  14
+deps_on_path() ->
  15
+    F = fun (X, Acc) ->
  16
+                ProjDir = filename:dirname(X),
  17
+                case {filename:basename(X),
  18
+                      filename:basename(filename:dirname(ProjDir))} of
  19
+                    {"ebin", "deps"} ->
  20
+                        [filename:basename(ProjDir) | Acc];
  21
+                    _ ->
  22
+                        Acc
  23
+                end
  24
+        end,
  25
+    ordsets:from_list(lists:foldl(F, [], code:get_path())).
  26
+
  27
+%% @spec new_siblings(Module) -> [Dir]
  28
+%% @doc Find new siblings paths relative to Module that aren't already on the
  29
+%%      code path.
  30
+new_siblings(Module) ->
  31
+    Existing = deps_on_path(),
  32
+    SiblingEbin = filelib:wildcard(local_path(["deps", "*", "ebin"], Module)),
  33
+    Siblings = [filename:dirname(X) || X <- SiblingEbin,
  34
+                           ordsets:is_element(
  35
+                             filename:basename(filename:dirname(X)),
  36
+                             Existing) =:= false],
  37
+    lists:filter(fun filelib:is_dir/1,
  38
+                 lists:append([[filename:join([X, "ebin"]),
  39
+                                filename:join([X, "include"])] ||
  40
+                                  X <- Siblings])).
  41
+
  42
+
  43
+%% @spec ensure(Module) -> ok
  44
+%% @doc Ensure that all ebin and include paths for dependencies
  45
+%%      of the application for Module are on the code path.
  46
+ensure(Module) ->
  47
+    code:add_paths(new_siblings(Module)),
  48
+    code:clash(),
  49
+    ok.
  50
+
  51
+%% @spec ensure() -> ok
  52
+%% @doc Ensure that the ebin and include paths for dependencies of
  53
+%%      this application are on the code path. Equivalent to
  54
+%%      ensure(?Module).
  55
+ensure() ->
  56
+    ensure(?MODULE).
  57
+
  58
+%% @spec get_base_dir(Module) -> string()
  59
+%% @doc Return the application directory for Module. It assumes Module is in
  60
+%%      a standard OTP layout application in the ebin or src directory.
  61
+get_base_dir(Module) ->
  62
+    {file, Here} = code:is_loaded(Module),
  63
+    filename:dirname(filename:dirname(Here)).
  64
+
  65
+%% @spec get_base_dir() -> string()
  66
+%% @doc Return the application directory for this application. Equivalent to
  67
+%%      get_base_dir(?MODULE).
  68
+get_base_dir() ->
  69
+    get_base_dir(?MODULE).
  70
+
  71
+%% @spec local_path([string()], Module) -> string()
  72
+%% @doc Return an application-relative directory from Module's application.
  73
+local_path(Components, Module) ->
  74
+    filename:join([get_base_dir(Module) | Components]).
  75
+
  76
+%% @spec local_path(Components) -> string()
  77
+%% @doc Return an application-relative directory for this application.
  78
+%%      Equivalent to local_path(Components, ?MODULE).
  79
+local_path(Components) ->
  80
+    local_path(Components, ?MODULE).
  81
+
42  src/cassanderl_worker.erl
... ...
@@ -0,0 +1,42 @@
  1
+-module(cassanderl_worker).
  2
+
  3
+-behaviour(gen_server).
  4
+
  5
+-export([start_link/1, stop/0, init/1, handle_call/3, handle_cast/2,
  6
+         handle_info/2, terminate/2, code_change/3]).
  7
+
  8
+-record(state, {conn}).
  9
+
  10
+start_link(Args) -> gen_server:start_link(?MODULE, Args, []).
  11
+stop() -> gen_server:cast(?MODULE, stop).
  12
+
  13
+init(Args) ->
  14
+    process_flag(trap_exit, true),
  15
+    Hostname = proplists:get_value(hostname, Args),
  16
+    Port = proplists:get_value(port, Args),
  17
+    {ok, Conn} = thrift_client_util:new(Hostname, Port, cassandra_thrift, []), ok,
  18
+    {ok, #state{conn=Conn}}.
  19
+
  20
+handle_call({call, Function, Args}, _From, #state{conn=Conn}=State) ->
  21
+    {NewConn, Response} = thrift_client:call(Conn, Function, Args), Response,
  22
+    NewState = State#state{conn=NewConn},
  23
+    {reply, Response, NewState};
  24
+handle_call(_Request, _From, State) ->
  25
+    {reply, ok, State}.
  26
+
  27
+handle_cast(stop, State) ->
  28
+    {stop, shutdown, State};
  29
+handle_cast(_Msg, State) ->
  30
+    {noreply, State}.
  31
+
  32
+handle_info({'EXIT', _, _}, State) ->
  33
+    {stop, shutdown, State};
  34
+handle_info(_Info, State) ->
  35
+    {noreply, State}.
  36
+
  37
+terminate(_Reason, #state{conn=Conn}) ->
  38
+    thrift_client:close(Conn),
  39
+    ok.
  40
+
  41
+code_change(_OldVsn, State, _Extra) ->
  42
+    {ok, State}.

0 notes on commit 18ddc87

Please sign in to comment.
Something went wrong with that request. Please try again.