packages feed

zoovisitor 0.1.1.0 → 0.1.1.1

raw patch · 8 files changed

+271/−69 lines, 8 filesdep ~Z-IOPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: Z-IO

API changes (from Hackage documentation)

- ZooKeeper: zooGetClientID :: ZHandle -> IO ClientID
+ ZooKeeper: zooClientID :: ZHandle -> IO ClientID
+ ZooKeeper: zooGetAcl :: HasCallStack => ZHandle -> CBytes -> IO AclCompletion
+ ZooKeeper.Types: AclCompletion :: [ZooAcl] -> Stat -> AclCompletion
+ ZooKeeper.Types: ZooAcl :: [ZooPerm] -> CBytes -> CBytes -> ZooAcl
+ ZooKeeper.Types: [aclCompletionAcls] :: AclCompletion -> [ZooAcl]
+ ZooKeeper.Types: [aclCompletionStat] :: AclCompletion -> Stat
+ ZooKeeper.Types: [aclIdScheme] :: ZooAcl -> CBytes
+ ZooKeeper.Types: [aclId] :: ZooAcl -> CBytes
+ ZooKeeper.Types: [aclPerms] :: ZooAcl -> [ZooPerm]
+ ZooKeeper.Types: compactZooPerms :: [ZooPerm] -> ZooPerm
+ ZooKeeper.Types: data AclCompletion
+ ZooKeeper.Types: data ZooAcl
+ ZooKeeper.Types: data ZooPerm
+ ZooKeeper.Types: pattern ZooPermAdmin :: ZooPerm
+ ZooKeeper.Types: pattern ZooPermAll :: ZooPerm
+ ZooKeeper.Types: pattern ZooPermCreate :: ZooPerm
+ ZooKeeper.Types: pattern ZooPermDelete :: ZooPerm
+ ZooKeeper.Types: pattern ZooPermRead :: ZooPerm
+ ZooKeeper.Types: pattern ZooPermWrite :: ZooPerm
- ZooKeeper.Types: Stat :: Int64 -> Int64 -> Int64 -> Int64 -> Int32 -> Int32 -> Int32 -> Int64 -> Int32 -> Int32 -> Int64 -> Stat
+ ZooKeeper.Types: Stat :: {-# UNPACK #-} !Int64 -> {-# UNPACK #-} !Int64 -> {-# UNPACK #-} !Int64 -> {-# UNPACK #-} !Int64 -> {-# UNPACK #-} !Int32 -> {-# UNPACK #-} !Int32 -> {-# UNPACK #-} !Int32 -> {-# UNPACK #-} !Int64 -> {-# UNPACK #-} !Int32 -> {-# UNPACK #-} !Int32 -> {-# UNPACK #-} !Int64 -> Stat
- ZooKeeper.Types: [statAversion] :: Stat -> Int32
+ ZooKeeper.Types: [statAversion] :: Stat -> {-# UNPACK #-} !Int32
- ZooKeeper.Types: [statCtime] :: Stat -> Int64
+ ZooKeeper.Types: [statCtime] :: Stat -> {-# UNPACK #-} !Int64
- ZooKeeper.Types: [statCversion] :: Stat -> Int32
+ ZooKeeper.Types: [statCversion] :: Stat -> {-# UNPACK #-} !Int32
- ZooKeeper.Types: [statCzxid] :: Stat -> Int64
+ ZooKeeper.Types: [statCzxid] :: Stat -> {-# UNPACK #-} !Int64
- ZooKeeper.Types: [statDataLength] :: Stat -> Int32
+ ZooKeeper.Types: [statDataLength] :: Stat -> {-# UNPACK #-} !Int32
- ZooKeeper.Types: [statEphemeralOwner] :: Stat -> Int64
+ ZooKeeper.Types: [statEphemeralOwner] :: Stat -> {-# UNPACK #-} !Int64
- ZooKeeper.Types: [statMtime] :: Stat -> Int64
+ ZooKeeper.Types: [statMtime] :: Stat -> {-# UNPACK #-} !Int64
- ZooKeeper.Types: [statMzxid] :: Stat -> Int64
+ ZooKeeper.Types: [statMzxid] :: Stat -> {-# UNPACK #-} !Int64
- ZooKeeper.Types: [statNumChildren] :: Stat -> Int32
+ ZooKeeper.Types: [statNumChildren] :: Stat -> {-# UNPACK #-} !Int32
- ZooKeeper.Types: [statPzxid] :: Stat -> Int64
+ ZooKeeper.Types: [statPzxid] :: Stat -> {-# UNPACK #-} !Int64
- ZooKeeper.Types: [statVersion] :: Stat -> Int32
+ ZooKeeper.Types: [statVersion] :: Stat -> {-# UNPACK #-} !Int32

Files

cbits/hs_zk.c view
@@ -207,6 +207,41 @@   hs_thread_done(); } +/**+ * \brief signature of a completion function that returns an ACL.+ *+ * This method will be invoked at the end of a asynchronous call and also as+ * a result of connection loss or timeout.+ * \param rc the error code of the call. Connection loss/timeout triggers+ * the completion with one of the following error codes:+ * ZCONNECTIONLOSS -- lost connection to the server+ * ZOPERATIONTIMEOUT -- connection timed out+ * Data related events trigger the completion with error codes listed the+ * Exceptions section of the documentation of the function that initiated the+ * call. (Zero indicates call was successful.)+ * \param acl a pointer to the structure containng the ACL of a node. If a non+ *   zero error code is returned, the content of strings is undefined. The+ *   programmer is NOT responsible for freeing acl.+ * \param stat a pointer to the stat information for the node involved in+ *   this function. If a non zero error code is returned, the content of+ *   stat is undefined. The programmer is NOT responsible for freeing stat.+ * \param data the pointer that was passed by the caller when the function+ *   that this completion corresponds to was invoked. The programmer+ *   is responsible for any memory freeing associated with the data+ *   pointer.+ */+void hs_acl_completion_fn(int rc, struct ACL_vector* acl, struct Stat* stat,+                          const void* data) {+  hs_acl_completion_t* acl_completion = (hs_acl_completion_t*)data;+  acl_completion->rc = rc;+  if (!rc) {+    acl_completion->acl = dup_acl_vector(acl);+    acl_completion->stat = dup_stat(stat);+  }+  hs_try_putmvar(acl_completion->cap, acl_completion->mvar);+  hs_thread_done();+}+ // ----------------------------------------------------------------------------  zhandle_t* hs_zookeeper_init(HsStablePtr mvar, HsInt cap,@@ -220,6 +255,8 @@   return zh; } +// ----------------------------------------------------------------------------+ int hs_zoo_acreate(zhandle_t* zh, const char* path, const char* value,                    HsInt offset, HsInt valuelen, const struct ACL_vector* acl,                    int mode, HsStablePtr mvar, HsInt cap,@@ -326,6 +363,13 @@                              hs_strings_stat_completion_fn, strings_stat); } +int hs_zoo_aget_acl(zhandle_t* zh, const char* path, HsStablePtr mvar,+                    HsInt cap, hs_acl_completion_t* completion) {+  completion->mvar = mvar;+  completion->cap = cap;+  return zoo_aget_acl(zh, path, hs_acl_completion_fn, completion);+}+ int hs_zoo_amulti(zhandle_t* zh, int count, const zoo_op_t* ops,                   zoo_op_result_t* results, HsStablePtr mvar, HsInt cap,                   hs_void_completion_t* void_completion) {@@ -348,5 +392,3 @@                         stat_t* stat) {   zoo_set_op_init(op, path, value + valoffset, valuelen, version, stat); }--// ----------------------------------------------------------------------------
include/hs_zk.h view
@@ -9,6 +9,8 @@  typedef struct Stat stat_t; typedef struct String_vector string_vector_t;+typedef struct ACL acl_t;+typedef struct ACL_vector acl_vector_t;  const stat_t* dup_stat(const stat_t* old_stat) {   stat_t* new_stat = (stat_t*)malloc(sizeof(stat_t));@@ -17,9 +19,13 @@ }  const string_vector_t* dup_string_vector(const string_vector_t* old_strings) {+  int count = old_strings->count;+  if (count < 0) {+    fprintf(stderr, "dup_string_vector error: count %d\n", count);+    return NULL;+  }   string_vector_t* new_strings =       (string_vector_t*)malloc(sizeof(string_vector_t));-  int count = old_strings->count;   char** vals = malloc(count * sizeof(char*));   for (int i = 0; i < count; ++i) {     vals[i] = strdup(old_strings->data[i]);@@ -29,6 +35,26 @@   return new_strings; } +const acl_vector_t* dup_acl_vector(const acl_vector_t* old_acls) {+  int count = old_acls->count;+  if (count < 0) {+    fprintf(stderr, "dup_acl_vector error: count %d\n", count);+    return NULL;+  }+  acl_t* data = (acl_t*)malloc(count * sizeof(acl_t));+  acl_t* old_data = old_acls->data;+  for (int i = 0; i < count; ++i) {+    data[i].perms = old_data[i].perms;+    data[i].id.scheme = strdup(old_data[i].id.scheme);+    data[i].id.id = strdup(old_data[i].id.id);+  }++  acl_vector_t* new_acls = (acl_vector_t*)malloc(sizeof(acl_vector_t));+  new_acls->count = count;+  new_acls->data = data;+  return new_acls;+}+ typedef struct hs_watcher_ctx_t {   HsStablePtr mvar;   HsInt cap;@@ -82,12 +108,23 @@   const stat_t* stat; } hs_strings_stat_completion_t; +typedef struct hs_acl_completion_t {+  HsStablePtr mvar;+  HsInt cap;+  int rc;+  const struct ACL_vector* acl;+  const struct Stat* stat;+} hs_acl_completion_t;+ // ----------------------------------------------------------------------------  zhandle_t* hs_zookeeper_init(HsStablePtr mvar, HsInt cap,                              hs_watcher_ctx_t* watcher_ctx, const char* host,                              int recv_timeout, const clientid_t* clientid,                              int flags);++int hs_zoo_aget_acl(zhandle_t* zh, const char* path, HsStablePtr mvar,+                    HsInt cap, hs_acl_completion_t* completion);  int hs_zoo_acreate(zhandle_t* zh, const char* path, const char* value,                    HsInt offset, HsInt valuelen, const struct ACL_vector* acl,
src/ZooKeeper.hs view
@@ -6,12 +6,6 @@   , Res.withResource   , Res.Resource -  , zooGetClientID-  , zooState-  , zooRecvTimeout--  , isUnrecoverable-   , zooCreate   , zooSet   , zooGet@@ -23,6 +17,7 @@   , zooDelete   , zooExists   , zooWatchExists+  , zooGetAcl    , zooMulti   , zooCreateOpInit@@ -30,6 +25,11 @@   , zooSetOpInit   , zooCheckOpInit +  , zooClientID+  , zooState+  , zooRecvTimeout+  , isUnrecoverable+   , zookeeperInit   , zookeeperClose   ) where@@ -82,16 +82,6 @@ zookeeperResInit host timeout mclientid flags =   Res.initResource (zookeeperInit host timeout mclientid flags) zookeeperClose --- | Checks if the current zookeeper connection state can't be recovered.------ If True, the application must close the zhandle and then try to reconnect.-isUnrecoverable-  :: T.ZHandle-  -- ^ The zookeeper handle obtained by a call to 'zookeeperResInit'-  -> IO Bool-  -- ^ Return True if connection is unrecoverable-isUnrecoverable zh = (< 0) <$> I.c_is_unrecoverable zh- -- | Create a node. -- -- This method will create a node in ZooKeeper. A node can only be created if@@ -472,22 +462,32 @@           csize I.peekRet I.peekData stringsfn'           (I.c_hs_zoo_awget_children2 zh path') --- | Return the client session id, only valid if the connections--- is currently connected (ie. last watcher state is 'T.ZooConnectedState')-zooGetClientID :: T.ZHandle -> IO T.ClientID-zooGetClientID = I.c_zoo_client_id---- | Get the state of the zookeeper connection+-- | Gets the acl associated with a node. ----- The return valud will be one of the State Consts-zooState :: T.ZHandle  -> IO T.ZooState-zooState = I.c_zoo_state+-- Throw one of the following exceptions on failure:+--+-- ZBADARGUMENTS - invalid input parameters+-- ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE+-- ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory+zooGetAcl+  :: HasCallStack+  => T.ZHandle+  -- ^ The zookeeper handle obtained by a call to 'zookeeperResInit'+  -> CBytes+  -- ^ The name of the node. Expressed as a file name with slashes+  -- separating ancestors of the node.+  -> IO T.AclCompletion+  -- ^ The result when the request completes.+  --+  -- Throw one of the following exceptions if the request completes failed:+  --+  -- * ZNONODE the node does not exist.+  -- * ZNOAUTH the client does not have permission.+zooGetAcl zh path = CBytes.withCBytesUnsafe path $ \path' -> do+  let csize = I.csize @T.AclCompletion+      cfunc = I.c_hs_zoo_aget_acl zh path'+   in E.throwZooErrorIfLeft =<< I.withZKAsync csize I.peekRet I.peekData cfunc --- | Return the timeout for this session, only valid if the connections--- is currently connected (ie. last watcher state is ZOO_CONNECTED_STATE). This--- value may change after a server re-connect.-zooRecvTimeout :: T.ZHandle  -> IO CInt-zooRecvTimeout = I.c_zoo_recv_timeout -------------------------------------------------------------------------------  -- | Atomically commits multiple zookeeper operations.@@ -676,3 +676,30 @@ {-# INLINABLE zookeeperClose #-} zookeeperClose :: T.ZHandle -> IO () zookeeperClose = void . E.throwZooErrorIfNotOK <=< I.c_zookeeper_close_safe++-- | Return the client session id, only valid if the connections+-- is currently connected (ie. last watcher state is 'T.ZooConnectedState')+zooClientID :: T.ZHandle -> IO T.ClientID+zooClientID = I.c_zoo_client_id++-- | Checks if the current zookeeper connection state can't be recovered.+--+-- If True, the application must close the zhandle and then try to reconnect.+isUnrecoverable+  :: T.ZHandle+  -- ^ The zookeeper handle obtained by a call to 'zookeeperResInit'+  -> IO Bool+  -- ^ Return True if connection is unrecoverable+isUnrecoverable zh = (< 0) <$> I.c_is_unrecoverable zh++-- | Get the state of the zookeeper connection+--+-- The return valud will be one of the State Consts+zooState :: T.ZHandle -> IO T.ZooState+zooState = I.c_zoo_state++-- | Return the timeout for this session, only valid if the connections+-- is currently connected (ie. last watcher state is ZOO_CONNECTED_STATE). This+-- value may change after a server re-connect.+zooRecvTimeout :: T.ZHandle -> IO CInt+zooRecvTimeout = I.c_zoo_recv_timeout
src/ZooKeeper/Internal/FFI.hsc view
@@ -65,6 +65,12 @@ foreign import ccall unsafe "hs_zk.h zoo_recv_timeout"   c_zoo_recv_timeout :: ZHandle -> IO CInt +foreign import ccall unsafe "hs_zk.h hs_zoo_aget_acl"+  c_hs_zoo_aget_acl+    :: ZHandle -> BA## Word8+    -> StablePtr PrimMVar -> Int -> Ptr AclCompletion+    -> IO CInt+ foreign import ccall unsafe "hs_zk.h hs_zoo_acreate"   c_hs_zoo_acreate     :: ZHandle
src/ZooKeeper/Internal/Types.hsc view
@@ -44,8 +44,8 @@ -------------------------------------------------------------------------------  -- | ACL permissions.-newtype ZooPerm = ZooPerm { unAcl :: CInt }-  deriving Eq+newtype ZooPerm = ZooPerm { unZooPerm :: CInt }+  deriving (Eq, Bits)  instance Show ZooPerm where   show ZooPermRead   = "ZooPermRead"@@ -56,25 +56,60 @@   show ZooPermAll    = "ZooPermAll"   show (ZooPerm x)   = "ZooPerm: 0x" ++ showHex x "" -pattern ZooPermRead :: ZooPerm-pattern ZooPermRead = ZooPerm (#const ZOO_PERM_READ)--pattern ZooPermWrite :: ZooPerm-pattern ZooPermWrite = ZooPerm (#const ZOO_PERM_WRITE)--pattern ZooPermCreate :: ZooPerm+pattern ZooPermRead, ZooPermWrite, ZooPermCreate, ZooPermDelete, ZooPermAdmin :: ZooPerm+pattern ZooPermRead   = ZooPerm (#const ZOO_PERM_READ)+pattern ZooPermWrite  = ZooPerm (#const ZOO_PERM_WRITE) pattern ZooPermCreate = ZooPerm (#const ZOO_PERM_CREATE)--pattern ZooPermDelete :: ZooPerm pattern ZooPermDelete = ZooPerm (#const ZOO_PERM_DELETE)--pattern ZooPermAdmin :: ZooPerm-pattern ZooPermAdmin = ZooPerm (#const ZOO_PERM_ADMIN)+pattern ZooPermAdmin  = ZooPerm (#const ZOO_PERM_ADMIN)  pattern ZooPermAll :: ZooPerm pattern ZooPermAll = ZooPerm (#const ZOO_PERM_ALL) -newtype AclVector = AclVector { unAclVector :: Ptr () }+{-# INLINE toZooPerms #-}+toZooPerms :: CInt -> [ZooPerm]+toZooPerms n = go allPerms+  where+    go [] = []+    go (x:xs)+      | ZooPerm n .&. x == x = x : (go $! xs)+      | otherwise            = go $! xs+    allPerms = [ZooPermRead, ZooPermWrite, ZooPermCreate, ZooPermDelete, ZooPermAdmin]++{-# INLINE fromZooPerms #-}+fromZooPerms :: [ZooPerm] -> CInt+fromZooPerms = foldr (.|.) 0 . map unZooPerm++{-# INLINE compactZooPerms #-}+compactZooPerms :: [ZooPerm] -> ZooPerm+compactZooPerms = ZooPerm . fromZooPerms++data ZooAcl = ZooAcl+  { aclPerms    :: [ZooPerm]+  , aclIdScheme :: CBytes+  , aclId       :: CBytes+  } deriving Show++{-# INLINE sizeOfZooAcl #-}+sizeOfZooAcl :: Int+sizeOfZooAcl = (#size acl_t)++peekZooAcl :: Ptr ZooAcl -> IO ZooAcl+peekZooAcl ptr = do+  perms <- toZooPerms <$> (#peek acl_t, perms) ptr+  scheme_ptr <- (#peek acl_t, id.scheme) ptr+  id_ptr <- (#peek acl_t, id.id) ptr+  scheme <- CBytes.fromCString scheme_ptr <* free scheme_ptr+  acl_id <- CBytes.fromCString id_ptr <* free id_ptr+  return $ ZooAcl perms scheme acl_id++-- TODO+unsafeAllocaZooAcl :: ZooAcl -> IO Z.ByteArray+unsafeAllocaZooAcl = undefined++-- FIXME: consider this+-- data AclVector = AclVector (Ptr ()) | AclList [ZooAcl]+newtype AclVector = AclVector (Ptr ())   deriving (Show, Eq)  -- | This is a completely open ACL@@ -89,6 +124,18 @@ foreign import ccall unsafe "hs_zk.h &ZOO_CREATOR_ALL_ACL"   zooCreatorAllAcl :: AclVector +toAclList :: AclVector -> IO [ZooAcl]+toAclList (AclVector ptr) = do+  count <- fromIntegral @Int32 <$> (#peek acl_vector_t, count) ptr+  data_ptr <- (#peek acl_vector_t, data) ptr+  forM [0..count-1] $ \idx -> do+    let data_ptr' = data_ptr `plusPtr` (idx * sizeOfZooAcl)+    peekZooAcl data_ptr'++-- TODO+fromAclList :: [ZooAcl] -> IO AclVector+fromAclList = undefined+ -------------------------------------------------------------------------------  -- | Interest Consts@@ -240,17 +287,17 @@ --pattern ZooPersistentSequentialWithTTL = CreateMode (#const ZOO_PERSISTENT_SEQUENTIAL_WITH_TTL)  data Stat = Stat-  { statCzxid          :: Int64-  , statMzxid          :: Int64-  , statCtime          :: Int64-  , statMtime          :: Int64-  , statVersion        :: Int32-  , statCversion       :: Int32-  , statAversion       :: Int32-  , statEphemeralOwner :: Int64-  , statDataLength     :: Int32-  , statNumChildren    :: Int32-  , statPzxid          :: Int64+  { statCzxid          :: {-# UNPACK #-} !Int64+  , statMzxid          :: {-# UNPACK #-} !Int64+  , statCtime          :: {-# UNPACK #-} !Int64+  , statMtime          :: {-# UNPACK #-} !Int64+  , statVersion        :: {-# UNPACK #-} !Int32+  , statCversion       :: {-# UNPACK #-} !Int32+  , statAversion       :: {-# UNPACK #-} !Int32+  , statEphemeralOwner :: {-# UNPACK #-} !Int64+  , statDataLength     :: {-# UNPACK #-} !Int32+  , statNumChildren    :: {-# UNPACK #-} !Int32+  , statPzxid          :: {-# UNPACK #-} !Int64   } deriving (Show, Eq)  statSize :: Int@@ -391,6 +438,20 @@     stat_ptr <- (#peek hs_strings_stat_completion_t, stat) ptr     stat <- peekStat stat_ptr     return $ StringsStatCompletion vals stat++data AclCompletion = AclCompletion+  { aclCompletionAcls :: [ZooAcl]+  , aclCompletionStat :: Stat+  } deriving Show++instance Completion AclCompletion where+  csize = (#size hs_acl_completion_t)+  peekRet ptr = (#peek hs_acl_completion_t, rc) ptr+  peekData ptr = do+    acls <- toAclList . AclVector =<< (#peek hs_acl_completion_t, acl) ptr+    stat_ptr <- (#peek hs_acl_completion_t, stat) ptr+    stat <- peekStat stat_ptr+    return $ AclCompletion acls stat  ------------------------------------------------------------------------------- 
src/ZooKeeper/Types.hs view
@@ -9,6 +9,7 @@   , I.zooOpenAclUnsafe   , I.zooReadAclUnsafe   , I.zooCreatorAllAcl+  , I.ZooAcl (..)    , I.HsWatcherCtx (..) @@ -18,6 +19,7 @@   , I.StringCompletion (..)   , I.StringsCompletion (..)   , I.StringsStatCompletion (..)+  , I.AclCompletion (..)    , I.Stat (..) @@ -46,6 +48,15 @@   , pattern I.ZooLogWarn   , pattern I.ZooLogInfo   , pattern I.ZooLogDebug++  , I.ZooPerm+  , pattern I.ZooPermRead+  , pattern I.ZooPermWrite+  , pattern I.ZooPermCreate+  , pattern I.ZooPermDelete+  , pattern I.ZooPermAdmin+  , pattern I.ZooPermAll+  , I.compactZooPerms    , I.StringVector (..)   ) where
test/Spec.hs view
@@ -5,21 +5,26 @@ import           Control.Concurrent import           Control.Monad       (void) import           Data.Version        (makeVersion)+import           Foreign.C import           Test.Hspec import           ZooKeeper import           ZooKeeper.Exception import           ZooKeeper.Types +recvTimeout :: CInt+recvTimeout = 5000+ client :: Resource ZHandle-client = zookeeperResInit "127.0.0.1:2182" 5000 Nothing 0+client = zookeeperResInit "127.0.0.1:2182" recvTimeout Nothing 0  main :: IO () main = withResource client $ \zh -> do-  hspec $ smoke zh-  hspec $ multiSpec zh+  hspec $ opSpec zh+  hspec $ multiOpSpec zh+  hspec $ propSpec zh -smoke :: ZHandle -> Spec-smoke zh = do+opSpec :: ZHandle -> Spec+opSpec zh = do   describe "ZooKeeper.zooVersion" $ do     it "version should be 3.4.* - 3.6.*" $ do       zooVersion `shouldSatisfy` (>= makeVersion [3, 4, 0])@@ -70,16 +75,29 @@       unStrVec . strsCompletionValues <$> zooGetChildren zh "/y" `shouldReturn` []       zooDelete zh "/y" Nothing `shouldReturn` () +  describe "ZooKeeper.zooGetAcl" $ do+    it "get acl of READ permission" $ do+      void $ zooCreate zh "/acl1" Nothing zooReadAclUnsafe ZooEphemeral+      compactZooPerms . aclPerms . head . aclCompletionAcls <$> zooGetAcl zh "/acl1"+        `shouldReturn` ZooPermRead++    it "get acl of ALL permission" $ do+      void $ zooCreate zh "/acl2" Nothing zooOpenAclUnsafe ZooEphemeral+      compactZooPerms . aclPerms . head . aclCompletionAcls <$> zooGetAcl zh "/acl2"+        `shouldReturn` ZooPermAll++propSpec :: ZHandle -> Spec+propSpec zh = do   describe "ZooKeeper.zooState" $ do     it "test get state" $ do       zooState zh `shouldReturn` ZooConnectedState    describe "ZooKeeper.zooRecvTimeout" $ do     it "test receive timeout" $ do-      zooRecvTimeout zh `shouldReturn` 5000+      zooRecvTimeout zh `shouldReturn` recvTimeout -multiSpec :: ZHandle -> Spec-multiSpec zh = describe "ZooKeeper.zooMulti" $ do+multiOpSpec :: ZHandle -> Spec+multiOpSpec zh = describe "ZooKeeper.zooMulti" $ do   it "Test basic multi-op functionality" $ do     let op0 = zooCreateOpInit "/multi" (Just "") 64 zooOpenAclUnsafe ZooPersistent     let op1 = zooCreateOpInit "/multi/a" (Just "") 64 zooOpenAclUnsafe ZooPersistent
zoovisitor.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.2 name:               zoovisitor-version:            0.1.1.0+version:            0.1.1.1 synopsis:   A haskell binding to Apache Zookeeper C library(mt) using Haskell Z project. @@ -41,7 +41,7 @@   build-depends:     , base    >=4.12  && <5     , Z-Data  >=0.7.2 && <1.0-    , Z-IO    ^>=0.7+    , Z-IO    >=0.7   && <1.0    includes:           hs_zk.h   c-sources:          cbits/hs_zk.c