Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add support for assert_exists

  • Loading branch information...
commit af07e6e953b5d1bcfbf6b98bc33587c946538e41 1 parent 093c961
@blackmath86 blackmath86 authored
View
1  COMPILING
@@ -20,6 +20,7 @@ documentation
executable
ocamlbuild -use-ocamlfind arakoon.native ==> arakoon.native
+(Note: if you have previous 1.x Arakoon then duo to environement possible conflicts, 'ocamlbuild -use-ocamlfind barakoon.native')
libraries
ocamlbuild -use-ocamlfind arakoon_client.cma arakoon_client.cmxa arakoon_client.a ==>
View
5 README
@@ -1,5 +1,6 @@
Arakoon: a simple distributed key/value store
+(Note: if you have previous 1.x Arakoon, then duo to environement possible conflicts, You can replace arakoon with barakoon, e.g ./barakoon.native)
Compiling: see COMPILING
License information:
@@ -30,7 +31,9 @@ create the following configuration:
A sample configuration like this can be found in the cfg dir.
-Just running './arakoon.native --node arakoon_0' starts a 1 node cluster for you to play with.
+You will need to init first starting from Arakoon 2.0:
+'./arakoon.native --init-db arakoon_0' which init node arakoon_0.
+After this, Just running './arakoon.native --node arakoon_0' starts a 1 node cluster for you to play with.
You can get/set values from the command line using :
./arakoon.native --set key value
View
51 pylabs/test/server/quick/system_tests_basic.py
@@ -138,7 +138,56 @@ def test_aSSert_sequences():
v = client.get('test_assert')
assert_equals(v, 'changed', 'second_sequence: %s <> %s' % (v,'changed'))
-
+
+@C.with_custom_setup(C.default_setup, C.basic_teardown)
+def test_aSSert_exists_scenario_1():
+ client = C.get_client(protocol_version = 2)
+ client.set('x_new','x')
+ try:
+ client.aSSert_exists('x_new')
+ except ArakoonException as ex:
+ X.logging.error ( "Bad stuff happened: %s" % ex)
+ assert_equals(True,False)
+
+@C.with_custom_setup(C.default_setup, C.basic_teardown)
+def test_aSSert_exists_scenario_2():
+ client = C.get_client(protocol_version = 2)
+ client.set('x_new2','x')
+ assert_raises( ArakoonAssertionFailed, client.aSSert_exists, 'x')
+
+@C.with_custom_setup(C.default_setup, C.basic_teardown)
+def test_aSSert_exists_scenario_3():
+ client = C.get_client(protocol_version = 2)
+ client.set('x3','x3')
+ ass = arakoon.ArakoonProtocol.Assert_exists('x3')
+ seq = arakoon.ArakoonProtocol.Sequence()
+ seq.addUpdate(ass)
+ client.sequence(seq)
+
+@C.with_custom_setup(C.setup_1_node_forced_master, C.basic_teardown)
+def test_aSSert_exists_sequences():
+ client = C.get_client(protocol_version = 2)
+ client.set ('test_assert_2','test_assert')
+ client.aSSert_exists('test_assert_2')
+ assert_raises(ArakoonAssertionFailed,
+ client.aSSert_exists,
+ 'test_assert_3')
+
+ seq = arakoon.ArakoonProtocol.Sequence()
+ seq.addAssert_exists('test_assert_2')
+ seq.addSet('test_assert_2','changed')
+ client.sequence(seq)
+
+ seq2 = arakoon.ArakoonProtocol.Sequence()
+ seq2.addAssert_exists('test_assert_4')
+ seq2.addSet('test_assert_4','changed2')
+ assert_raises(ArakoonAssertionFailed,
+ client.sequence,
+ seq2)
+ client.set ('test_assert_4','changed3')
+ client.aSSert_exists('test_assert_4')
+ v = client.get('test_assert_4')
+ assert_equals(v, 'changed3', 'third_sequence: %s <> %s' % (v,'changed'))
@C.with_custom_setup( C.default_setup, C.basic_teardown )
def test_prefix ():
View
7 src/client/arakoon_client.mli
@@ -9,6 +9,7 @@ type change =
| Set of key * value
| Delete of key
| Assert of (key * value option)
+ | Assert_exists of (key)
| TestAndSet of key * value option * value option
| Sequence of change list
@@ -65,6 +66,12 @@ method rev_range_entries:
the value associated with the key is not what was expected.
*)
+ method aSSert_exists: ?allow_dirty:bool -> key -> unit Lwt.t
+ (**
+ [aSSert_exists key] throws Arakoon_exc.Exception (E_ASSERTION_FAILED,_) if
+ the value associated with the key is not what was expected.
+ *)
+
method delete: key -> unit Lwt.t
View
4 src/client/arakoon_remote_client.ml
@@ -45,6 +45,10 @@ object(self: #Arakoon_client.client)
request oc (fun buf -> assert_to ~allow_dirty buf key vo) >>= fun () ->
response_old ic nothing
+ method aSSert_exists ?(allow_dirty=false) key =
+ request oc (fun buf -> assert_exists_to ~allow_dirty buf key) >>= fun () ->
+ response_old ic nothing
+
method delete key =
request oc (fun buf -> delete_to buf key) >>= fun () ->
response_limited ic (fun _ -> ())
View
1  src/client/arakoon_remote_client_test.ml
@@ -168,6 +168,7 @@ let _test_delete_non_existing (client:Arakoon_client.client) =
let wrap f = (fun () -> __client_server_wrapper__ _CLUSTER f)
+
let map_wrap = List.map (fun (name, inner) -> name >:: (wrap inner))
let suite = "remote_client" >:::
View
10 src/client/common.ml
@@ -43,6 +43,7 @@ type client_command =
| EXISTS
| GET
| ASSERT
+ | ASSERT_EXISTS
| SET
| DELETE
| RANGE
@@ -109,6 +110,7 @@ let code2int = [
COMPACT , 0x25l;
DELETE_PREFIX , 0x27l;
VERSION , 0x28l;
+ ASSERT_EXISTS , 0x29l;
]
let int2code =
@@ -202,6 +204,11 @@ let assert_to ~allow_dirty out key vo =
Pack.string_to out key;
Pack.string_option_to out vo
+let assert_exists_to ~allow_dirty out key =
+ command_to out ASSERT_EXISTS;
+ Pack.bool_to out allow_dirty;
+ Pack.string_to out key
+
let set_to out key value =
command_to out SET;
Pack.string_to out key;
@@ -368,7 +375,8 @@ let _build_sequence_request output changes =
| Arakoon_client.Set (k,v) -> Core.SET(k,v)
| Arakoon_client.Delete k -> Core.DELETE k
| Arakoon_client.Sequence cs -> Core.SEQUENCE (List.map c2u cs)
- | Arakoon_client.Assert(k,vo) -> Core.ASSERT (k,vo)
+ | Arakoon_client.Assert(k,vo) -> Core.ASSERT (k,vo)
+ | Arakoon_client.Assert_exists(k) -> Core.ASSERT_EXISTS(k)
in
let updates = List.map c2u changes in
let seq = Core.SEQUENCE updates in
View
16 src/client/python/Arakoon.py
@@ -286,6 +286,22 @@ def aSSert(self, key, vo):
return result
@retryDuringMasterReelection
+ def aSSert_exists(self, key):
+ """
+ verifies the value for key exists
+ @type key: string
+ @param key: the key to be verified
+ @rtype: void
+ """
+ msg = ArakoonProtocol.encodeAssert_exists(key, self._allowDirty)
+ if self._allowDirty:
+ conn = self._sendMessage(self._dirtyReadNode, msg)
+ else:
+ conn = self._sendToMaster (msg)
+ result = conn.decodeVoidResult()
+ return result
+
+ @retryDuringMasterReelection
@SignatureValidator( 'sequence' )
def sequence(self, seq, sync = False):
"""
View
6 src/client/python/ArakoonExceptions.py
@@ -75,6 +75,10 @@ class ArakoonAssertionFailed(ArakoonException):
def __init__(self,msg):
ArakoonException.__init__(self,msg)
+class ArakoonAssertExistsFailed(ArakoonException):
+ _msg = "Assert_exists did not yield expected result"
+ def __init__(self,msg):
+ ArakoonException.__init__(self,msg)
class ArakoonSocketException ( ArakoonException ):
pass
@@ -111,4 +115,4 @@ class NurseryRangeError( NurseryException ):
pass
class NurseryInvalidConfig(NurseryException):
- pass
+ pass
View
25 src/client/python/ArakoonProtocol.py
@@ -229,6 +229,8 @@ def dump(src, length=8):
ARA_CMD_REV_RAN_E = 0x00000023 | ARA_CMD_MAG
ARA_CMD_SYNCED_SEQUENCE = 0x00000024 | ARA_CMD_MAG
ARA_CMD_VERSION = 0x00000028 | ARA_CMD_MAG
+ARA_CMD_ASSERT_EXISTS = 0x00000029 | ARA_CMD_MAG
+
# Arakoon error codes
# Success
ARA_ERR_SUCCESS = 0
@@ -241,6 +243,7 @@ def dump(src, length=8):
# wrong cluster
ARA_ERR_WRONG_CLUSTER = 6
ARA_ERR_ASSERTION_FAILED = 7
+ARA_ERR_ASSERT_EXISTS_FAILED = 17
ARA_ERR_RANGE_ERROR = 9
NAMED_FIELD_TYPE_INT = 1
@@ -562,6 +565,15 @@ def write(self, fob):
fob.write(_packString(self._key))
fob.write(_packStringOption(self._vo))
+class Assert_exists(Update):
+ def __init__(self, key):
+ self._key = key
+
+ def write(self, fob):
+ fob.write(_packInt(15))
+ fob.write(_packString(self._key))
+
+
class Sequence(Update):
def __init__(self):
self._updates = []
@@ -580,6 +592,9 @@ def addDelete(self, key):
def addAssert(self, key,vo):
self._updates.append(Assert(key,vo))
+ def addAssert_exists(self, key):
+ self._updates.append(Assert_exists(key))
+
def write(self, fob):
fob.write( _packInt(5))
fob.write( _packInt(len(self._updates)))
@@ -615,6 +630,12 @@ def encodeAssert(key, vo, allowDirty):
msg += _vpackStringOption(vo)
return msg
+ @staticmethod
+ def encodeAssert_exists(key, allowDirty):
+ msg = _packInt(ARA_CMD_ASSERT_EXISTS)
+ msg += _vpackBool(allowDirty)
+ msg += _vpackString(key)
+ return msg
@staticmethod
def encodeGet(key , allowDirty):
@@ -733,7 +754,9 @@ def _evaluateErrorCode(input ):
if errorCode == ARA_ERR_NOT_MASTER:
raise ArakoonNodeNotMaster()
if errorCode == ARA_ERR_ASSERTION_FAILED:
- raise ArakoonAssertionFailed(errorMsg)
+ raise ArakoonAssertionFailed(errorMsg)
+ if errorCode == ARA_ERR_ASSERT_EXISTS_FAILED:
+ raise ArakoonAssertExistsFailed(errorMsg)
if errorCode == ARA_ERR_RANGE_ERROR:
raise NurseryRangeError(errorMsg)
View
10 src/hope/bstore.ml
@@ -188,7 +188,15 @@ module BStore = (struct
in
Lwt.return r'
end
-
+ | Core.ASSERT_EXISTS (k) ->
+ begin
+ BS.get tx (pref_key k) >>= fun r ->
+ let (r':tx_result) = match r with
+ | OK v' -> OK None
+ | NOK k -> NOK (Arakoon_exc.E_ASSERTION_FAILED, k)
+ in
+ Lwt.return r'
+ end
| Core.SEQUENCE s ->
begin
Lwt_list.fold_left_s
View
2  src/hope/bstore_test.ml
@@ -34,7 +34,9 @@ let t_log () =
let u = SET("x","x") in
BStore.log t true u >>= fun _ ->
let u2 = SEQUENCE [ASSERT("x",Some "x")] in
+ let u3 = SEQUENCE [ASSERT_EXISTS("x")] in
BStore.log t true u2 >>= fun _ ->
+ BStore.log t true u3 >>= fun _ ->
Lwt.return ()
in
let main_t () = lwt_wrap setup () test teardown in
View
10 src/hope/core.ml
@@ -19,6 +19,7 @@ type update =
| DELETE of k
| TEST_AND_SET of (k * v option * v option)
| ASSERT of k * v option
+ | ASSERT_EXISTS of k
| ADMIN_SET of k * v option
| USER_FUNCTION of string * string option
| SEQUENCE of update list
@@ -30,6 +31,7 @@ let update2s = function
| DELETE k -> Printf.sprintf "U_DEL (%S)" k
| TEST_AND_SET (k,e,w) -> Printf.sprintf "U_TEST_AND_SET (%S,_,_)" k
| ASSERT (k, _) -> Printf.sprintf "U_ASSERT (%S,_)" k
+ | ASSERT_EXISTS (k) -> Printf.sprintf "U_ASSERT_EXISTS (%S,_)" k
| ADMIN_SET (k, _) -> Printf.sprintf "U_ADMINSET (%S,_)" k
| USER_FUNCTION(n,po) -> Printf.sprintf "U_USER_FUNCTION(%S,_)" n
| SEQUENCE s -> Printf.sprintf "U_SEQ (...)"
@@ -64,8 +66,9 @@ let rec update_to buf = function
| DELETE_PREFIX k ->
Llio.int_to buf 14;
Llio.string_to buf k
-
-
+ | ASSERT_EXISTS (k) ->
+ Llio.int_to buf 15;
+ Llio.string_to buf k
let rec update_from buf off =
let kind, off = Llio.int_from buf off in
@@ -108,6 +111,9 @@ let rec update_from buf off =
| 14 ->
let k, off = Llio.string_from buf off in
DELETE_PREFIX k, off
+ | 15 ->
+ let k, off = Llio.string_from buf off in
+ ASSERT_EXISTS (k), off
| i -> let msg = Printf.sprintf "Unknown update type %d" i in failwith msg
View
1  src/hope/core_test.ml
@@ -13,6 +13,7 @@ let update_serialization () =
SET("key_set", "value_set");
DELETE "key_delete";
ASSERT ("key_assert", None);
+ ASSERT_EXISTS ("key_assert_exists");
ADMIN_SET ("key_admin", Some "admin_value");
SEQUENCE [SET ("k0","v0)");
SET ("k1","v1");
View
15 src/hope/v1.ml
@@ -260,6 +260,20 @@ module V1(S:Core.STORE)(A:MP_ACTION_DISPATCHER) = struct
in
_only_if_master (ic,oc) me store allow_dirty _inner
+ let _do_assert_exists (ic,oc) me store stats =
+ Llio.input_bool ic >>= fun allow_dirty ->
+ Llio.input_string ic >>= fun key ->
+ let _inner () =
+ S.get store key >>= fun m_val ->
+ begin
+ if m_val = None
+ then _non_fatal oc Arakoon_exc.E_ASSERTION_FAILED key
+ else V.response_ok_unit oc
+ end
+ in
+ _only_if_master (ic,oc) me store allow_dirty _inner
+
+
let _do_sequence (ic,oc) me store stats driver =
Llio.input_string ic >>= fun data ->
let _inner () =
@@ -339,6 +353,7 @@ module V1(S:Core.STORE)(A:MP_ACTION_DISPATCHER) = struct
| Common.STATISTICS -> _do_statistics conn stats
| Common.USER_FUNCTION -> fail ()
| Common.ASSERT -> _do_assert conn me store stats
+ | Common.ASSERT_EXISTS -> _do_assert_exists conn me store stats
| Common.SET_INTERVAL -> fail ()
| Common.DELETE_PREFIX -> _do_delete_prefix conn me store stats driver
| Common.VERSION -> _do_version conn
View
16 src/hope/v2.ml
@@ -469,6 +469,22 @@ let _set driver k v =
in
_only_if_master rest oc me store allow_dirty inner
end
+ | Common.ASSERT_EXISTS ->
+ begin
+ let allow_dirty = Pack.input_bool rest in
+ let key = Pack.input_string rest in
+ Lwtc.log "ASSERT_EXISTS: allow_dirty:%b key:%s" allow_dirty key
+ >>= fun () ->
+ let inner () =
+ S.get store key >>= fun m_val ->
+ if m_val = None
+ then
+ _output_simple_error oc Arakoon_exc.E_ASSERTION_FAILED key
+ else
+ _output_ok_unit oc
+ in
+ _only_if_master rest oc me store allow_dirty inner
+ end
| Common.CONFIRM ->
begin
let key = Pack.input_string rest in
View
53 src/system/single.ml
@@ -304,6 +304,51 @@ let _assert3 (client:client) =
OUnit.assert_equal v2 "REALLY";
Lwt.return ()
+let _assert_exists1 (client: client) =
+ Lwt_log.info "_assert_exists1" >>= fun () ->
+ client # set "my_value_exists" "my_value_exists" >>= fun () ->
+ client # aSSert_exists "my_value_exists" >>= fun () ->
+ Lwt.return ()
+
+let _assert_exists2 (client: client) =
+ Lwt_log.info "_assert_exists2" >>= fun () ->
+ client # set "x_exists" "x_exists" >>= fun () ->
+ should_fail
+ (fun () -> client # aSSert_exists "x_no_exists")
+ "PROBLEM:_assert_exists2: yielded unit"
+ "_assert_exists2: ok, this aSSert should indeed fail"
+
+let _assert_exists3 (client:client) =
+ Lwt_log.info "_assert_exists3" >>= fun () ->
+ let k = "_assert_exists3" in
+ client # set k k >>= fun () ->
+ Lwt_log.info "_assert_exists3: value set" >>= fun () ->
+ let updates = [
+ Arakoon_client.Assert_exists(k);
+ Arakoon_client.Set(k, "REALLY")
+ ]
+ in
+ client # sequence updates >>= fun () ->
+ client # get k >>= fun v2 ->
+ OUnit.assert_equal v2 "REALLY";
+ Lwt.catch
+ (fun () ->
+ client # sequence updates >>= fun () ->
+ let u2 = [
+ Arakoon_client.Assert_exists(k);
+ Arakoon_client.Set(k,"NO WAY")
+ ]
+ in
+ client # sequence u2)
+ (function
+ | Arakoon_exc.Exception(Arakoon_exc.E_ASSERTION_FAILED, msg) -> Lwt.return ()
+ | ex -> Lwt.fail ex
+ )
+ >>= fun () ->
+ client # get k >>= fun v3 ->
+ OUnit.assert_equal v2 "REALLY";
+ Lwt.return ()
+
let _range_1 (client: client) =
Lwt_log.info_f "_range_1" >>= fun () ->
@@ -499,6 +544,11 @@ let assert2 tpl = _with_master tpl _assert2
let assert3 tpl = _with_master tpl _assert3
+let assert_exists1 tpl = _with_master tpl _assert_exists1
+
+let assert_exists2 tpl = _with_master tpl _assert_exists2
+
+let assert_exists3 tpl = _with_master tpl _assert_exists3
let setup master base () =
let lease_period = 10 in
@@ -525,6 +575,9 @@ let make_suite base name w =
"assert1" >:: w (base + 800) assert1;
"assert2" >:: w (base + 900) assert2;
"assert3" >:: w (base + 1000) assert3;
+ "assert_exists1" >:: w (base + 800) assert_exists1;
+ "assert_exists2" >:: w (base + 900) assert_exists2;
+ "assert_exists3" >:: w (base + 1000) assert_exists3;
]
let force_master =
Please sign in to comment.
Something went wrong with that request. Please try again.