diff options
Diffstat (limited to 'scheduler/random/src/random.c')
-rw-r--r-- | scheduler/random/src/random.c | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/scheduler/random/src/random.c b/scheduler/random/src/random.c new file mode 100644 index 000000000..9e761d08a --- /dev/null +++ b/scheduler/random/src/random.c @@ -0,0 +1,283 @@ +/* + 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 <stdlib.h> +#include <sys/time.h> + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "random.h" + +#define RANDOM_LIMITS_MIN_FREE_DISK_DEFAULT 15 +#define RANDOM_REFRESH_INTERVAL_DEFAULT 10 + + +static int32_t +random_init (xlator_t *xl) +{ + struct random_struct *random_buf = NULL; + xlator_list_t *trav_xl = xl->children; + data_t *limit = NULL; + int32_t index = 0; + + random_buf = CALLOC (1, sizeof (struct random_struct)); + ERR_ABORT (random_buf); + + /* Set the seed for the 'random' function */ + srandom ((uint32_t) time (NULL)); + + limit = dict_get (xl->options, "scheduler.limits.min-free-disk"); + if (limit) { + if (gf_string2percent (data_to_str (limit), + &random_buf->min_free_disk) != 0) { + gf_log ("random", GF_LOG_ERROR, + "invalid number format \"%s\" of \"option " + "scheduler.limits.min-free-disk\"", + limit->data); + return -1; + } + if (random_buf->min_free_disk >= 100) { + gf_log ("random", GF_LOG_ERROR, + "check the \"option random.limits.min-free" + "-disk\", it should be percentage value"); + return -1; + } + + } else { + gf_log ("random", GF_LOG_WARNING, + "No option for limit min-free-disk given, " + "defaulting it to 5%%"); + random_buf->min_free_disk = + RANDOM_LIMITS_MIN_FREE_DISK_DEFAULT; + } + + limit = dict_get (xl->options, "scheduler.refresh-interval"); + if (limit) { + if (gf_string2time (data_to_str (limit), + &random_buf->refresh_interval) != 0) { + gf_log ("random", GF_LOG_ERROR, + "invalid number format \"%s\" of " + "\"option random.refresh-interval\"", + limit->data); + return -1; + } + } else { + random_buf->refresh_interval = RANDOM_REFRESH_INTERVAL_DEFAULT; + } + + while (trav_xl) { + index++; + trav_xl = trav_xl->next; + } + random_buf->child_count = index; + random_buf->array = CALLOC (index, + sizeof (struct random_sched_struct)); + ERR_ABORT (random_buf->array); + trav_xl = xl->children; + index = 0; + + while (trav_xl) { + random_buf->array[index].xl = trav_xl->xlator; + random_buf->array[index].eligible = 1; + trav_xl = trav_xl->next; + index++; + } + pthread_mutex_init (&random_buf->random_mutex, NULL); + + // put it at the proper place + *((long *)xl->private) = (long)random_buf; + return 0; +} + +static void +random_fini (xlator_t *xl) +{ + struct random_struct *random_buf = NULL; + + random_buf = (struct random_struct *)*((long *)xl->private); + pthread_mutex_destroy (&random_buf->random_mutex); + free (random_buf->array); + free (random_buf); +} + + +static int32_t +update_stat_array_cbk (call_frame_t *frame, + void *cookie, + xlator_t *xl, + int32_t op_ret, + int32_t op_errno, + struct xlator_stats *trav_stats) +{ + int32_t idx = 0; + int32_t percent = 0; + struct random_struct *random_buf = NULL; + + random_buf = (struct random_struct *)*((long *)xl->private); + + pthread_mutex_lock (&random_buf->random_mutex); + for (idx = 0; idx < random_buf->child_count; idx++) { + if (strcmp (random_buf->array[idx].xl->name, + (char *)cookie) == 0) + break; + } + pthread_mutex_unlock (&random_buf->random_mutex); + + if (op_ret == 0) { + percent = ((trav_stats->free_disk *100) / + trav_stats->total_disk_size); + if (random_buf->min_free_disk > percent) { + random_buf->array[idx].eligible = 0; + } else { + random_buf->array[idx].eligible = 1; + } + } else { + random_buf->array[idx].eligible = 0; + } + + STACK_DESTROY (frame->root); + return 0; +} + +static void +update_stat_array (xlator_t *xl) +{ + int32_t idx; + struct random_struct *random_buf = NULL; + call_frame_t *frame = NULL; + call_pool_t *pool = xl->ctx->pool; + + random_buf = (struct random_struct *)*((long *)xl->private); + for (idx = 0; idx < random_buf->child_count; idx++) { + frame = create_frame (xl, pool); + + STACK_WIND_COOKIE (frame, + update_stat_array_cbk, + random_buf->array[idx].xl->name, + random_buf->array[idx].xl, + (random_buf->array[idx].xl)->mops->stats, + 0); + } + return ; +} + +static void +random_update (xlator_t *xl) +{ + struct timeval tv; + struct random_struct *random_buf = NULL; + + random_buf = (struct random_struct *)*((long *)xl->private); + + gettimeofday(&tv, NULL); + if (tv.tv_sec > (random_buf->refresh_interval + + random_buf->last_stat_entry.tv_sec)) { + update_stat_array (xl); + random_buf->last_stat_entry.tv_sec = tv.tv_sec; + } +} + +static xlator_t * +random_schedule (xlator_t *xl, const void *path) +{ + struct random_struct *random_buf = NULL; + int32_t rand = 0; + int32_t try = 0; + + random_buf = (struct random_struct *)*((long *)xl->private); + + rand = (int32_t) (1.0*random_buf->child_count * + (random() / (RAND_MAX + 1.0))); + + random_update (xl); + + while (!random_buf->array[rand].eligible) { + if (try++ > 100) { + /* there is a chance of this becoming a + infinite loop otherwise. */ + break; + } + rand = (int32_t) (1.0*random_buf->child_count * + (random() / (RAND_MAX + 1.0))); + } + return random_buf->array[rand].xl; +} + + +/** + * notify + */ +void +random_notify (xlator_t *xl, int32_t event, void *data) +{ + struct random_struct *random_buf = NULL; + int32_t idx = 0; + + random_buf = (struct random_struct *)*((long *)xl->private); + if (!random_buf) + return; + + for (idx = 0; idx < random_buf->child_count; idx++) { + if (random_buf->array[idx].xl == (xlator_t *)data) + break; + } + + switch (event) + { + case GF_EVENT_CHILD_UP: + { + //random_buf->array[idx].eligible = 1; + } + break; + case GF_EVENT_CHILD_DOWN: + { + random_buf->array[idx].eligible = 0; + } + break; + default: + { + ; + } + break; + } + +} + +struct sched_ops sched = { + .init = random_init, + .fini = random_fini, + .update = random_update, + .schedule = random_schedule, + .notify = random_notify +}; + +struct volume_options options[] = { + { .key = { "scheduler.refresh-interval", + "random.refresh-interval" }, + .type = GF_OPTION_TYPE_TIME + }, + { .key = { "scheduler.limits.min-free-disk", + "random.limits.min-free-disk" }, + .type = GF_OPTION_TYPE_PERCENT + }, + { .key = {NULL} } +}; |