Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

changes for pooling connections

  • Loading branch information...
commit e26f0cedc3d00684eed38721a7e25fdf061902b5 1 parent d7ddf01
Ali Yakamercan authored
View
1  c_src/callbacks.h
@@ -2,7 +2,6 @@
#define CALLBACKS_H
#include <stdio.h>
-#include "config.h"
#include <string.h>
#include <libcouchbase/couchbase.h>
View
186 c_src/config.h
@@ -1,186 +0,0 @@
-/* src/config.h. Generated from config.h.in by configure. */
-/* src/config.h.in. Generated from configure.ac by autoheader. */
-
-
-#ifndef CONFIG_H
-#define CONFIG_H
-/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- * Copyright 2010, 2011 Couchbase, Inc.
- *
- * 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.
- */
-
-/*
- * This file is generated by running configure. Any changes you make to this
- * file will be overwritten the next time you run configure. If you want to
- * make permanent changes to the file you should edit configure.ac instead.
- * All platform-specific includes should be placed inside config_static.h
- * to keep the config.h as small as possible. That allows us for easily
- * use another build systems with a poor support for automake (like Windows)
- *
- * @author Trond Norbye
- */
-
-
-/* Define to 1 if you have the `clock_gettime' function. */
-/* #undef HAVE_CLOCK_GETTIME */
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if you have the <event.h> header file. */
-#define HAVE_EVENT_H 1
-
-/* Define to 1 if you have the `gethrtime' function. */
-/* #undef HAVE_GETHRTIME */
-
-/* Define to 1 if you have the `gettimeofday' function. */
-#define HAVE_GETTIMEOFDAY 1
-
-/* Have ntohll */
-/* #undef HAVE_HTONLL */
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* We have libevent2 */
-#define HAVE_LIBEVENT2 1
-
-/* Define to 1 if you have the <libvbucket/vbucket.h> header file. */
-#define HAVE_LIBVBUCKET_VBUCKET_H 1
-
-/* We have libyajl2 */
-/* #undef HAVE_LIBYAJL2 */
-
-/* Define to 1 if you have the <mach/mach_time.h> header file. */
-/* #undef HAVE_MACH_MACH_TIME_H */
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the <netdb.h> header file. */
-#define HAVE_NETDB_H 1
-
-/* Define to 1 if you have the <netinet/in.h> header file. */
-#define HAVE_NETINET_IN_H 1
-
-/* Define to 1 if you have the `QueryPerformanceCounter' function. */
-/* #undef HAVE_QUERYPERFORMANCECOUNTER */
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Use system internal sasl */
-/* #undef HAVE_SYSTEM_LIBSASL */
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to 1 if you have the <winsock2.h> header file. */
-/* #undef HAVE_WINSOCK2_H */
-
-/* Define to 1 if you have the <ws2tcpip.h> header file. */
-/* #undef HAVE_WS2TCPIP_H */
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-#define LT_OBJDIR ".libs/"
-
-/* Define to 1 if your C compiler doesn't accept -c and -o together. */
-/* #undef NO_MINUS_C_MINUS_O */
-
-/* Name of package */
-#define PACKAGE "libcouchbase"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "support@couchbase.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "libcouchbase"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libcouchbase 1.1.0dp7_43_gd9e354e"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libcouchbase"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "1.1.0dp7_43_gd9e354e"
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Enable extensions on AIX 3, Interix. */
-#ifndef _ALL_SOURCE
-# define _ALL_SOURCE 1
-#endif
-/* Enable GNU extensions on systems that have them. */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-#endif
-/* Enable threading extensions on Solaris. */
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# define _POSIX_PTHREAD_SEMANTICS 1
-#endif
-/* Enable extensions on HP NonStop. */
-#ifndef _TANDEM_SOURCE
-# define _TANDEM_SOURCE 1
-#endif
-/* Enable general extensions on Solaris. */
-#ifndef __EXTENSIONS__
-# define __EXTENSIONS__ 1
-#endif
-
-
-/* Version number of package */
-#define VERSION "1.1.0dp7_43_gd9e354e"
-
-/* Define to 1 if on MINIX. */
-/* #undef _MINIX */
-
-/* Define to 2 if the system does not provide POSIX.1 features except with
- this defined. */
-/* #undef _POSIX_1_SOURCE */
-
-/* Define to 1 if you need to in order for `stat' and other things to work. */
-/* #undef _POSIX_SOURCE */
-
-
-#include "config_static.h"
-#endif
-
View
107 c_src/config_static.h
@@ -1,107 +0,0 @@
-/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- * Copyright 2010, 2011 Couchbase, Inc.
- *
- * 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.
- */
-
-/**
- * This file contains the static part of the configure script. Please add
- * all platform specific conditional code to this file.
- *
- * @author Trond Norbye
- */
-#ifndef LIBCOUCHBASE_CONFIG_STATIC_H
-#define LIBCOUCHBASE_CONFIG_STATIC_H 1
-
-#if !defined HAVE_STDINT_H && defined WIN32
-# include "win_stdint.h"
-#else
-# include <stdint.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
-
-#ifdef HAVE_WS2TCPIP_H
-#include <ws2tcpip.h>
-#endif
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#ifdef _WIN32
-#include "win32/win_errno_sock.h"
-typedef int ssize_t;
-#define snprintf _snprintf
-#undef strdup
-#define strdup _strdup
-#else
-#define INVALID_SOCKET -1
-#define SOCKET_ERROR -1
-#endif /* _WIN32 */
-
-#ifndef HAVE_HTONLL
-#ifdef WORDS_BIGENDIAN
-#define ntohll(a) a
-#define htonll(a) a
-#else
-#define ntohll(a) libcouchbase_byteswap64(a)
-#define htonll(a) libcouchbase_byteswap64(a)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
- extern uint64_t libcouchbase_byteswap64(uint64_t val);
-#ifdef __cplusplus
-}
-#endif
-#endif /* WORDS_BIGENDIAN */
-#endif /* HAVE_HTONLL */
-
-
-#ifdef linux
-#undef ntohs
-#undef ntohl
-#undef htons
-#undef htonl
-#endif
-
-#ifndef HAVE_GETHRTIME
-typedef uint64_t hrtime_t;
-extern hrtime_t gethrtime(void);
-#endif
-
-#endif /* LIBCOUCHBASE_CONFIG_STATIC_H */
View
7 rebar.config
@@ -7,5 +7,10 @@
{port_specs, [{"priv/cberl_drv.so", ["c_src/*.c"]}]}.
{deps, [
- {'jiffy', "", {git, "https://github.com/davisp/jiffy.git", {branch, master}}}
+ {'jiffy', "", {git, "https://github.com/davisp/jiffy.git", {branch, master}}},
+ {'poolboy', "", {git, "git@github.com:devinus/poolboy.git", {branch, master}}}
]}.
+
+{erl_opts, [debug_info, warnings_as_errors]}.
+{eunit_opts, [verbose]}.
+{cover_enabled, true}.
View
218 src/cberl.erl
@@ -6,28 +6,33 @@
-module(cberl).
-include("cberl.hrl").
--export([new/0, new/1, new/3, new/4, remove/2, destroy/1]).
--export([store/7, mget/3, getl/3, arithmetic/6]).
+
+-export([start_link/2, start_link/3, start_link/5, start_link/6]).
+-export([stop/1]).
%store operations
--export([add/4, add/5, replace/4, replace/5, set/4, set/5]).
+-export([add/4, add/5, replace/4, replace/5, set/4, set/5, store/7]).
%update operations
-export([append/4, prepend/4, touch/3, mtouch/3]).
-export([incr/3, incr/4, incr/5, decr/3, decr/4, decr/5]).
+-export([arithmetic/6]).
%retrieval operations
--export([get_and_touch/3, get_and_lock/3, mget/2, get/2, unlock/3]).
+-export([get_and_touch/3, get_and_lock/3, mget/2, get/2, unlock/3,
+ mget/3, getl/3]).
+%remove
+-export([remove/2]).
-%% @equiv new("localhost:8091", "", "", "")
-new() ->
- new("localhost:8091", "", "", "").
+%% @equiv start_link(PoolName, NumCon, "localhost:8091", "", "", "")
+start_link(PoolName, NumCon) ->
+ start_link(PoolName, NumCon, "localhost:8091", "", "", "").
-%% @equiv new(Host, "", "", "")
-new(Host) ->
- new(Host, "", "", "").
+%% @equiv start_link(PoolName, NumCon, Host, "", "", "")
+start_link(PoolName, NumCon, Host) ->
+ start_link(PoolName, NumCon, Host, "", "", "").
-%% @equiv new(Host, Username, Password, "")
-new(Host, Username, Password) ->
- new(Host, Username, Password, "").
+%% @equiv start_link(PoolName, NumCon, Host, Username, Password, "")
+start_link(PoolName, NumCon, Host, Username, Password) ->
+ start_link(PoolName, NumCon, Host, Username, Password, "").
%% @doc Create an instance of libcouchbase
%% hosts A list of hosts:port separated by ';' to the
@@ -38,121 +43,125 @@ new(Host, Username, Password) ->
%% Username the username to use
%% Password The password
%% bucket The bucket to connect to
--spec new(string(), string(), string(), string()) -> {ok, instance()} | {error, _}.
-new(Host, Username, Password, BucketName) ->
- new(Host, Username, Password, BucketName, cberl_transcoder).
+-spec start_link(atom(), integer(), string(), string(), string(), string()) -> {ok, instance()} | {error, _}.
+start_link(PoolName, NumCon, Host, Username, Password, BucketName) ->
+ start_link(PoolName, NumCon, Host, Username, Password, BucketName, cberl_transcoder).
-new(Host, Username, Password, BucketName, Transcoder) ->
- {ok, Handle} = cberl_nif:new(Host, Username, Password, BucketName),
- {ok, #instance{handle = Handle, transcoder = Transcoder}}.
+start_link(PoolName, NumCon, Host, Username, Password, BucketName, Transcoder) ->
+ SizeArgs = [{size, NumCon},
+ {max_overflow, 10}],
+ PoolArgs = [{name, {local, PoolName}},
+ {worker_module, cberl_worker}] ++ SizeArgs,
+ poolboy:start(PoolArgs, [Host, Username, Password, BucketName, Transcoder]).
%%%%%%%%%%%%%%%%%%%%%%%%
%%% STORE OPERATIONS %%%
%%%%%%%%%%%%%%%%%%%%%%%%
-%% @equiv add(Instance, Key, Exp, Value, standard)
+%% @equiv add(PoolName, Key, Exp, Value, standard)
-spec add(instance(), key(), integer(), value()) -> ok | {error, _}.
-add(Instance, Key, Exp, Value) ->
- add(Instance, Key, Exp, Value, standard).
+add(PoolName, Key, Exp, Value) ->
+ add(PoolName, Key, Exp, Value, standard).
-%% @equiv store(Instance, add, Key, Value, TranscoderOpts, Exp, 0)
+%% @equiv store(PoolName, add, Key, Value, TranscoderOpts, Exp, 0)
-spec add(instance(), key(), integer(), value(), atom()) -> ok | {error, _}.
-add(Instance, Key, Exp, Value, TranscoderOpts) ->
- store(Instance, add, Key, Value, TranscoderOpts, Exp, 0).
+add(PoolName, Key, Exp, Value, TranscoderOpts) ->
+ store(PoolName, add, Key, Value, TranscoderOpts, Exp, 0).
-%% @equiv replace(Instance, Key, Exp, Value, standard)
+%% @equiv replace(PoolName, Key, Exp, Value, standard)
-spec replace(instance(), key(), integer(), value()) -> ok | {error, _}.
-replace(Instance, Key, Exp, Value) ->
- replace(Instance, Key, Exp, Value, standard).
+replace(PoolName, Key, Exp, Value) ->
+ replace(PoolName, Key, Exp, Value, standard).
-%% @equiv store(Instance, replace, "", Key, Value, Exp)
+%% @equiv store(PoolName, replace, "", Key, Value, Exp)
-spec replace(instance(), key(), integer(), value(), atom()) -> ok | {error, _}.
-replace(Instance, Key, Exp, Value, TranscoderOpts) ->
- store(Instance, replace, Key, Value, TranscoderOpts, Exp, 0).
+replace(PoolName, Key, Exp, Value, TranscoderOpts) ->
+ store(PoolName, replace, Key, Value, TranscoderOpts, Exp, 0).
-%% @equiv set(Instance, Key, Exp, Value, standard)
+%% @equiv set(PoolName, Key, Exp, Value, standard)
-spec set(instance(), key(), integer(), value()) -> ok | {error, _}.
-set(Instance, Key, Exp, Value) ->
- set(Instance, Key, Exp, Value, standard).
+set(PoolName, Key, Exp, Value) ->
+ set(PoolName, Key, Exp, Value, standard).
-%% @equiv store(Instance, set, "", Key, Value, Exp)
+%% @equiv store(PoolName, set, "", Key, Value, Exp)
-spec set(instance(), key(), integer(), value(), integer()) -> ok | {error, _}.
-set(Instance, Key, Exp, Value, TranscoderOpts) ->
- store(Instance, set, Key, Value, TranscoderOpts, Exp, 0).
+set(PoolName, Key, Exp, Value, TranscoderOpts) ->
+ store(PoolName, set, Key, Value, TranscoderOpts, Exp, 0).
%%%%%%%%%%%%%%%%%%%%%%%%%
%%% UPDATE OPERATIONS %%%
%%%%%%%%%%%%%%%%%%%%%%%%%
-spec append(instance(), integer(), key(), value()) -> ok | {error, _}.
-append(Instance, Cas, Key, Value) ->
- store(Instance, append, Key, Value, str, 0, Cas).
+append(PoolName, Cas, Key, Value) ->
+ store(PoolName, append, Key, Value, str, 0, Cas).
-spec prepend(instance(), integer(), key(), value()) -> ok | {error, _}.
-prepend(Instance, Cas, Key, Value) ->
- store(Instance, prepend, Key, Value, str, 0, Cas).
+prepend(PoolName, Cas, Key, Value) ->
+ store(PoolName, prepend, Key, Value, str, 0, Cas).
%% @doc Touch (set expiration time) on the given key
-%% Instance libcouchbase instance to use
+%% PoolName libcouchbase instance to use
%% Key key to touch
%% ExpTime a new expiration time for the item
-spec mtouch(instance(), key(), integer()) -> ok | {error, _}.
-touch(Instance, Key, ExpTime) ->
- {ok, Return} = mtouch(Instance, [Key], [ExpTime]),
+touch(PoolName, Key, ExpTime) ->
+ {ok, Return} = mtouch(PoolName, [Key], [ExpTime]),
{ok, hd(Return)}.
-mtouch(Instance, Keys, ExpTime) when is_integer(ExpTime) ->
- mtouch(Instance, Keys, [ExpTime]);
-mtouch(#instance{handle = Handle}, Keys, ExpTimes) ->
+mtouch(PoolName, Keys, ExpTime) when is_integer(ExpTime) ->
+ mtouch(PoolName, Keys, [ExpTime]);
+mtouch(PoolName, Keys, ExpTimes) ->
ExpTimesE = case length(Keys) - length(ExpTimes) of
R when R > 0 ->
ExpTimes ++ lists:duplicate(R, lists:last(ExpTimes));
_ ->
ExpTimes
end,
- cberl_nif:mtouch(Handle, Keys, ExpTimesE).
+ execute(PoolName, {mtouch, Keys, ExpTimesE}).
-incr(Instance, Key, OffSet) ->
- arithmetic(Instance, Key, OffSet, 0, 0, 0).
+incr(PoolName, Key, OffSet) ->
+ arithmetic(PoolName, Key, OffSet, 0, 0, 0).
-incr(Instance, Key, OffSet, Default) ->
- arithmetic(Instance, Key, OffSet, 0, 1, Default).
+incr(PoolName, Key, OffSet, Default) ->
+ arithmetic(PoolName, Key, OffSet, 0, 1, Default).
-incr(Instance, Key, OffSet, Default, Exp) ->
- arithmetic(Instance, Key, OffSet, Exp, 1, Default).
+incr(PoolName, Key, OffSet, Default, Exp) ->
+ arithmetic(PoolName, Key, OffSet, Exp, 1, Default).
-decr(Instance, Key, OffSet) ->
- arithmetic(Instance, Key, -OffSet, 0, 0, 0).
+decr(PoolName, Key, OffSet) ->
+ arithmetic(PoolName, Key, -OffSet, 0, 0, 0).
-decr(Instance, Key, OffSet, Default) ->
- arithmetic(Instance, Key, -OffSet, 0, 1, Default).
+decr(PoolName, Key, OffSet, Default) ->
+ arithmetic(PoolName, Key, -OffSet, 0, 1, Default).
-decr(Instance, Key, OffSet, Default, Exp) ->
- arithmetic(Instance, Key, -OffSet, Exp, 1, Default).
+decr(PoolName, Key, OffSet, Default, Exp) ->
+ arithmetic(PoolName, Key, -OffSet, Exp, 1, Default).
%%%%%%%%%%%%%%%%%%%%%%%%%
%%% RETRIEVAL METHODS %%%
%%%%%%%%%%%%%%%%%%%%%%%%%
-spec get_and_touch(instance(), key(), integer()) -> {ok, integer(), value()} | {error, _}.
-get_and_touch(Instance, Key, Exp) ->
- mget(Instance, [Key], Exp).
+get_and_touch(PoolName, Key, Exp) ->
+ mget(PoolName, [Key], Exp).
-spec get(instance(), key()) -> {ok, integer(), value()} | {error, _}.
-get(Instance, Key) ->
- hd(mget(Instance, [Key], 0)).
+get(PoolName, Key) ->
+ hd(mget(PoolName, [Key], 0)).
-mget(Instance, Keys) ->
- mget(Instance, Keys, 0).
+mget(PoolName, Keys) ->
+ mget(PoolName, Keys, 0).
-spec get_and_lock(instance(), key(), integer()) -> {ok, integer(), value()} | {error, _}.
-get_and_lock(Instance, Key, Exp) ->
- getl(Instance, Key, Exp).
+get_and_lock(PoolName, Key, Exp) ->
+ getl(PoolName, Key, Exp).
-spec unlock(instance(), key(), integer()) -> ok | {error, _}.
-unlock(#instance{handle = Handle}, Key, Cas) ->
- cberl_nif:unlock(Handle, Key, Cas).
+unlock(PoolName, Key, Cas) ->
+ execute(PoolName, {unlock, Key, Cas}).
+
%% @doc main store function takes care of all storing
%% Instance libcouchbase instance to use
%% Op add | replace | set | append | prepend
@@ -172,11 +181,10 @@ unlock(#instance{handle = Handle}, Key, Cas) ->
%% CAS
-spec store(instance(), operation_type(), key(), value(), atom(),
integer(), integer()) -> ok | {error, _}.
-store(#instance{handle = Handle, transcoder = Transcoder}, Op, Key, Value, TranscoderOpts, Exp, Cas) ->
- StoreValue = Transcoder:encode_value(TranscoderOpts, Value),
- cberl_nif:store(Handle, operation_value(Op), Key, StoreValue,
- Transcoder:flag(TranscoderOpts), Exp, Cas).
-
+store(PoolName, Op, Key, Value, TranscoderOpts, Exp, Cas) ->
+ execute(PoolName, {store, Op, Key, Value,
+ TranscoderOpts, Exp, Cas}).
+
%% @doc get the value for the given key
%% Instance libcouchbase instance to use
%% HashKey the key to use for hashing
@@ -184,34 +192,17 @@ store(#instance{handle = Handle, transcoder = Transcoder}, Op, Key, Value, Trans
%% Exp When the object should expire
%% pass a negative number for infinity
-spec mget(instance(), key(), integer()) -> {ok, integer(), value()} | {error, _}.
-mget(#instance{handle = Handle, transcoder = Transcoder}, Keys, Exp) ->
- case cberl_nif:mget(Handle, Keys, Exp) of
- {error, Error} -> {error, Error};
- {ok, Results} ->
- lists:map(fun(Result) ->
- case Result of
- {Cas, Flag, Key, Value} ->
- DecodedValue = Transcoder:decode_value(Flag, Value),
- {ok, Cas, DecodedValue};
- {_Key, {error, _Error}} ->
- Result
- end
- end, Results)
- end.
-
+mget(PoolName, Keys, Exp) ->
+ execute(PoolName, {mget, Keys, Exp}).
+
%% @doc Get an item with a lock that has a timeout
%% Instance libcouchbase instance to use
%% HashKey the key to use for hashing
%% Key the key to get
%% Exp When the lock should expire
-spec getl(instance(), key(), integer()) -> {ok, integer(), value()} | {error, _}.
-getl(#instance{handle = Handle, transcoder = Transcoder}, Key, Exp) ->
- case cberl_nif:getl(Handle, Key, Exp) of
- {error, Error} -> {error, Error};
- {ok, {Cas, Flag, Value}} ->
- DecodedValue = Transcoder:decode_value(Flag, Value),
- {ok, Cas, DecodedValue}
- end.
+getl(PoolName, Key, Exp) ->
+ execute(PoolName, {getl, Key, Exp}).
%% @doc perform an arithmetic operation on the given key
%% Instance libcouchbase instance to use
@@ -223,33 +214,20 @@ getl(#instance{handle = Handle, transcoder = Transcoder}, Key, Exp) ->
%% Initial The initial value of the object if we create it
-spec arithmetic(instance(), key(), integer(), integer(), integer(), integer()) ->
ok | {error, _}.
-arithmetic(#instance{handle = Handle, transcoder = Transcoder}, Key, OffSet, Exp, Create, Initial) ->
- case cberl_nif:arithmetic(Handle, Key, OffSet, Exp, Create, Initial) of
- {error, Error} -> {error, Error};
- {ok, {Cas, Flag, Value}} ->
- DecodedValue = Transcoder:decode_value(Flag, Value),
- {ok, Cas, DecodedValue}
- end.
+arithmetic(PoolName, Key, OffSet, Exp, Create, Initial) ->
+ execute(PoolName, {arithmetic, Key, OffSet, Exp, Create, Initial}).
%% @doc remove the value for given key
%% Instance libcouchbase instance to use
%% Key key to remove
-spec remove(instance(), key()) -> ok | {error, _}.
-remove(#instance{handle = Handle}, Key) ->
- cberl_nif:remove(Handle, Key, 0).
-
-%% @doc close the libcouchbase instance
-destroy(#instance{handle = Handle}) ->
- cberl_nif:destroy(Handle).
-
+remove(PoolName, Key) ->
+ execute(PoolName, {remove, Key, 0}).
-%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%% INTERNAL FUNCTIONS %%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%
+stop(PoolName) ->
+ poolboy:stop(PoolName).
--spec operation_value(operation_type()) -> integer().
-operation_value(add) -> ?'CBE_ADD';
-operation_value(replace) -> ?'CBE_REPLACE';
-operation_value(set) -> ?'CBE_SET';
-operation_value(append) -> ?'CBE_APPEND';
-operation_value(prepend) -> ?'CBE_PREPEND'.
+execute(PoolName, Cmd) ->
+ poolboy:transaction(PoolName, fun(Worker) ->
+ gen_server:call(Worker, Cmd)
+ end).
View
179 src/cberl_worker.erl
@@ -0,0 +1,179 @@
+-module(cberl_worker).
+-include("cberl.hrl").
+-behaviour(gen_server).
+
+%% API
+-export([start_link/1]).
+
+%% gen_server callbacks
+-export([init/1,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ terminate/2,
+ code_change/3]).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the server
+%%
+%% @spec start_link(Args) -> {ok, Pid} | ignore | {error, Error}
+%% @end
+%%--------------------------------------------------------------------
+start_link(Args) ->
+ gen_server:start_link(?MODULE, Args, []).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Initializes the server
+%%
+%% @spec init(Args) -> {ok, State} |
+%% {ok, State, Timeout} |
+%% ignore |
+%% {stop, Reason}
+%% @end
+%%--------------------------------------------------------------------
+init([Host, Username, Password, BucketName, Transcoder]) ->
+ {ok, Handle} = cberl_nif:new(Host, Username, Password, BucketName),
+ {ok, #instance{handle = Handle, transcoder = Transcoder}}.
+
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling call messages
+%%
+%% @spec handle_call(Request, From, State) ->
+%% {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} |
+%% {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+handle_call({mtouch, Keys, ExpTimesE}, _From,
+ State = #instance{handle = Handle}) ->
+ {reply, cberl_nif:mtouch(Handle, Keys, ExpTimesE), State};
+handle_call({unlock, Key, Cas}, _From,
+ State = #instance{handle = Handle}) ->
+ {reply, cberl_nif:unlock(Handle, Key, Cas), State};
+handle_call({store, Op, Key, Value, TranscoderOpts, Exp, Cas}, _From,
+ State = #instance{handle = Handle, transcoder = Transcoder}) ->
+ StoreValue = Transcoder:encode_value(TranscoderOpts, Value),
+ Reply = cberl_nif:store(Handle, operation_value(Op), Key, StoreValue,
+ Transcoder:flag(TranscoderOpts), Exp, Cas),
+ {reply, Reply, State};
+handle_call({mget, Keys, Exp}, _From,
+ State = #instance{handle = Handle, transcoder = Transcoder}) ->
+ Reply = case cberl_nif:mget(Handle, Keys, Exp) of
+ {error, Error} -> {error, Error};
+ {ok, Results} ->
+ lists:map(fun(Result) ->
+ case Result of
+ {Cas, Flag, Key, Value} ->
+ DecodedValue = Transcoder:decode_value(Flag, Value),
+ {Key, Cas, DecodedValue};
+ {_Key, {error, _Error}} ->
+ Result
+ end
+ end, Results)
+ end,
+ {reply, Reply, State};
+handle_call({getl, Key, Exp}, _From,
+ State = #instance{handle = Handle, transcoder = Transcoder}) ->
+ Reply = case cberl_nif:getl(Handle, Key, Exp) of
+ {error, Error} -> {error, Error};
+ {ok, {Cas, Flag, Value}} ->
+ DecodedValue = Transcoder:decode_value(Flag, Value),
+ {ok, Cas, DecodedValue}
+ end,
+ {reply, Reply, State};
+handle_call({arithmetic, Key, OffSet, Exp, Create, Initial}, _From,
+ State = #instance{handle = Handle, transcoder = Transcoder}) ->
+ Reply =
+ case cberl_nif:arithmetic(Handle, Key, OffSet, Exp, Create, Initial) of
+ {error, Error} -> {error, Error};
+ {ok, {Cas, Flag, Value}} ->
+ DecodedValue = Transcoder:decode_value(Flag, Value),
+ {ok, Cas, DecodedValue}
+ end,
+ {reply, Reply, State};
+handle_call({remove, Key, N}, _From,
+ State = #instance{handle = Handle}) ->
+ {reply, cberl_nif:remove(Handle, Key, N), State};
+handle_call(_Request, _From, State) ->
+ Reply = ok,
+ {reply, Reply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling cast messages
+%%
+%% @spec handle_cast(Msg, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling all non call/cast messages
+%%
+%% @spec handle_info(Info, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any
+%% necessary cleaning up. When it returns, the gen_server terminates
+%% with Reason. The return value is ignored.
+%%
+%% @spec terminate(Reason, State) -> void()
+%% @end
+%%--------------------------------------------------------------------
+terminate(_Reason, _State = #instance{handle = Handle}) ->
+ cberl_nif:destroy(Handle),
+ ok.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Convert process state when code is changed
+%%
+%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% @end
+%%--------------------------------------------------------------------
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+
+-spec operation_value(operation_type()) -> integer().
+operation_value(add) -> ?'CBE_ADD';
+operation_value(replace) -> ?'CBE_REPLACE';
+operation_value(set) -> ?'CBE_SET';
+operation_value(append) -> ?'CBE_APPEND';
+operation_value(prepend) -> ?'CBE_PREPEND'.
View
68 test/cberl_tests.erl
@@ -1,6 +1,6 @@
-module(cberl_tests).
-include_lib("eunit/include/eunit.hrl").
-
+-define(POOLNAME, testpool).
cberl_test_() ->
[{foreach, fun setup/0, fun clean_up/1,
@@ -11,51 +11,51 @@ cberl_test_() ->
%%% Setup / Teardown
%%%===================================================================
setup() ->
- {ok, Instance} = cberl:new(),
- Instance.
+ cberl:start_link(?POOLNAME, 3),
+ ok.
-clean_up(Instance) ->
- cberl:remove(Instance, "testkey"),
- cberl:remove(Instance, "testkey1"),
- cberl:remove(Instance, "notestkey"),
- ok = cberl:destroy(Instance).
+clean_up(_) ->
+ cberl:remove(?POOLNAME, "testkey"),
+ cberl:remove(?POOLNAME, "testkey1"),
+ cberl:remove(?POOLNAME, "notestkey"),
+ cberl:stop(?POOLNAME).
%%%===================================================================
%%% Tests
%%%===================================================================
-test_set_and_get(Instance) ->
- ok = cberl:set(Instance, "testkey", 0, "testval"),
- Get1 = cberl:get(Instance, "testkey"),
- ok = cberl:set(Instance, "testkey", 0, "testval", json),
- Get2 = cberl:get(Instance, "testkey"),
- ok = cberl:set(Instance, "testkey", 0, "testval", raw_binary),
- Get3 = cberl:get(Instance, "testkey"),
- [?_assertEqual({ok, 0, "testval"}, Get1),
- ?_assertEqual({ok, 0, "testval"}, Get2),
- ?_assertEqual({ok, 0, "testval"}, Get3)
+test_set_and_get(_) ->
+ ok = cberl:set(?POOLNAME, "testkey", 0, "testval"),
+ Get1 = cberl:get(?POOLNAME, "testkey"),
+ ok = cberl:set(?POOLNAME, "testkey", 0, "testval", json),
+ Get2 = cberl:get(?POOLNAME, "testkey"),
+ ok = cberl:set(?POOLNAME, "testkey", 0, "testval", raw_binary),
+ Get3 = cberl:get(?POOLNAME, "testkey"),
+ [?_assertEqual({"testkey", 0, "testval"}, Get1),
+ ?_assertEqual({"testkey", 0, "testval"}, Get2),
+ ?_assertEqual({"testkey", 0, "testval"}, Get3)
].
-test_replace_add(Instance) ->
- ok = cberl:set(Instance, "testkey", 0, "testval"),
- AddFail = cberl:add(Instance, "testkey", 0, "testval"),
- AddPass = cberl:add(Instance, "testkey1", 0, "testval"),
- ReplaceFail = cberl:replace(Instance, "notestkey", 0, "testval"),
- ok = cberl:replace(Instance, "testkey", 0, "testval1"),
- Get1 = cberl:get(Instance, "testkey"),
+test_replace_add(_) ->
+ ok = cberl:set(?POOLNAME, "testkey", 0, "testval"),
+ AddFail = cberl:add(?POOLNAME, "testkey", 0, "testval"),
+ AddPass = cberl:add(?POOLNAME, "testkey1", 0, "testval"),
+ ReplaceFail = cberl:replace(?POOLNAME, "notestkey", 0, "testval"),
+ ok = cberl:replace(?POOLNAME, "testkey", 0, "testval1"),
+ Get1 = cberl:get(?POOLNAME, "testkey"),
[?_assertEqual({error, key_eexists}, AddFail),
?_assertEqual(ok, AddPass),
?_assertEqual({error, key_enoent}, ReplaceFail),
- ?_assertEqual({ok, 0, "testval1"}, Get1)
+ ?_assertEqual({"testkey", 0, "testval1"}, Get1)
].
-test_append_prepend(Instance) ->
- ok = cberl:set(Instance, "testkey", 0, "base", str),
- ok = cberl:append(Instance, 0, "testkey", "tail"),
- Get1 = cberl:get(Instance, "testkey"),
- ok = cberl:prepend(Instance, 0, "testkey", "head"),
- Get2 = cberl:get(Instance, "testkey"),
- [?_assertEqual({ok, 0, "basetail"}, Get1),
- ?_assertEqual({ok, 0, "headbasetail"}, Get2)
+test_append_prepend(_) ->
+ ok = cberl:set(?POOLNAME, "testkey", 0, "base", str),
+ ok = cberl:append(?POOLNAME, 0, "testkey", "tail"),
+ Get1 = cberl:get(?POOLNAME, "testkey"),
+ ok = cberl:prepend(?POOLNAME, 0, "testkey", "head"),
+ Get2 = cberl:get(?POOLNAME, "testkey"),
+ [?_assertEqual({"testkey", 0, "basetail"}, Get1),
+ ?_assertEqual({"testkey", 0, "headbasetail"}, Get2)
].
%%%===================================================================
%%% Helper Functions
Please sign in to comment.
Something went wrong with that request. Please try again.