Skip to content

Commit

Permalink
api: add zooGetAcl
Browse files Browse the repository at this point in the history
  • Loading branch information
4eUeP committed Mar 30, 2021
1 parent 22f17dd commit 5d514a8
Show file tree
Hide file tree
Showing 7 changed files with 269 additions and 67 deletions.
46 changes: 44 additions & 2 deletions cbits/hs_zk.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,41 @@ void hs_strings_stat_completion_fn(int rc, const string_vector_t* strings,
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,
Expand All @@ -220,6 +255,8 @@ zhandle_t* hs_zookeeper_init(HsStablePtr mvar, HsInt cap,
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,
Expand Down Expand Up @@ -326,6 +363,13 @@ int hs_zoo_awget_children2(zhandle_t* zh, const char* path, HsStablePtr mvar_w,
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) {
Expand All @@ -348,5 +392,3 @@ void hs_zoo_set_op_init(zoo_op_t* op, const char* path, const char* value,
stat_t* stat) {
zoo_set_op_init(op, path, value + valoffset, valuelen, version, stat);
}

// ----------------------------------------------------------------------------
39 changes: 38 additions & 1 deletion include/hs_zk.h
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -17,9 +19,13 @@ const stat_t* dup_stat(const stat_t* old_stat) {
}

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]);
Expand All @@ -29,6 +35,26 @@ const string_vector_t* dup_string_vector(const string_vector_t* old_strings) {
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;
Expand Down Expand Up @@ -82,13 +108,24 @@ typedef struct hs_strings_stat_completion_t {
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,
int mode, HsStablePtr mvar, HsInt cap,
Expand Down
87 changes: 57 additions & 30 deletions src/ZooKeeper.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@ module ZooKeeper
, Res.withResource
, Res.Resource

, zooGetClientID
, zooState
, zooRecvTimeout

, isUnrecoverable

, zooCreate
, zooSet
, zooGet
Expand All @@ -23,13 +17,19 @@ module ZooKeeper
, zooDelete
, zooExists
, zooWatchExists
, zooGetAcl

, zooMulti
, zooCreateOpInit
, zooDeleteOpInit
, zooSetOpInit
, zooCheckOpInit

, zooClientID
, zooState
, zooRecvTimeout
, isUnrecoverable

, zookeeperInit
, zookeeperClose
) where
Expand Down Expand Up @@ -82,16 +82,6 @@ zookeeperResInit
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
Expand Down Expand Up @@ -472,22 +462,32 @@ zooWatchGetChildren2 zh path watchfn strsStatfn =
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.
Expand Down Expand Up @@ -676,3 +676,30 @@ zookeeperInit host timeout mclientid flags = do
{-# 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
6 changes: 6 additions & 0 deletions src/ZooKeeper/Internal/FFI.hsc
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ foreign import ccall unsafe "hs_zk.h zoo_state"
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
Expand Down
Loading

0 comments on commit 5d514a8

Please sign in to comment.