summaryrefslogtreecommitdiffstats
path: root/ctdb/client/client_event.c
diff options
context:
space:
mode:
Diffstat (limited to 'ctdb/client/client_event.c')
-rw-r--r--ctdb/client/client_event.c444
1 files changed, 444 insertions, 0 deletions
diff --git a/ctdb/client/client_event.c b/ctdb/client/client_event.c
new file mode 100644
index 0000000..7111fe7
--- /dev/null
+++ b/ctdb/client/client_event.c
@@ -0,0 +1,444 @@
+/*
+ Eventd client api
+
+ Copyright (C) Amitay Isaacs 2016
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/network.h"
+
+#include <talloc.h>
+#include <tevent.h>
+
+#include "lib/util/debug.h"
+#include "lib/util/tevent_unix.h"
+
+#include "common/logging.h"
+#include "common/sock_client.h"
+
+#include "protocol/protocol_api.h"
+
+#include "client/client_event.h"
+
+struct ctdb_event_context {
+ struct sock_client_context *sockc;
+};
+
+static int ctdb_event_msg_request_push(void *request_data, uint32_t reqid,
+ TALLOC_CTX *mem_ctx,
+ uint8_t **buf, size_t *buflen,
+ void *private_data)
+{
+ struct ctdb_event_request *request =
+ (struct ctdb_event_request *)request_data;
+ int ret;
+
+ sock_packet_header_set_reqid(&request->header, reqid);
+
+ *buflen = ctdb_event_request_len(request);
+ *buf = talloc_size(mem_ctx, *buflen);
+ if (*buf == NULL) {
+ return ENOMEM;
+ }
+
+ ret = ctdb_event_request_push(request, *buf, buflen);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ctdb_event_msg_reply_pull(uint8_t *buf, size_t buflen,
+ TALLOC_CTX *mem_ctx, void **reply_data,
+ void *private_data)
+{
+ struct ctdb_event_reply *reply;
+ int ret;
+
+ reply = talloc_zero(mem_ctx, struct ctdb_event_reply);
+ if (reply == NULL) {
+ return ENOMEM;
+ }
+
+ ret = ctdb_event_reply_pull(buf, buflen, reply, reply);
+ if (ret != 0) {
+ talloc_free(reply);
+ return ret;
+ }
+
+ *reply_data = reply;
+ return 0;
+}
+
+static int ctdb_event_msg_reply_reqid(uint8_t *buf, size_t buflen,
+ uint32_t *reqid, void *private_data)
+{
+ struct sock_packet_header header;
+ size_t np;
+ int ret;
+
+ ret = sock_packet_header_pull(buf, buflen, &header, &np);
+ if (ret != 0) {
+ return ret;
+ }
+
+ *reqid = header.reqid;
+ return 0;
+}
+
+struct sock_client_proto_funcs event_proto_funcs = {
+ .request_push = ctdb_event_msg_request_push,
+ .reply_pull = ctdb_event_msg_reply_pull,
+ .reply_reqid = ctdb_event_msg_reply_reqid,
+};
+
+
+int ctdb_event_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+ const char *sockpath, struct ctdb_event_context **out)
+{
+ struct ctdb_event_context *eclient;
+ int ret;
+
+ eclient = talloc_zero(mem_ctx, struct ctdb_event_context);
+ if (eclient == NULL) {
+ DEBUG(DEBUG_ERR, (__location__ " memory allocation error\n"));
+ return ENOMEM;
+ }
+
+ ret = sock_client_setup(eclient, ev, sockpath,
+ &event_proto_funcs, eclient,
+ &eclient->sockc);
+ if (ret != 0) {
+ talloc_free(eclient);
+ return ret;
+ }
+
+ *out = eclient;
+ return 0;
+}
+
+void ctdb_event_set_disconnect_callback(struct ctdb_event_context *eclient,
+ ctdb_client_callback_func_t callback,
+ void *private_data)
+{
+ sock_client_set_disconnect_callback(eclient->sockc,
+ callback, private_data);
+}
+
+/*
+ * Handle eventd_request and eventd_reply
+ */
+
+struct tevent_req *ctdb_event_msg_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct ctdb_event_context *eclient,
+ struct ctdb_event_request *request)
+{
+ struct tevent_req *req;
+
+ req = sock_client_msg_send(mem_ctx, ev, eclient->sockc,
+ tevent_timeval_zero(), request);
+ return req;
+}
+
+bool ctdb_event_msg_recv(struct tevent_req *req, int *perr,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_event_reply **reply)
+{
+ void *reply_data;
+ bool status;
+
+ status = sock_client_msg_recv(req, perr, mem_ctx, &reply_data);
+
+ if (status && reply != NULL) {
+ *reply = talloc_get_type_abort(
+ reply_data, struct ctdb_event_reply);
+ }
+
+ return status;
+}
+
+/*
+ * Run an event
+ */
+
+struct tevent_req *ctdb_event_run_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct ctdb_event_context *eclient,
+ enum ctdb_event event,
+ uint32_t timeout, const char *arg_str)
+{
+ struct ctdb_event_request request;
+ struct ctdb_event_request_run rdata;
+
+ rdata.event = event;
+ rdata.timeout = timeout;
+ rdata.arg_str = arg_str;
+
+ request.rdata.command = CTDB_EVENT_COMMAND_RUN;
+ request.rdata.data.run = &rdata;
+
+ return ctdb_event_msg_send(mem_ctx, ev, eclient, &request);
+}
+
+bool ctdb_event_run_recv(struct tevent_req *req, int *perr, int *result)
+{
+ struct ctdb_event_reply *reply;
+ int ret;
+ bool status;
+
+ status = ctdb_event_msg_recv(req, &ret, req, &reply);
+ if (! status) {
+ if (perr != NULL) {
+ *perr = ret;
+ }
+ return false;
+ }
+
+ if (reply->rdata.command != CTDB_EVENT_COMMAND_RUN) {
+ if (perr != NULL) {
+ *perr = EPROTO;
+ }
+ talloc_free(reply);
+ return false;
+ }
+
+ if (result != NULL) {
+ *result = reply->rdata.result;
+ }
+
+ talloc_free(reply);
+ return true;
+}
+
+/*
+ * Get event status
+ */
+
+struct tevent_req *ctdb_event_status_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct ctdb_event_context *eclient,
+ enum ctdb_event event,
+ enum ctdb_event_status_state state)
+{
+ struct ctdb_event_request request;
+ struct ctdb_event_request_status rdata;
+
+ rdata.event = event;
+ rdata.state = state;
+
+ request.rdata.command = CTDB_EVENT_COMMAND_STATUS;
+ request.rdata.data.status = &rdata;
+
+ return ctdb_event_msg_send(mem_ctx, ev, eclient, &request);
+}
+
+bool ctdb_event_status_recv(struct tevent_req *req, int *perr,
+ int32_t *result, int *event_status,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_script_list **script_list)
+{
+ struct ctdb_event_reply *reply;
+ int ret;
+ bool status;
+
+ status = ctdb_event_msg_recv(req, &ret, req, &reply);
+ if (! status) {
+ if (perr != NULL) {
+ *perr = ret;
+ }
+ return false;
+ }
+
+ if (reply->rdata.command != CTDB_EVENT_COMMAND_STATUS) {
+ if (perr != NULL) {
+ *perr = EPROTO;
+ }
+ talloc_free(reply);
+ return false;
+ }
+
+ if (result != NULL) {
+ *result = reply->rdata.result;
+ }
+ if (event_status != NULL) {
+ *event_status = reply->rdata.data.status->status;
+ }
+ if (script_list != NULL) {
+ *script_list = talloc_steal(mem_ctx,
+ reply->rdata.data.status->script_list);
+ }
+
+ talloc_free(reply);
+ return true;
+}
+
+/*
+ * Get script list
+ */
+
+struct tevent_req *ctdb_event_script_list_send(
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct ctdb_event_context *eclient)
+{
+ struct ctdb_event_request request;
+
+ request.rdata.command = CTDB_EVENT_COMMAND_SCRIPT_LIST;
+
+ return ctdb_event_msg_send(mem_ctx, ev, eclient, &request);
+}
+
+bool ctdb_event_script_list_recv(struct tevent_req *req, int *perr,
+ int32_t *result, TALLOC_CTX *mem_ctx,
+ struct ctdb_script_list **script_list)
+{
+ struct ctdb_event_reply *reply;
+ int ret;
+ bool status;
+
+ status = ctdb_event_msg_recv(req, &ret, req, &reply);
+ if (! status) {
+ if (perr != NULL) {
+ *perr = ret;
+ }
+ return false;
+ }
+
+ if (reply->rdata.command != CTDB_EVENT_COMMAND_SCRIPT_LIST) {
+ if (perr != NULL) {
+ *perr = EPROTO;
+ }
+ talloc_free(reply);
+ return false;
+ }
+
+ if (result != NULL) {
+ *result = reply->rdata.result;
+ }
+ if (script_list != NULL) {
+ *script_list = talloc_steal(mem_ctx,
+ reply->rdata.data.script_list->script_list);
+ }
+
+ talloc_free(reply);
+ return true;
+}
+
+/*
+ * Enable a script
+ */
+
+struct tevent_req *ctdb_event_script_enable_send(
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct ctdb_event_context *eclient,
+ const char *script_name)
+{
+ struct ctdb_event_request request;
+ struct ctdb_event_request_script_enable rdata;
+
+ rdata.script_name = script_name;
+
+ request.rdata.command = CTDB_EVENT_COMMAND_SCRIPT_ENABLE;
+ request.rdata.data.script_enable = &rdata;
+
+ return ctdb_event_msg_send(mem_ctx, ev, eclient, &request);
+}
+
+bool ctdb_event_script_enable_recv(struct tevent_req *req, int *perr,
+ int *result)
+{
+ struct ctdb_event_reply *reply;
+ int ret;
+ bool status;
+
+ status = ctdb_event_msg_recv(req, &ret, req, &reply);
+ if (! status) {
+ if (perr != NULL) {
+ *perr = ret;
+ }
+ return false;
+ }
+
+ if (reply->rdata.command != CTDB_EVENT_COMMAND_SCRIPT_ENABLE) {
+ if (perr != NULL) {
+ *perr = EPROTO;
+ }
+ talloc_free(reply);
+ return false;
+ }
+
+ if (result != NULL) {
+ *result = reply->rdata.result;
+ }
+
+ talloc_free(reply);
+ return true;
+}
+
+/*
+ * Disable a script
+ */
+
+struct tevent_req *ctdb_event_script_disable_send(
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct ctdb_event_context *eclient,
+ const char *script_name)
+{
+ struct ctdb_event_request request;
+ struct ctdb_event_request_script_disable rdata;
+
+ rdata.script_name = script_name;
+
+ request.rdata.command = CTDB_EVENT_COMMAND_SCRIPT_DISABLE;
+ request.rdata.data.script_disable = &rdata;
+
+ return ctdb_event_msg_send(mem_ctx, ev, eclient, &request);
+}
+
+bool ctdb_event_script_disable_recv(struct tevent_req *req, int *perr,
+ int *result)
+{
+ struct ctdb_event_reply *reply;
+ int ret;
+ bool status;
+
+ status = ctdb_event_msg_recv(req, &ret, req, &reply);
+ if (! status) {
+ if (perr != NULL) {
+ *perr = ret;
+ }
+ return false;
+ }
+
+ if (reply->rdata.command != CTDB_EVENT_COMMAND_SCRIPT_DISABLE) {
+ if (perr != NULL) {
+ *perr = EPROTO;
+ }
+ talloc_free(reply);
+ return false;
+ }
+
+ if (result != NULL) {
+ *result = reply->rdata.result;
+ }
+
+ talloc_free(reply);
+ return true;
+}