diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-op-sm.c')
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 1041 |
1 files changed, 1041 insertions, 0 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c new file mode 100644 index 000000000..41203606c --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -0,0 +1,1041 @@ +/* + Copyright (c) 2006-2009 Gluster, Inc. <http://www.gluster.com> + This file is part of GlusterFS. + + GlusterFS is GF_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. + + GlusterFS 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/>. +*/ + + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif +#include <time.h> +#include <sys/uio.h> +#include <sys/resource.h> + +#include <libgen.h> +#include <uuid/uuid.h> + +//#include "transport.h" +#include "fnmatch.h" +#include "xlator.h" +#include "protocol-common.h" +#include "glusterd.h" +#include "call-stub.h" +#include "defaults.h" +#include "list.h" +#include "dict.h" +#include "compat.h" +#include "compat-errno.h" +#include "statedump.h" +//#include "md5.h" +#include "glusterd-sm.h" +#include "glusterd-op-sm.h" +#include "glusterd-utils.h" +#include "glusterd-ha.h" + +static struct list_head gd_op_sm_queue; +glusterd_op_info_t opinfo; + +static int +glusterd_op_get_len (glusterd_op_t op) +{ + GF_ASSERT (op < GD_OP_MAX); + GF_ASSERT (op > GD_OP_NONE); + int ret = -1; + + switch (op) { + case GD_OP_CREATE_VOLUME: + { + dict_t *dict = glusterd_op_get_ctx (op); + ret = dict_serialized_length (dict); + return ret; + } + break; + + case GD_OP_START_BRICK: + break; + + default: + GF_ASSERT (op); + + } + + return 0; +} + +int +glusterd_op_build_payload (glusterd_op_t op, gd1_mgmt_stage_op_req **req) +{ + int len = 0; + int ret = -1; + gd1_mgmt_stage_op_req *stage_req = NULL; + + GF_ASSERT (op < GD_OP_MAX); + GF_ASSERT (op > GD_OP_NONE); + GF_ASSERT (req); + + len = glusterd_op_get_len (op); + + stage_req = GF_CALLOC (1, sizeof (*stage_req), + gf_gld_mt_mop_stage_req_t); + + if (!stage_req) { + gf_log ("", GF_LOG_ERROR, "Out of Memory"); + goto out; + } + + stage_req->buf.buf_val = GF_CALLOC (1, len, + gf_gld_mt_mop_stage_req_t); + + if (!stage_req->buf.buf_val) { + gf_log ("", GF_LOG_ERROR, "Out of Memory"); + goto out; + } + + glusterd_get_uuid (&stage_req->uuid); + stage_req->op = op; + stage_req->buf.buf_len = len; + + switch (op) { + case GD_OP_CREATE_VOLUME: + { + dict_t *dict = NULL; + dict = glusterd_op_get_ctx (op); + GF_ASSERT (dict); + ret = dict_serialize (dict, + stage_req->buf.buf_val); + if (ret) { + goto out; + } + } + + + default: + break; + } + + *req = stage_req; + ret = 0; + +out: + return ret; +} + + + +/*static int +glusterd_xfer_stage_req (xlator_t *this, int32_t *lock_count) +{ + gf_hdr_common_t *hdr = NULL; + size_t hdrlen = -1; + int ret = -1; + glusterd_conf_t *priv = NULL; + call_frame_t *dummy_frame = NULL; + glusterd_peerinfo_t *peerinfo = NULL; + int pending_lock = 0; + int i = 0; + + GF_ASSERT (this); + GF_ASSERT (lock_count); + + priv = this->private; + GF_ASSERT (priv); + + + for ( i = GD_OP_NONE; i < GD_OP_MAX; i++) { + if (opinfo.pending_op[i]) + break; + } + + if (GD_OP_MAX == i) { + + //No pending ops, inject stage_acc + + glusterd_op_sm_event_t *event = NULL; + + ret = glusterd_op_sm_new_event (GD_OP_EVENT_STAGE_ACC, + &event); + + if (ret) + goto out; + + ret = glusterd_op_sm_inject_event (event); + + return ret; + } + + + ret = glusterd_op_build_payload (i, &hdr, &hdrlen); + + if (ret) + goto out; + + dummy_frame = create_frame (this, this->ctx->pool); + + if (!dummy_frame) + goto out; + + list_for_each_entry (peerinfo, &opinfo.op_peers, op_peers_list) { + GF_ASSERT (peerinfo); + + GF_ASSERT (peerinfo->state.state == GD_FRIEND_STATE_BEFRIENDED); + + + ret = glusterd_xfer (dummy_frame, this, + peerinfo->trans, + GF_OP_TYPE_MOP_REQUEST, + GF_MOP_STAGE_OP, + hdr, hdrlen, NULL, 0, NULL); + if (!ret) + pending_lock++; + } + + gf_log ("glusterd", GF_LOG_NORMAL, "Sent op req to %d peers", + pending_lock); + if (i < GD_OP_MAX) + opinfo.pending_op[i] = 0; + + *lock_count = pending_lock; + +out: + if (hdr) + GF_FREE (hdr); + + return ret; +} */ + +/*static int +glusterd_xfer_commit_req (xlator_t *this, int32_t *lock_count) +{ + gf_hdr_common_t *hdr = NULL; + size_t hdrlen = -1; + int ret = -1; + glusterd_conf_t *priv = NULL; + call_frame_t *dummy_frame = NULL; + glusterd_peerinfo_t *peerinfo = NULL; + int pending_lock = 0; + int i = 0; + + GF_ASSERT (this); + GF_ASSERT (lock_count); + + priv = this->private; + GF_ASSERT (priv); + + + for ( i = GD_OP_NONE; i < GD_OP_MAX; i++) { + if (opinfo.commit_op[i]) + break; + } + + if (GD_OP_MAX == i) { + + //No pending ops, inject stage_acc + + glusterd_op_sm_event_t *event = NULL; + + ret = glusterd_op_sm_new_event (GD_OP_EVENT_COMMIT_ACC, + &event); + + if (ret) + goto out; + + ret = glusterd_op_sm_inject_event (event); + + return ret; + } + + + ret = glusterd_op_build_payload (i, &hdr, &hdrlen); + + if (ret) + goto out; + + dummy_frame = create_frame (this, this->ctx->pool); + + if (!dummy_frame) + goto out; + + list_for_each_entry (peerinfo, &opinfo.op_peers, op_peers_list) { + GF_ASSERT (peerinfo); + + GF_ASSERT (peerinfo->state.state == GD_FRIEND_STATE_BEFRIENDED); + + + ret = glusterd_xfer (dummy_frame, this, + peerinfo->trans, + GF_OP_TYPE_MOP_REQUEST, + GF_MOP_STAGE_OP, + hdr, hdrlen, NULL, 0, NULL); + if (!ret) + pending_lock++; + } + + gf_log ("glusterd", GF_LOG_NORMAL, "Sent op req to %d peers", + pending_lock); + if (i < GD_OP_MAX) + opinfo.pending_op[i] = 0; + + *lock_count = pending_lock; + +out: + if (hdr) + GF_FREE (hdr); + + return ret; +}*/ + +static int +glusterd_op_stage_create_volume (gd1_mgmt_stage_op_req *req) +{ + int ret = 0; + dict_t *dict = NULL; + char *volname = NULL; + gf_boolean_t exists = _gf_false; + + GF_ASSERT (req); + + ret = dict_unserialize (req->buf.buf_val, req->buf.buf_len, &dict); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to unserialize dict"); + goto out; + } + + ret = dict_get_str (dict, "volname", &volname); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + exists = glusterd_check_volume_exists (volname); + + if (exists) { + gf_log ("", GF_LOG_ERROR, "Volume with name: %s exists", + volname); + ret = -1; + } else { + ret = 0; + } + +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +static int +glusterd_op_create_volume (gd1_mgmt_stage_op_req *req) +{ + int ret = 0; + dict_t *dict = NULL; + char *volname = NULL; + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + xlator_t *this = NULL; + char *brick = NULL; + int32_t count = 0; + int32_t i = 0; + char key[50]; + + GF_ASSERT (req); + + this = THIS; + GF_ASSERT (this); + + priv = this->private; + GF_ASSERT (priv); + + ret = dict_unserialize (req->buf.buf_val, req->buf.buf_len, &dict); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to unserialize dict"); + goto out; + } + + ret = glusterd_volinfo_new (&volinfo); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + goto out; + } + + ret = dict_get_str (dict, "volname", &volname); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + strncpy (volinfo->volname, volname, 1024); + + GF_ASSERT (volinfo->volname); + + ret = dict_get_int32 (dict, "type", &volinfo->type); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get type"); + goto out; + } + + ret = dict_get_int32 (dict, "count", &volinfo->brick_count); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get count"); + goto out; + } + + count = volinfo->brick_count; + + while ( i <= count) { + snprintf (key, 50, "brick%d", i); + ret = dict_get_str (dict, key, &brick); + if (ret) + goto out; + + ret = glusterd_brickinfo_from_brick (brick, &brickinfo); + if (ret) + goto out; + + list_add_tail (&brickinfo->brick_list, &volinfo->bricks); + i++; + } + + ret = glusterd_ha_create_volume (volinfo); + +out: + return ret; +} + +static int +glusterd_op_ac_none (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + + return ret; +} + +static int +glusterd_op_ac_send_lock (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + rpc_clnt_procedure_t *proc = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + + this = THIS; + priv = this->private; + + proc = &priv->mgmt->proctable[GD_MGMT_CLUSTER_LOCK]; + if (proc->fn) { + ret = proc->fn (NULL, this, NULL); + } + // TODO: if pending_count = 0, inject ALL_ACC here + + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + + return ret; +} + +static int +glusterd_op_ac_send_unlock (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + rpc_clnt_procedure_t *proc = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + + this = THIS; + priv = this->private; + + proc = &priv->mgmt->proctable[GD_MGMT_CLUSTER_UNLOCK]; + if (proc->fn) { + ret = proc->fn (NULL, this, NULL); + } + // TODO: if pending_count = 0, inject ALL_ACC here + + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + + return ret; + +} + +static int +glusterd_op_ac_lock (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + glusterd_op_lock_ctx_t *lock_ctx = NULL; + int32_t status = 0; + + + GF_ASSERT (event); + GF_ASSERT (ctx); + + lock_ctx = (glusterd_op_lock_ctx_t *)ctx; + + status = glusterd_lock (lock_ctx->uuid); + + gf_log ("", GF_LOG_DEBUG, "Lock Returned %d", status); + + ret = glusterd_op_lock_send_resp (lock_ctx->req, status); + + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + + return ret; +} + +static int +glusterd_op_ac_unlock (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + glusterd_op_lock_ctx_t *lock_ctx = NULL; + + GF_ASSERT (event); + GF_ASSERT (ctx); + + lock_ctx = (glusterd_op_lock_ctx_t *)ctx; + + ret = glusterd_unlock (lock_ctx->uuid); + + gf_log ("", GF_LOG_DEBUG, "Unlock Returned %d", ret); + + ret = glusterd_op_unlock_send_resp (lock_ctx->req, ret); + + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + + return ret; +} + +static int +glusterd_op_ac_rcvd_lock_acc (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + glusterd_op_sm_event_t *new_event = NULL; + + GF_ASSERT (event); + + opinfo.pending_count--; + + if (opinfo.pending_count) + goto out; + + ret = glusterd_op_sm_new_event (GD_OP_EVENT_ALL_ACC, &new_event); + + if (ret) + goto out; + + ret = glusterd_op_sm_inject_event (new_event); + + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + +out: + return ret; +} + +static int +glusterd_op_ac_send_stage_op (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + rpc_clnt_procedure_t *proc = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + GF_ASSERT (priv->mgmt); + + proc = &priv->mgmt->proctable[GD_MGMT_STAGE_OP]; + GF_ASSERT (proc); + if (proc->fn) { + ret = proc->fn (NULL, this, NULL); + } + // TODO: if pending_count = 0, inject ALL_ACC here + + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + + return ret; + +} + +static int +glusterd_op_ac_send_commit_op (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + rpc_clnt_procedure_t *proc = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + GF_ASSERT (priv->mgmt); + + proc = &priv->mgmt->proctable[GD_MGMT_COMMIT_OP]; + GF_ASSERT (proc); + if (proc->fn) { + ret = proc->fn (NULL, this, NULL); + } + // TODO: if pending_count = 0, inject ALL_ACC here + + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + + return ret; + +} + +static int +glusterd_op_ac_rcvd_stage_op_acc (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + glusterd_op_sm_event_t *new_event = NULL; + + GF_ASSERT (event); + + opinfo.pending_count--; + + if (opinfo.pending_count) + goto out; + + ret = glusterd_op_sm_new_event (GD_OP_EVENT_STAGE_ACC, &new_event); + + if (ret) + goto out; + + ret = glusterd_op_sm_inject_event (new_event); + + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + +out: + return ret; +} + +static int +glusterd_op_ac_rcvd_commit_op_acc (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + glusterd_op_sm_event_t *new_event = NULL; + + GF_ASSERT (event); + + opinfo.pending_count--; + + if (opinfo.pending_count) + goto out; + + ret = glusterd_op_sm_new_event (GD_OP_EVENT_COMMIT_ACC, &new_event); + + if (ret) + goto out; + + ret = glusterd_op_sm_inject_event (new_event); + + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + +out: + return ret; +} + +static int +glusterd_op_ac_rcvd_unlock_acc (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + glusterd_op_sm_event_t *new_event = NULL; + + GF_ASSERT (event); + + opinfo.pending_count--; + + if (opinfo.pending_count) + goto out; + + ret = glusterd_op_sm_new_event (GD_OP_EVENT_ALL_ACC, &new_event); + + if (ret) + goto out; + + ret = glusterd_op_sm_inject_event (new_event); + + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + +out: + return ret; +} + +static int +glusterd_op_ac_commit_error (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + + //Log here with who failed the commit + // + return ret; +} + +static int +glusterd_op_ac_stage_op (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = -1; + gd1_mgmt_stage_op_req *req = NULL; + glusterd_op_stage_ctx_t *stage_ctx = NULL; + int32_t status = 0; + + GF_ASSERT (ctx); + + stage_ctx = ctx; + + req = stage_ctx->stage_req; + + switch (req->op) { + case GD_OP_CREATE_VOLUME: + status = glusterd_op_stage_create_volume (req); + break; + + default: + gf_log ("", GF_LOG_ERROR, "Unknown op %d", + req->op); + } + + ret = glusterd_op_stage_send_resp (stage_ctx->req, req->op, status); + + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + + return ret; +} + +static int +glusterd_op_ac_commit_op (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + gd1_mgmt_stage_op_req *req = NULL; + glusterd_op_commit_ctx_t *commit_ctx = NULL; + int32_t status = 0; + + GF_ASSERT (ctx); + + commit_ctx = ctx; + + req = commit_ctx->stage_req; + + switch (req->op) { + case GD_OP_CREATE_VOLUME: + ret = glusterd_op_create_volume (req); + break; + + default: + gf_log ("", GF_LOG_ERROR, "Unknown op %d", + req->op); + } + + ret = glusterd_op_commit_send_resp (commit_ctx->req, req->op, status); + + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + + return ret; +} + + +static int +glusterd_op_sm_transition_state (glusterd_op_info_t *opinfo, + glusterd_op_sm_t *state, + glusterd_op_sm_event_type_t event_type) +{ + + GF_ASSERT (state); + GF_ASSERT (opinfo); + + gf_log ("", GF_LOG_NORMAL, "Transitioning from %d to %d", + opinfo->state.state, state[event_type].next_state); + opinfo->state.state = + state[event_type].next_state; + return 0; +} + + + +glusterd_op_sm_t glusterd_op_state_default [] = { + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_NONE + {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_send_lock},//EVENT_START_LOCK + {GD_OP_STATE_LOCKED, glusterd_op_ac_lock}, //EVENT_LOCK + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_RCVD_ACC + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_ALL_ACC + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_STAGE_ACC + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_COMMIT_ACC + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_RCVD_RJT + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_STAGE_OP + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_COMMIT_OP + {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_MAX +}; + +glusterd_op_sm_t glusterd_op_state_lock_sent [] = { + {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_NONE + {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none},//EVENT_START_LOCK + {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_rcvd_lock_acc}, //EVENT_RCVD_ACC + {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_send_stage_op}, //EVENT_ALL_ACC + {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_STAGE_ACC + {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_ACC + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_RCVD_RJT + {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_STAGE_OP + {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_OP + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_MAX +}; + +glusterd_op_sm_t glusterd_op_state_locked [] = { + {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_NONE + {GD_OP_STATE_LOCKED, glusterd_op_ac_none},//EVENT_START_LOCK + {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_RCVD_ACC + {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_ALL_ACC + {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_STAGE_ACC + {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_COMMIT_ACC + {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_RCVD_RJT + {GD_OP_STATE_STAGED, glusterd_op_ac_stage_op}, //EVENT_STAGE_OP + {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_COMMIT_OP + {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_MAX +}; + +glusterd_op_sm_t glusterd_op_state_stage_op_sent [] = { + {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_NONE + {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none},//EVENT_START_LOCK + {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_rcvd_stage_op_acc}, //EVENT_RCVD_ACC + {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_send_stage_op}, //EVENT_ALL_ACC + {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_send_commit_op}, //EVENT_STAGE_ACC + {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_ACC + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_RCVD_RJT + {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_STAGE_OP + {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_OP + {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_MAX +}; + +glusterd_op_sm_t glusterd_op_state_staged [] = { + {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_NONE + {GD_OP_STATE_STAGED, glusterd_op_ac_none},//EVENT_START_LOCK + {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_RCVD_ACC + {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_ALL_ACC + {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_STAGE_ACC + {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_COMMIT_ACC + {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_RCVD_RJT + {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_STAGE_OP + {GD_OP_STATE_COMMITED, glusterd_op_ac_commit_op}, //EVENT_COMMIT_OP + {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_MAX +}; + +glusterd_op_sm_t glusterd_op_state_commit_op_sent [] = { + {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_NONE + {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none},//EVENT_START_LOCK + {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_rcvd_commit_op_acc}, //EVENT_RCVD_ACC + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_commit_op}, //EVENT_ALL_ACC + {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_STAGE_ACC + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_COMMIT_ACC + {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_commit_error}, //EVENT_RCVD_RJT + {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_STAGE_OP + {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_OP + {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_MAX +}; + +glusterd_op_sm_t glusterd_op_state_commited [] = { + {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_NONE + {GD_OP_STATE_COMMITED, glusterd_op_ac_none},//EVENT_START_LOCK + {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_RCVD_ACC + {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_ALL_ACC + {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_STAGE_ACC + {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_COMMIT_ACC + {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_RCVD_RJT + {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_STAGE_OP + {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_COMMIT_OP + {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_MAX +}; + +glusterd_op_sm_t glusterd_op_state_unlock_sent [] = { + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_NONE + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none},//EVENT_START_LOCK + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_rcvd_unlock_acc}, //EVENT_RCVD_ACC + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_ALL_ACC + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_STAGE_ACC + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_ACC + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_RCVD_RJT + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_STAGE_OP + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_OP + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_MAX +}; + + +glusterd_op_sm_t *glusterd_op_state_table [] = { + glusterd_op_state_default, + glusterd_op_state_lock_sent, + glusterd_op_state_locked, + glusterd_op_state_stage_op_sent, + glusterd_op_state_staged, + glusterd_op_state_commit_op_sent, + glusterd_op_state_commited, + glusterd_op_state_unlock_sent +}; + +int +glusterd_op_sm_new_event (glusterd_op_sm_event_type_t event_type, + glusterd_op_sm_event_t **new_event) +{ + glusterd_op_sm_event_t *event = NULL; + + GF_ASSERT (new_event); + GF_ASSERT (GD_OP_EVENT_NONE <= event_type && + GD_OP_EVENT_MAX > event_type); + + event = GF_CALLOC (1, sizeof (*event), gf_gld_mt_op_sm_event_t); + + if (!event) + return -1; + + *new_event = event; + event->event = event_type; + INIT_LIST_HEAD (&event->list); + + return 0; +} + +int +glusterd_op_sm_inject_event (glusterd_op_sm_event_t *event) +{ + GF_ASSERT (event); + gf_log ("glusterd", GF_LOG_NORMAL, "Enqueuing event: %d", + event->event); + list_add_tail (&event->list, &gd_op_sm_queue); + + return 0; +} + + +int +glusterd_op_sm () +{ + glusterd_op_sm_event_t *event = NULL; + glusterd_op_sm_event_t *tmp = NULL; + int ret = -1; + glusterd_op_sm_ac_fn handler = NULL; + glusterd_op_sm_t *state = NULL; + glusterd_op_sm_event_type_t event_type = 0; + + + while (!list_empty (&gd_op_sm_queue)) { + + list_for_each_entry_safe (event, tmp, &gd_op_sm_queue, list) { + + list_del_init (&event->list); + event_type = event->event; + + state = glusterd_op_state_table[opinfo.state.state]; + + GF_ASSERT (state); + + handler = state[event_type].handler; + GF_ASSERT (handler); + + ret = handler (event, event->ctx); + + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, + "handler returned: %d", ret); + return ret; + } + + ret = glusterd_op_sm_transition_state (&opinfo, state, + event_type); + + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, + "Unable to transition" + "state from %d to %d", + opinfo.state.state, + state[event_type].next_state); + return ret; + } + + GF_FREE (event); + } + } + + + ret = 0; + + return ret; +} + +int32_t +glusterd_op_set_op (glusterd_op_t op) +{ + + GF_ASSERT (op < GD_OP_MAX); + GF_ASSERT (op > GD_OP_NONE); + + opinfo.op[op] = 1; + opinfo.pending_op[op] = 1; + opinfo.commit_op[op] = 1; + + return 0; + +} + +int32_t +glusterd_op_set_ctx (glusterd_op_t op, void *ctx) +{ + + GF_ASSERT (op < GD_OP_MAX); + GF_ASSERT (op > GD_OP_NONE); + + opinfo.op_ctx[op] = ctx; + + return 0; + +} + + +void * +glusterd_op_get_ctx (glusterd_op_t op) +{ + GF_ASSERT (op < GD_OP_MAX); + GF_ASSERT (op > GD_OP_NONE); + + return opinfo.op_ctx[op]; + +} + +int +glusterd_op_sm_init () +{ + INIT_LIST_HEAD (&gd_op_sm_queue); + return 0; +} |