summaryrefslogtreecommitdiffstats
path: root/xlators/cluster/ha/src/ha-helpers.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/cluster/ha/src/ha-helpers.c')
-rw-r--r--xlators/cluster/ha/src/ha-helpers.c191
1 files changed, 191 insertions, 0 deletions
diff --git a/xlators/cluster/ha/src/ha-helpers.c b/xlators/cluster/ha/src/ha-helpers.c
new file mode 100644
index 000000000..8193caf27
--- /dev/null
+++ b/xlators/cluster/ha/src/ha-helpers.c
@@ -0,0 +1,191 @@
+/*
+ Copyright (c) 2008, 2009 Z RESEARCH, Inc. <http://www.zresearch.com>
+ This file is part of GlusterFS.
+
+ GlusterFS 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.
+
+ 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/>.
+*/
+
+#include "xlator.h"
+#include "call-stub.h"
+#include "defaults.h"
+#include "dict.h"
+#include "compat-errno.h"
+#include "ha.h"
+
+int ha_alloc_init_fd (call_frame_t *frame, fd_t *fd)
+{
+ ha_local_t *local = NULL;
+ int i = -1;
+ ha_private_t *pvt = NULL;
+ int child_count = 0;
+ int ret = -1;
+ hafd_t *hafdp = NULL;
+ xlator_t *this = NULL;
+ uint64_t tmp_hafdp = 0;
+
+ this = frame->this;
+ local = frame->local;
+ pvt = this->private;
+ child_count = pvt->child_count;
+
+ if (local == NULL) {
+ ret = fd_ctx_get (fd, this, &tmp_hafdp);
+ if (ret < 0) {
+ goto out;
+ }
+ hafdp = (hafd_t *)(long)tmp_hafdp;
+ local = frame->local = CALLOC (1, sizeof (*local));
+ if (local == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ local->state = CALLOC (1, child_count);
+ if (local->state == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* take care of the preferred subvolume */
+ if (pvt->pref_subvol == -1)
+ local->active = hafdp->active;
+ else
+ local->active = pvt->pref_subvol;
+
+ LOCK (&hafdp->lock);
+ memcpy (local->state, hafdp->fdstate, child_count);
+ UNLOCK (&hafdp->lock);
+
+ /* in case the preferred subvolume is down */
+ if ((local->active != -1) && (local->state[local->active] == 0))
+ local->active = -1;
+
+ for (i = 0; i < child_count; i++) {
+ if (local->state[i]) {
+ if (local->active == -1)
+ local->active = i;
+ local->tries++;
+ }
+ }
+ if (local->active == -1) {
+ ret = -ENOTCONN;
+ goto out;
+ }
+ local->fd = fd_ref (fd);
+ }
+ ret = 0;
+out:
+ return ret;
+}
+
+int ha_handle_cbk (call_frame_t *frame, void *cookie, int op_ret, int op_errno)
+{
+ xlator_t *xl = NULL;
+ ha_private_t *pvt = NULL;
+ xlator_t **children = NULL;
+ int prev_child = -1;
+ hafd_t *hafdp = NULL;
+ int ret = -1;
+ call_stub_t *stub = NULL;
+ ha_local_t *local = NULL;
+ uint64_t tmp_hafdp = 0;
+
+ xl = frame->this;
+ pvt = xl->private;
+ children = pvt->children;
+ prev_child = (long) cookie;
+ local = frame->local;
+
+ if (op_ret == -1) {
+ gf_log (xl->name, GF_LOG_ERROR ,"(child=%s) (op_ret=%d op_errno=%s)",
+ children[prev_child]->name, op_ret, strerror (op_errno));
+ }
+ if (op_ret == -1 && (op_errno == ENOTCONN)) {
+ ret = 0;
+ if (local->fd) {
+ ret = fd_ctx_get (local->fd, xl, &tmp_hafdp);
+ }
+ hafdp = (hafd_t *)(long)tmp_hafdp;
+ if (ret == 0) {
+ if (local->fd) {
+ LOCK(&hafdp->lock);
+ hafdp->fdstate[prev_child] = 0;
+ UNLOCK(&hafdp->lock);
+ }
+ local->tries--;
+ if (local->tries != 0) {
+ while (1) {
+ local->active = (local->active + 1) % pvt->child_count;
+ if (local->state[local->active])
+ break;
+ }
+ stub = local->stub;
+ local->stub = NULL;
+ call_resume (stub);
+ return -1;
+ }
+ }
+ }
+ if (local->stub)
+ call_stub_destroy (local->stub);
+ if (local->fd) {
+ FREE (local->state);
+ fd_unref (local->fd);
+ }
+ return 0;
+}
+
+int ha_alloc_init_inode (call_frame_t *frame, inode_t *inode)
+{
+ int i = -1;
+ ha_private_t *pvt = NULL;
+ xlator_t *xl = NULL;
+ int ret = -1;
+ ha_local_t *local = NULL;
+ uint64_t tmp_state = 0;
+
+ xl = frame->this;
+ pvt = xl->private;
+ local = frame->local;
+
+ if (local == NULL) {
+ local = frame->local = CALLOC (1, sizeof (*local));
+ if (local == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ local->active = pvt->pref_subvol;
+ ret = inode_ctx_get (inode, xl, &tmp_state);
+ if (ret < 0) {
+ goto out;
+ }
+ local->state = (char *)(long)tmp_state;
+ if (local->active != -1 && local->state[local->active] == 0)
+ local->active = -1;
+ for (i = 0; i < pvt->child_count; i++) {
+ if (local->state[i]) {
+ if (local->active == -1)
+ local->active = i;
+ local->tries++;
+ }
+ }
+ if (local->active == -1) {
+ ret = -ENOTCONN;
+ goto out;
+ }
+ }
+ ret = 0;
+out:
+ return ret;
+}