📄 switch.c
字号:
/* Copyright (c) 2006, 2007, 2008 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 <sys/time.h>#include <stdlib.h>#include <fnmatch.h>#ifndef _CONFIG_H#define _CONFIG_H#include "config.h"#endif#include "xlator.h"#include "scheduler.h"struct switch_sched_array { xlator_t *xl; int32_t eligible; int32_t considered;};/* Select one of this struct based on the path's pattern match */struct switch_sched_struct { struct switch_sched_struct *next; struct switch_sched_array *array; char path_pattern[256]; int32_t node_index; /* Index of the node in this pattern. */ int32_t num_child; /* Total number of child nodes with this pattern. */};struct switch_struct { struct switch_sched_struct *cond; struct switch_sched_array *array; pthread_mutex_t switch_mutex; int32_t child_count;};/* This function should return child node as '*:subvolumes' is inserterd */static xlator_t *switch_get_matching_xl (const char *path, struct switch_sched_struct *cond){ struct switch_sched_struct *trav = cond; char *pathname = strdup (path); while (trav) { if (fnmatch (trav->path_pattern, pathname, FNM_NOESCAPE) == 0) { free (pathname); trav->node_index %= trav->num_child; return trav->array[(trav->node_index++)%trav->num_child].xl; } trav = trav->next; } free (pathname); return NULL;}static int32_tswitch_init (xlator_t *xl){ int32_t index = 0; data_t *data = NULL; xlator_list_t *trav_xl = xl->children; struct switch_struct *switch_buf = calloc (1, sizeof (struct switch_struct)); while (trav_xl) { index++; trav_xl = trav_xl->next; } switch_buf->child_count = index; switch_buf->array = calloc (index + 1, sizeof (struct switch_sched_struct)); trav_xl = xl->children; index = 0; while (trav_xl) { switch_buf->array[index].xl = trav_xl->xlator; switch_buf->array[index].eligible = 1; trav_xl = trav_xl->next; index++; } data = dict_get (xl->options, "switch.read-only-subvolumes"); if (data) { char *child = NULL; char *tmp = NULL; char *childs_data = strdup (data->data); child = strtok_r (childs_data, ",", &tmp); while (child) { for (index = 1; index < switch_buf->child_count; index++) { if (strcmp (switch_buf->array[index - 1].xl->name, child) == 0) { gf_log ("switch", GF_LOG_DEBUG, "Child '%s' is read-only", child); memcpy (&(switch_buf->array[index - 1]), &(switch_buf->array[switch_buf->child_count - 1]), sizeof (struct switch_sched_array)); switch_buf->child_count--; break; } } child = strtok_r (NULL, ",", &tmp); } free (childs_data); } data = dict_get (xl->options, "switch.nufa.local-volume-name"); if (data) { /* Means, give preference to that node first */ gf_log ("switch", GF_LOG_DEBUG, "local volume defined as %s", data->data); /* TODO: parse it properly, have an extra index to specify that first */ } /* *jpg:child1,child2;*mpg:child3;*:child4,child5,child6 */ data = dict_get (xl->options, "switch.case"); if (data) { char *tmp = NULL; char *tmp_str = NULL; char *tmp_str1 = NULL; char *dup_str = NULL; char *switch_str = NULL; char *pattern = NULL; char *childs = NULL; char *child = NULL; struct switch_sched_struct *switch_opt = NULL; /* Get the pattern for striping. "option block-size *avi:10MB" etc */ switch_str = strtok_r (data->data, ";", &tmp_str); while (switch_str) { dup_str = strdup (switch_str); switch_opt = calloc (1, sizeof (struct switch_sched_struct)); /* Link it to the main structure */ if (switch_buf->cond) { /* there are already few entries */ struct switch_sched_struct *trav = switch_buf->cond; while (trav->next) trav = trav->next; trav->next = switch_opt; } else { /* First entry */ switch_buf->cond = switch_opt; } pattern = strtok_r (dup_str, ":", &tmp_str1); childs = strtok_r (NULL, ":", &tmp_str1); if (strncmp (pattern, "*", 2) == 0) { gf_log ("switch", GF_LOG_WARNING, "'*' pattern will be taken by default for all the unconfigured child nodes, hence neglecting the current option"); switch_str = strtok_r (NULL, ";", &tmp_str); free (dup_str); continue; } memcpy (switch_opt->path_pattern, pattern, strlen (pattern)); if (childs) { int32_t idx = 0; char *tmp1 = NULL; char *dup_childs = NULL; /* TODO: get the list of child nodes for the given pattern */ dup_childs = strdup (childs); child = strtok_r (dup_childs, ",", &tmp); while (child) { idx++; child = strtok_r (NULL, ",", &tmp); } free (dup_childs); child = strtok_r (childs, ",", &tmp1); switch_opt->num_child = idx; switch_opt->array = calloc (1, idx * sizeof (struct switch_sched_array)); idx = 0; child = strtok_r (childs, ",", &tmp); while (child) { for (index = 1; index < switch_buf->child_count; index++) { if (strcmp (switch_buf->array[index - 1].xl->name, child) == 0) { gf_log ("switch", GF_LOG_DEBUG, "'%s' pattern will be scheduled to \"%s\"", switch_opt->path_pattern, child); /* if (switch_buf->array[index-1].considered) { gf_log ("switch", GF_LOG_DEBUG, "ambiguity found, exiting"); return -1; } */ switch_opt->array[idx].xl = switch_buf->array[index-1].xl; switch_buf->array[index-1].considered = 1; idx++; break; } } child = strtok_r (NULL, ",", &tmp1); } } else { /* error */ gf_log ("switch", GF_LOG_ERROR, "Check \"switch.case\" option in unify volume. Exiting"); free (switch_buf->array); free (switch_buf); return -1; } free (dup_str); switch_str = strtok_r (NULL, ";", &tmp_str); } } /* Now, all the pattern based considerations done, so for all the remaining * pattern, '*' to all the remaining child nodes */ { struct switch_sched_struct *switch_opt = NULL; int32_t flag = 0; int32_t index = 0; for (index=0; index < switch_buf->child_count; index++) { /* check for considered flag */ if (switch_buf->array[index].considered) continue; flag++; } if (!flag) { gf_log ("switch", GF_LOG_ERROR, "No nodes left for pattern '*'. Exiting."); return -1; } switch_opt = calloc (1, sizeof (struct switch_sched_struct)); if (switch_buf->cond) { /* there are already few entries */ struct switch_sched_struct *trav = switch_buf->cond; while (trav->next) trav = trav->next; trav->next = switch_opt; } else { /* First entry */ switch_buf->cond = switch_opt; } /* Add the '*' pattern to the array */ memcpy (switch_opt->path_pattern, "*", 2); switch_opt->num_child = flag; switch_opt->array = calloc (1, flag * sizeof (struct switch_sched_array)); flag = 0; for (index=0; index < switch_buf->child_count; index++) { /* check for considered flag */ if (switch_buf->array[index].considered) continue; gf_log ("switch", GF_LOG_DEBUG, "'%s' pattern will be scheduled to \"%s\"", switch_opt->path_pattern, switch_buf->array[index].xl->name); switch_opt->array[flag].xl = switch_buf->array[index].xl; switch_buf->array[index].considered = 1; flag++; } } pthread_mutex_init (&switch_buf->switch_mutex, NULL); *((long *)xl->private) = (long)switch_buf; // put it at the proper place return 0;}static voidswitch_fini (xlator_t *xl){ /* TODO: free all the allocated entries */ struct switch_struct *switch_buf = NULL; switch_buf = (struct switch_struct *)*((long *)xl->private); pthread_mutex_destroy (&switch_buf->switch_mutex); free (switch_buf->array); free (switch_buf);}static xlator_t *switch_schedule (xlator_t *xl, void *path){ struct switch_struct *switch_buf = NULL; switch_buf = (struct switch_struct *)*((long *)xl->private); return switch_get_matching_xl (path, switch_buf->cond);}/** * notify */voidswitch_notify (xlator_t *xl, int32_t event, void *data){ /* TODO: This should be checking in switch_sched_struct */#if 0 struct switch_struct *switch_buf = (struct switch_struct *)*((long *)xl->private); int32_t idx = 0; if (!switch_buf) return; for (idx = 0; idx < switch_buf->child_count; idx++) { if (switch_buf->array[idx].xl == (xlator_t *)data) break; } switch (event) { case GF_EVENT_CHILD_UP: { switch_buf->array[idx].eligible = 1; } break; case GF_EVENT_CHILD_DOWN: { switch_buf->array[idx].eligible = 0; } break; default: { ; } break; }#endif}static void switch_update (xlator_t *xl){ return;}struct sched_ops sched = { .init = switch_init, .fini = switch_fini, .update = switch_update, .schedule = switch_schedule, .notify = switch_notify};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -