⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 switch.c

📁 分布式文件系统
💻 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 + -