summaryrefslogtreecommitdiffstats
path: root/scheduler/alu/src/alu.c
diff options
context:
space:
mode:
Diffstat (limited to 'scheduler/alu/src/alu.c')
-rw-r--r--scheduler/alu/src/alu.c1019
1 files changed, 0 insertions, 1019 deletions
diff --git a/scheduler/alu/src/alu.c b/scheduler/alu/src/alu.c
deleted file mode 100644
index 58bef60ae9f..00000000000
--- a/scheduler/alu/src/alu.c
+++ /dev/null
@@ -1,1019 +0,0 @@
-/*
- Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.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/>.
-*/
-
-
-
-/* ALU code needs a complete re-write. This is one of the most important
- * part of GlusterFS and so needs more and more reviews and testing
- */
-
-#ifndef _CONFIG_H
-#define _CONFIG_H
-#include "config.h"
-#endif
-
-#include <sys/time.h>
-#include <stdint.h>
-#include "stack.h"
-#include "alu.h"
-#include "alu-mem-types.h"
-
-#define ALU_DISK_USAGE_ENTRY_THRESHOLD_DEFAULT (1 * GF_UNIT_GB)
-#define ALU_DISK_USAGE_EXIT_THRESHOLD_DEFAULT (512 * GF_UNIT_MB)
-
-#define ALU_WRITE_USAGE_ENTRY_THRESHOLD_DEFAULT 25
-#define ALU_WRITE_USAGE_EXIT_THRESHOLD_DEFAULT 5
-
-#define ALU_READ_USAGE_ENTRY_THRESHOLD_DEFAULT 25
-#define ALU_READ_USAGE_EXIT_THRESHOLD_DEFAULT 5
-
-#define ALU_OPEN_FILES_USAGE_ENTRY_THRESHOLD_DEFAULT 1000
-#define ALU_OPEN_FILES_USAGE_EXIT_THRESHOLD_DEFAULT 100
-
-#define ALU_LIMITS_TOTAL_DISK_SIZE_DEFAULT 100
-
-#define ALU_REFRESH_INTERVAL_DEFAULT 5
-#define ALU_REFRESH_CREATE_COUNT_DEFAULT 5
-
-
-static int64_t
-get_stats_disk_usage (struct xlator_stats *this)
-{
- return this->disk_usage;
-}
-
-static int64_t
-get_stats_write_usage (struct xlator_stats *this)
-{
- return this->write_usage;
-}
-
-static int64_t
-get_stats_read_usage (struct xlator_stats *this)
-{
- return this->read_usage;
-}
-
-static int64_t
-get_stats_disk_speed (struct xlator_stats *this)
-{
- return this->disk_speed;
-}
-
-static int64_t
-get_stats_file_usage (struct xlator_stats *this)
-{
- /* Avoid warning "defined but not used" */
- (void) &get_stats_file_usage;
-
- return this->nr_files;
-}
-
-static int64_t
-get_stats_free_disk (struct xlator_stats *this)
-{
- if (this->total_disk_size > 0)
- return (this->free_disk * 100) / this->total_disk_size;
- return 0;
-}
-
-static int64_t
-get_max_diff_write_usage (struct xlator_stats *max, struct xlator_stats *min)
-{
- return (max->write_usage - min->write_usage);
-}
-
-static int64_t
-get_max_diff_read_usage (struct xlator_stats *max, struct xlator_stats *min)
-{
- return (max->read_usage - min->read_usage);
-}
-
-static int64_t
-get_max_diff_disk_usage (struct xlator_stats *max, struct xlator_stats *min)
-{
- return (max->disk_usage - min->disk_usage);
-}
-
-static int64_t
-get_max_diff_disk_speed (struct xlator_stats *max, struct xlator_stats *min)
-{
- return (max->disk_speed - min->disk_speed);
-}
-
-static int64_t
-get_max_diff_file_usage (struct xlator_stats *max, struct xlator_stats *min)
-{
- return (max->nr_files - min->nr_files);
-}
-
-
-int
-alu_parse_options (xlator_t *xl, struct alu_sched *alu_sched)
-{
- data_t *order = dict_get (xl->options, "scheduler.alu.order");
- if (!order) {
- gf_log (xl->name, GF_LOG_ERROR,
- "option 'scheduler.alu.order' not specified");
- return -1;
- }
- struct alu_threshold *_threshold_fn;
- struct alu_threshold *tmp_threshold;
- data_t *entry_fn = NULL;
- data_t *exit_fn = NULL;
- char *tmp_str = NULL;
- char *order_str = strtok_r (order->data, ":", &tmp_str);
- /* Get the scheduling priority order, specified by the user. */
- while (order_str) {
- gf_log ("alu", GF_LOG_DEBUG,
- "alu_init: order string: %s",
- order_str);
- if (strcmp (order_str, "disk-usage") == 0) {
- /* Disk usage */
- _threshold_fn =
- GF_CALLOC (1,
- sizeof (struct alu_threshold),
- gf_alu_mt_alu_threshold);
- ERR_ABORT (_threshold_fn);
- _threshold_fn->diff_value = get_max_diff_disk_usage;
- _threshold_fn->sched_value = get_stats_disk_usage;
- entry_fn =
- dict_get (xl->options,
- "scheduler.alu.disk-usage.entry-threshold");
- if (entry_fn) {
- if (gf_string2bytesize (entry_fn->data,
- &alu_sched->entry_limit.disk_usage) != 0) {
- gf_log (xl->name, GF_LOG_ERROR,
- "invalid number format \"%s\" "
- "of \"option scheduler.alu."
- "disk-usage.entry-threshold\"",
- entry_fn->data);
- return -1;
- }
- } else {
- alu_sched->entry_limit.disk_usage = ALU_DISK_USAGE_ENTRY_THRESHOLD_DEFAULT;
- }
- _threshold_fn->entry_value = get_stats_disk_usage;
- exit_fn = dict_get (xl->options,
- "scheduler.alu.disk-usage.exit-threshold");
- if (exit_fn) {
- if (gf_string2bytesize (exit_fn->data, &alu_sched->exit_limit.disk_usage) != 0) {
- gf_log (xl->name, GF_LOG_ERROR,
- "invalid number format \"%s\" "
- "of \"option scheduler.alu."
- "disk-usage.exit-threshold\"",
- exit_fn->data);
- return -1;
- }
- } else {
- alu_sched->exit_limit.disk_usage = ALU_DISK_USAGE_EXIT_THRESHOLD_DEFAULT;
- }
- _threshold_fn->exit_value = get_stats_disk_usage;
- tmp_threshold = alu_sched->threshold_fn;
- if (!tmp_threshold) {
- alu_sched->threshold_fn = _threshold_fn;
- } else {
- while (tmp_threshold->next) {
- tmp_threshold = tmp_threshold->next;
- }
- tmp_threshold->next = _threshold_fn;
- }
- gf_log ("alu",
- GF_LOG_DEBUG, "alu_init: = %"PRId64",%"PRId64"",
- alu_sched->entry_limit.disk_usage,
- alu_sched->exit_limit.disk_usage);
-
- } else if (strcmp (order_str, "write-usage") == 0) {
- /* Handle "write-usage" */
-
- _threshold_fn = GF_CALLOC (1, sizeof (struct alu_threshold), gf_alu_mt_alu_threshold);
- ERR_ABORT (_threshold_fn);
- _threshold_fn->diff_value = get_max_diff_write_usage;
- _threshold_fn->sched_value = get_stats_write_usage;
- entry_fn = dict_get (xl->options,
- "scheduler.alu.write-usage.entry-threshold");
- if (entry_fn) {
- if (gf_string2bytesize (entry_fn->data,
- &alu_sched->entry_limit.write_usage) != 0) {
- gf_log (xl->name, GF_LOG_ERROR,
- "invalid number format \"%s\" "
- "of option scheduler.alu."
- "write-usage.entry-threshold",
- entry_fn->data);
- return -1;
- }
- } else {
- alu_sched->entry_limit.write_usage = ALU_WRITE_USAGE_ENTRY_THRESHOLD_DEFAULT;
- }
- _threshold_fn->entry_value = get_stats_write_usage;
- exit_fn = dict_get (xl->options,
- "scheduler.alu.write-usage.exit-threshold");
- if (exit_fn) {
- if (gf_string2bytesize (exit_fn->data,
- &alu_sched->exit_limit.write_usage) != 0) {
- gf_log (xl->name, GF_LOG_ERROR,
- "invalid number format \"%s\""
- " of \"option scheduler.alu."
- "write-usage.exit-threshold\"",
- exit_fn->data);
- return -1;
- }
- } else {
- alu_sched->exit_limit.write_usage = ALU_WRITE_USAGE_EXIT_THRESHOLD_DEFAULT;
- }
- _threshold_fn->exit_value = get_stats_write_usage;
- tmp_threshold = alu_sched->threshold_fn;
- if (!tmp_threshold) {
- alu_sched->threshold_fn = _threshold_fn;
- } else {
- while (tmp_threshold->next) {
- tmp_threshold = tmp_threshold->next;
- }
- tmp_threshold->next = _threshold_fn;
- }
- gf_log (xl->name, GF_LOG_DEBUG,
- "alu_init: = %"PRId64",%"PRId64"",
- alu_sched->entry_limit.write_usage,
- alu_sched->exit_limit.write_usage);
-
- } else if (strcmp (order_str, "read-usage") == 0) {
- /* Read usage */
-
- _threshold_fn = GF_CALLOC (1, sizeof (struct alu_threshold), gf_alu_mt_alu_threshold);
- ERR_ABORT (_threshold_fn);
- _threshold_fn->diff_value = get_max_diff_read_usage;
- _threshold_fn->sched_value = get_stats_read_usage;
- entry_fn = dict_get (xl->options,
- "scheduler.alu.read-usage.entry-threshold");
- if (entry_fn) {
- if (gf_string2bytesize (entry_fn->data,
- &alu_sched->entry_limit.read_usage) != 0) {
- gf_log (xl->name,
- GF_LOG_ERROR,
- "invalid number format \"%s\" "
- "of \"option scheduler.alu."
- "read-usage.entry-threshold\"",
- entry_fn->data);
- return -1;
- }
- } else {
- alu_sched->entry_limit.read_usage = ALU_READ_USAGE_ENTRY_THRESHOLD_DEFAULT;
- }
- _threshold_fn->entry_value = get_stats_read_usage;
- exit_fn = dict_get (xl->options,
- "scheduler.alu.read-usage.exit-threshold");
- if (exit_fn)
- {
- if (gf_string2bytesize (exit_fn->data,
- &alu_sched->exit_limit.read_usage) != 0)
- {
- gf_log ("alu", GF_LOG_ERROR,
- "invalid number format \"%s\" "
- "of \"option scheduler.alu."
- "read-usage.exit-threshold\"",
- exit_fn->data);
- return -1;
- }
- }
- else
- {
- alu_sched->exit_limit.read_usage = ALU_READ_USAGE_EXIT_THRESHOLD_DEFAULT;
- }
- _threshold_fn->exit_value = get_stats_read_usage;
- tmp_threshold = alu_sched->threshold_fn;
- if (!tmp_threshold) {
- alu_sched->threshold_fn = _threshold_fn;
- }
- else {
- while (tmp_threshold->next) {
- tmp_threshold = tmp_threshold->next;
- }
- tmp_threshold->next = _threshold_fn;
- }
- gf_log ("alu", GF_LOG_DEBUG,
- "alu_init: = %"PRId64",%"PRId64"",
- alu_sched->entry_limit.read_usage,
- alu_sched->exit_limit.read_usage);
-
- } else if (strcmp (order_str, "open-files-usage") == 0) {
- /* Open files counter */
-
- _threshold_fn = GF_CALLOC (1, sizeof (struct alu_threshold), gf_alu_mt_alu_threshold);
- ERR_ABORT (_threshold_fn);
- _threshold_fn->diff_value = get_max_diff_file_usage;
- _threshold_fn->sched_value = get_stats_file_usage;
- entry_fn = dict_get (xl->options,
- "scheduler.alu.open-files-usage.entry-threshold");
- if (entry_fn) {
- if (gf_string2uint64 (entry_fn->data,
- &alu_sched->entry_limit.nr_files) != 0)
- {
- gf_log ("alu", GF_LOG_ERROR,
- "invalid number format \"%s\" "
- "of \"option scheduler.alu."
- "open-files-usage.entry-"
- "threshold\"", entry_fn->data);
- return -1;
- }
- }
- else
- {
- alu_sched->entry_limit.nr_files = ALU_OPEN_FILES_USAGE_ENTRY_THRESHOLD_DEFAULT;
- }
- _threshold_fn->entry_value = get_stats_file_usage;
- exit_fn = dict_get (xl->options,
- "scheduler.alu.open-files-usage.exit-threshold");
- if (exit_fn)
- {
- if (gf_string2uint64 (exit_fn->data,
- &alu_sched->exit_limit.nr_files) != 0)
- {
- gf_log ("alu", GF_LOG_ERROR,
- "invalid number format \"%s\" "
- "of \"option scheduler.alu."
- "open-files-usage.exit-"
- "threshold\"", exit_fn->data);
- return -1;
- }
- }
- else
- {
- alu_sched->exit_limit.nr_files = ALU_OPEN_FILES_USAGE_EXIT_THRESHOLD_DEFAULT;
- }
- _threshold_fn->exit_value = get_stats_file_usage;
- tmp_threshold = alu_sched->threshold_fn;
- if (!tmp_threshold) {
- alu_sched->threshold_fn = _threshold_fn;
- }
- else {
- while (tmp_threshold->next) {
- tmp_threshold = tmp_threshold->next;
- }
- tmp_threshold->next = _threshold_fn;
- }
- gf_log ("alu", GF_LOG_DEBUG,
- "alu.c->alu_init: = %"PRIu64",%"PRIu64"",
- alu_sched->entry_limit.nr_files,
- alu_sched->exit_limit.nr_files);
-
- } else if (strcmp (order_str, "disk-speed-usage") == 0) {
- /* Disk speed */
-
- _threshold_fn = GF_CALLOC (1, sizeof (struct alu_threshold), gf_alu_mt_alu_threshold);
- ERR_ABORT (_threshold_fn);
- _threshold_fn->diff_value = get_max_diff_disk_speed;
- _threshold_fn->sched_value = get_stats_disk_speed;
- entry_fn = dict_get (xl->options,
- "scheduler.alu.disk-speed-usage.entry-threshold");
- if (entry_fn) {
- gf_log ("alu", GF_LOG_DEBUG,
- "entry-threshold is given, "
- "value is constant");
- }
- _threshold_fn->entry_value = NULL;
- exit_fn = dict_get (xl->options,
- "scheduler.alu.disk-speed-usage.exit-threshold");
- if (exit_fn) {
- gf_log ("alu", GF_LOG_DEBUG,
- "exit-threshold is given, "
- "value is constant");
- }
- _threshold_fn->exit_value = NULL;
- tmp_threshold = alu_sched->threshold_fn;
- if (!tmp_threshold) {
- alu_sched->threshold_fn = _threshold_fn;
- }
- else {
- while (tmp_threshold->next) {
- tmp_threshold = tmp_threshold->next;
- }
- tmp_threshold->next = _threshold_fn;
- }
-
- } else {
- gf_log ("alu", GF_LOG_DEBUG,
- "%s, unknown option provided to scheduler",
- order_str);
- }
- order_str = strtok_r (NULL, ":", &tmp_str);
- }
-
- return 0;
-}
-
-static int32_t
-alu_init (xlator_t *xl)
-{
- struct alu_sched *alu_sched = NULL;
- struct alu_limits *_limit_fn = NULL;
- struct alu_limits *tmp_limits = NULL;
- uint32_t min_free_disk = 0;
- data_t *limits = NULL;
-
- alu_sched = GF_CALLOC (1, sizeof (struct alu_sched),
- gf_alu_mt_alu_sched);
- ERR_ABORT (alu_sched);
-
- {
- alu_parse_options (xl, alu_sched);
- }
-
- /* Get the limits */
-
- limits = dict_get (xl->options,
- "scheduler.limits.min-free-disk");
- if (limits) {
- _limit_fn = GF_CALLOC (1, sizeof (struct alu_limits),
- gf_alu_mt_alu_limits);
- ERR_ABORT (_limit_fn);
- _limit_fn->min_value = get_stats_free_disk;
- _limit_fn->cur_value = get_stats_free_disk;
- tmp_limits = alu_sched->limits_fn ;
- _limit_fn->next = tmp_limits;
- alu_sched->limits_fn = _limit_fn;
-
- if (gf_string2percent (limits->data,
- &min_free_disk) != 0) {
- gf_log ("alu", GF_LOG_ERROR,
- "invalid number format \"%s\" "
- "of \"option scheduler.limits."
- "min-free-disk\"", limits->data);
- return -1;
- }
- alu_sched->spec_limit.free_disk = min_free_disk;
-
- if (alu_sched->spec_limit.free_disk >= 100) {
- gf_log ("alu", GF_LOG_ERROR,
- "check the \"option scheduler."
- "limits.min-free-disk\", it should "
- "be percentage value");
- return -1;
- }
- alu_sched->spec_limit.total_disk_size = ALU_LIMITS_TOTAL_DISK_SIZE_DEFAULT; /* Its in % */
- gf_log ("alu", GF_LOG_DEBUG,
- "alu.limit.min-disk-free = %"PRId64"",
- _limit_fn->cur_value (&(alu_sched->spec_limit)));
- }
-
- limits = dict_get (xl->options,
- "scheduler.limits.max-open-files");
- if (limits) {
- // Update alu_sched->priority properly
- _limit_fn = GF_CALLOC (1, sizeof (struct alu_limits),
- gf_alu_mt_alu_limits);
- ERR_ABORT (_limit_fn);
- _limit_fn->max_value = get_stats_file_usage;
- _limit_fn->cur_value = get_stats_file_usage;
- tmp_limits = alu_sched->limits_fn ;
- _limit_fn->next = tmp_limits;
- alu_sched->limits_fn = _limit_fn;
- if (gf_string2uint64_base10 (limits->data,
- &alu_sched->spec_limit.nr_files) != 0)
- {
- gf_log ("alu", GF_LOG_ERROR,
- "invalid number format '%s' of option "
- "scheduler.limits.max-open-files",
- limits->data);
- return -1;
- }
-
- gf_log ("alu", GF_LOG_DEBUG,
- "alu_init: limit.max-open-files = %"PRId64"",
- _limit_fn->cur_value (&(alu_sched->spec_limit)));
- }
-
-
- /* Stats refresh options */
- limits = dict_get (xl->options,
- "scheduler.refresh-interval");
- if (limits) {
- if (gf_string2time (limits->data,
- &alu_sched->refresh_interval) != 0) {
- gf_log ("alu", GF_LOG_ERROR,
- "invalid number format \"%s\" of "
- "option scheduler.refresh-interval",
- limits->data);
- return -1;
- }
- } else {
- alu_sched->refresh_interval = ALU_REFRESH_INTERVAL_DEFAULT;
- }
- gettimeofday (&(alu_sched->last_stat_fetch), NULL);
-
-
- limits = dict_get (xl->options,
- "scheduler.alu.stat-refresh.num-file-create");
- if (limits) {
- if (gf_string2uint32 (limits->data,
- &alu_sched->refresh_create_count) != 0)
- {
- gf_log ("alu", GF_LOG_ERROR,
- "invalid number format \"%s\" of \"option "
- "alu.stat-refresh.num-file-create\"",
- limits->data);
- return -1;
- }
- } else {
- alu_sched->refresh_create_count = ALU_REFRESH_CREATE_COUNT_DEFAULT;
- }
-
- {
- /* Build an array of child_nodes */
- struct alu_sched_struct *sched_array = NULL;
- xlator_list_t *trav_xl = xl->children;
- data_t *data = NULL;
- int32_t index = 0;
-
- while (trav_xl) {
- index++;
- trav_xl = trav_xl->next;
- }
- alu_sched->child_count = index;
- sched_array = GF_CALLOC (index, sizeof (struct alu_sched_struct), gf_alu_mt_alu_sched_struct);
- ERR_ABORT (sched_array);
- trav_xl = xl->children;
- index = 0;
- while (trav_xl) {
- sched_array[index].xl = trav_xl->xlator;
- sched_array[index].eligible = 1;
- index++;
- trav_xl = trav_xl->next;
- }
- alu_sched->array = sched_array;
-
- data = dict_get (xl->options,
- "scheduler.read-only-subvolumes");
- if (data) {
- char *child = NULL;
- char *tmp = NULL;
- char *childs_data = gf_strdup (data->data);
-
- child = strtok_r (childs_data, ",", &tmp);
- while (child) {
- for (index = 1; index < alu_sched->child_count; index++) {
- if (strcmp (alu_sched->array[index -1].xl->name, child) == 0) {
- memcpy (&(alu_sched->array[index -1]),
- &(alu_sched->array[alu_sched->child_count -1]),
- sizeof (struct alu_sched_struct));
- alu_sched->child_count--;
- break;
- }
- }
- child = strtok_r (NULL, ",", &tmp);
- }
- }
- }
-
- *((long *)xl->private) = (long)alu_sched;
-
- /* Initialize all the alu_sched structure's elements */
- {
- alu_sched->sched_nodes_pending = 0;
-
- alu_sched->min_limit.free_disk = 0x00FFFFFF;
- alu_sched->min_limit.disk_usage = 0xFFFFFFFF;
- alu_sched->min_limit.total_disk_size = 0xFFFFFFFF;
- alu_sched->min_limit.disk_speed = 0xFFFFFFFF;
- alu_sched->min_limit.write_usage = 0xFFFFFFFF;
- alu_sched->min_limit.read_usage = 0xFFFFFFFF;
- alu_sched->min_limit.nr_files = 0xFFFFFFFF;
- alu_sched->min_limit.nr_clients = 0xFFFFFFFF;
- }
-
- pthread_mutex_init (&alu_sched->alu_mutex, NULL);
- return 0;
-}
-
-static void
-alu_fini (xlator_t *xl)
-{
- if (!xl)
- return;
- struct alu_sched *alu_sched = (struct alu_sched *)*((long *)xl->private);
- struct alu_limits *limit = alu_sched->limits_fn;
- struct alu_threshold *threshold = alu_sched->threshold_fn;
- void *tmp = NULL;
- pthread_mutex_destroy (&alu_sched->alu_mutex);
- GF_FREE (alu_sched->array);
- while (limit) {
- tmp = limit;
- limit = limit->next;
- GF_FREE (tmp);
- }
- while (threshold) {
- tmp = threshold;
- threshold = threshold->next;
- GF_FREE (tmp);
- }
- GF_FREE (alu_sched);
-}
-
-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)
-{
- struct alu_sched *alu_sched = (struct alu_sched *)*((long *)xl->private);
- struct alu_limits *limits_fn = alu_sched->limits_fn;
- int32_t idx = 0;
-
- pthread_mutex_lock (&alu_sched->alu_mutex);
- for (idx = 0; idx < alu_sched->child_count; idx++) {
- if (alu_sched->array[idx].xl == (xlator_t *)cookie)
- break;
- }
- pthread_mutex_unlock (&alu_sched->alu_mutex);
-
- if (op_ret == -1) {
- alu_sched->array[idx].eligible = 0;
- } else {
- memcpy (&(alu_sched->array[idx].stats), trav_stats, sizeof (struct xlator_stats));
-
- /* Get stats from all the child node */
- /* Here check the limits specified by the user to
- consider the nodes to be used by scheduler */
- alu_sched->array[idx].eligible = 1;
- limits_fn = alu_sched->limits_fn;
- while (limits_fn){
- if (limits_fn->max_value &&
- (limits_fn->cur_value (trav_stats) >
- limits_fn->max_value (&(alu_sched->spec_limit)))) {
- alu_sched->array[idx].eligible = 0;
- }
- if (limits_fn->min_value &&
- (limits_fn->cur_value (trav_stats) <
- limits_fn->min_value (&(alu_sched->spec_limit)))) {
- alu_sched->array[idx].eligible = 0;
- }
- limits_fn = limits_fn->next;
- }
-
- /* Select minimum and maximum disk_usage */
- if (trav_stats->disk_usage > alu_sched->max_limit.disk_usage) {
- alu_sched->max_limit.disk_usage = trav_stats->disk_usage;
- }
- if (trav_stats->disk_usage < alu_sched->min_limit.disk_usage) {
- alu_sched->min_limit.disk_usage = trav_stats->disk_usage;
- }
-
- /* Select minimum and maximum disk_speed */
- if (trav_stats->disk_speed > alu_sched->max_limit.disk_speed) {
- alu_sched->max_limit.disk_speed = trav_stats->disk_speed;
- }
- if (trav_stats->disk_speed < alu_sched->min_limit.disk_speed) {
- alu_sched->min_limit.disk_speed = trav_stats->disk_speed;
- }
-
- /* Select minimum and maximum number of open files */
- if (trav_stats->nr_files > alu_sched->max_limit.nr_files) {
- alu_sched->max_limit.nr_files = trav_stats->nr_files;
- }
- if (trav_stats->nr_files < alu_sched->min_limit.nr_files) {
- alu_sched->min_limit.nr_files = trav_stats->nr_files;
- }
-
- /* Select minimum and maximum write-usage */
- if (trav_stats->write_usage > alu_sched->max_limit.write_usage) {
- alu_sched->max_limit.write_usage = trav_stats->write_usage;
- }
- if (trav_stats->write_usage < alu_sched->min_limit.write_usage) {
- alu_sched->min_limit.write_usage = trav_stats->write_usage;
- }
-
- /* Select minimum and maximum read-usage */
- if (trav_stats->read_usage > alu_sched->max_limit.read_usage) {
- alu_sched->max_limit.read_usage = trav_stats->read_usage;
- }
- if (trav_stats->read_usage < alu_sched->min_limit.read_usage) {
- alu_sched->min_limit.read_usage = trav_stats->read_usage;
- }
-
- /* Select minimum and maximum free-disk */
- if (trav_stats->free_disk > alu_sched->max_limit.free_disk) {
- alu_sched->max_limit.free_disk = trav_stats->free_disk;
- }
- if (trav_stats->free_disk < alu_sched->min_limit.free_disk) {
- alu_sched->min_limit.free_disk = trav_stats->free_disk;
- }
- }
-
- STACK_DESTROY (frame->root);
-
- return 0;
-}
-
-static void
-update_stat_array (xlator_t *xl)
-{
- /* This function schedules the file in one of the child nodes */
- struct alu_sched *alu_sched = (struct alu_sched *)*((long *)xl->private);
- int32_t idx = 0;
- call_frame_t *frame = NULL;
- call_pool_t *pool = xl->ctx->pool;
-
- for (idx = 0 ; idx < alu_sched->child_count; idx++) {
- frame = create_frame (xl, pool);
-
- STACK_WIND_COOKIE (frame,
- update_stat_array_cbk,
- alu_sched->array[idx].xl, //cookie
- alu_sched->array[idx].xl,
- (alu_sched->array[idx].xl)->mops->stats,
- 0); //flag
- }
- return;
-}
-
-static void
-alu_update (xlator_t *xl)
-{
- struct timeval tv;
- struct alu_sched *alu_sched = (struct alu_sched *)*((long *)xl->private);
-
- gettimeofday (&tv, NULL);
- if (tv.tv_sec > (alu_sched->refresh_interval + alu_sched->last_stat_fetch.tv_sec)) {
- /* Update the stats from all the server */
- update_stat_array (xl);
- alu_sched->last_stat_fetch.tv_sec = tv.tv_sec;
- }
-}
-
-static xlator_t *
-alu_scheduler (xlator_t *xl, const void *path)
-{
- /* This function schedules the file in one of the child nodes */
- struct alu_sched *alu_sched = (struct alu_sched *)*((long *)xl->private);
- int32_t sched_index = 0;
- int32_t sched_index_orig = 0;
- int32_t idx = 0;
-
- alu_update (xl);
-
- /* Now check each threshold one by one if some nodes are classified */
- {
- struct alu_threshold *trav_threshold = alu_sched->threshold_fn;
- struct alu_threshold *tmp_threshold = alu_sched->sched_method;
- struct alu_sched_node *tmp_sched_node;
-
- /* This pointer 'trav_threshold' contains function pointers according to spec file
- give by user, */
- while (trav_threshold) {
- /* This check is needed for seeing if already there are nodes in this criteria
- to be scheduled */
- if (!alu_sched->sched_nodes_pending) {
- for (idx = 0; idx < alu_sched->child_count; idx++) {
- if (!alu_sched->array[idx].eligible) {
- continue;
- }
- if (trav_threshold->entry_value) {
- if (trav_threshold->diff_value (&(alu_sched->max_limit),
- &(alu_sched->array[idx].stats)) <
- trav_threshold->entry_value (&(alu_sched->entry_limit))) {
- continue;
- }
- }
- tmp_sched_node = GF_CALLOC (1, sizeof (struct alu_sched_node), gf_alu_mt_alu_sched_node);
- ERR_ABORT (tmp_sched_node);
- tmp_sched_node->index = idx;
- if (!alu_sched->sched_node) {
- alu_sched->sched_node = tmp_sched_node;
- } else {
- pthread_mutex_lock (&alu_sched->alu_mutex);
- tmp_sched_node->next = alu_sched->sched_node;
- alu_sched->sched_node = tmp_sched_node;
- pthread_mutex_unlock (&alu_sched->alu_mutex);
- }
- alu_sched->sched_nodes_pending++;
- }
- } /* end of if (sched_nodes_pending) */
-
- /* This loop is required to check the eligible nodes */
- struct alu_sched_node *trav_sched_node;
- while (alu_sched->sched_nodes_pending) {
- trav_sched_node = alu_sched->sched_node;
- sched_index = trav_sched_node->index;
- if (alu_sched->array[sched_index].eligible)
- break;
- alu_sched->sched_node = trav_sched_node->next;
- GF_FREE (trav_sched_node);
- alu_sched->sched_nodes_pending--;
- }
- if (alu_sched->sched_nodes_pending) {
- /* There are some node in this criteria to be scheduled, no need
- * to sort and check other methods
- */
- if (tmp_threshold && tmp_threshold->exit_value) {
- /* verify the exit value && whether node is eligible or not */
- if (tmp_threshold->diff_value (&(alu_sched->max_limit),
- &(alu_sched->array[sched_index].stats)) >
- tmp_threshold->exit_value (&(alu_sched->exit_limit))) {
- /* Free the allocated info for the node :) */
- pthread_mutex_lock (&alu_sched->alu_mutex);
- alu_sched->sched_node = trav_sched_node->next;
- GF_FREE (trav_sched_node);
- trav_sched_node = alu_sched->sched_node;
- alu_sched->sched_nodes_pending--;
- pthread_mutex_unlock (&alu_sched->alu_mutex);
- }
- } else {
- /* if there is no exit value, then exit after scheduling once */
- pthread_mutex_lock (&alu_sched->alu_mutex);
- alu_sched->sched_node = trav_sched_node->next;
- GF_FREE (trav_sched_node);
- trav_sched_node = alu_sched->sched_node;
- alu_sched->sched_nodes_pending--;
- pthread_mutex_unlock (&alu_sched->alu_mutex);
- }
-
- alu_sched->sched_method = tmp_threshold; /* this is the method used for selecting */
-
- /* */
- if (trav_sched_node) {
- tmp_sched_node = trav_sched_node;
- while (trav_sched_node->next) {
- trav_sched_node = trav_sched_node->next;
- }
- if (tmp_sched_node->next) {
- pthread_mutex_lock (&alu_sched->alu_mutex);
- alu_sched->sched_node = tmp_sched_node->next;
- tmp_sched_node->next = NULL;
- trav_sched_node->next = tmp_sched_node;
- pthread_mutex_unlock (&alu_sched->alu_mutex);
- }
- }
- /* return the scheduled node */
- return alu_sched->array[sched_index].xl;
- } /* end of if (pending_nodes) */
-
- tmp_threshold = trav_threshold;
- trav_threshold = trav_threshold->next;
- }
- }
-
- /* This is used only when there is everything seems ok, or no eligible nodes */
- sched_index_orig = alu_sched->sched_index;
- alu_sched->sched_method = NULL;
- while (1) {
- //lock
- pthread_mutex_lock (&alu_sched->alu_mutex);
- sched_index = alu_sched->sched_index++;
- alu_sched->sched_index = alu_sched->sched_index % alu_sched->child_count;
- pthread_mutex_unlock (&alu_sched->alu_mutex);
- //unlock
- if (alu_sched->array[sched_index].eligible)
- break;
- if (sched_index_orig == (sched_index + 1) % alu_sched->child_count) {
- gf_log ("alu", GF_LOG_WARNING, "No node is eligible to schedule");
- //lock
- pthread_mutex_lock (&alu_sched->alu_mutex);
- alu_sched->sched_index++;
- alu_sched->sched_index = alu_sched->sched_index % alu_sched->child_count;
- pthread_mutex_unlock (&alu_sched->alu_mutex);
- //unlock
- break;
- }
- }
- return alu_sched->array[sched_index].xl;
-}
-
-/**
- * notify
- */
-void
-alu_notify (xlator_t *xl, int32_t event, void *data)
-{
- struct alu_sched *alu_sched = NULL;
- int32_t idx = 0;
-
- alu_sched = (struct alu_sched *)*((long *)xl->private);
- if (!alu_sched)
- return;
-
- for (idx = 0; idx < alu_sched->child_count; idx++) {
- if (alu_sched->array[idx].xl == (xlator_t *)data)
- break;
- }
-
- switch (event)
- {
- case GF_EVENT_CHILD_UP:
- {
- //alu_sched->array[idx].eligible = 1;
- }
- break;
- case GF_EVENT_CHILD_DOWN:
- {
- alu_sched->array[idx].eligible = 0;
- }
- break;
- default:
- {
- ;
- }
- break;
- }
-
-}
-
-int32_t
-alu_mem_acct_init (xlator_t *this)
-{
- int ret = -1;
-
- if (!this)
- return ret;
-
- ret = xlator_mem_acct_init (this, gf_alu_mt_end + 1);
-
- if (ret != 0) {
- gf_log (this->name, GF_LOG_ERROR, "Memory accounting init"
- "failed");
- return ret;
- }
-
- return ret;
-}
-
-struct sched_ops sched = {
- .init = alu_init,
- .fini = alu_fini,
- .update = alu_update,
- .schedule = alu_scheduler,
- .notify = alu_notify,
- .mem_acct_init = alu_mem_acct_init,
-};
-
-struct volume_options options[] = {
- { .key = { "scheduler.alu.order", "alu.order" },
- .type = GF_OPTION_TYPE_ANY
- },
- { .key = { "scheduler.alu.disk-usage.entry-threshold",
- "alu.disk-usage.entry-threshold" },
- .type = GF_OPTION_TYPE_SIZET
- },
- { .key = { "scheduler.alu.disk-usage.exit-threshold",
- "alu.disk-usage.exit-threshold" },
- .type = GF_OPTION_TYPE_SIZET
- },
- { .key = { "scheduler.alu.write-usage.entry-threshold",
- "alu.write-usage.entry-threshold" },
- .type = GF_OPTION_TYPE_SIZET
- },
- { .key = { "scheduler.alu.write-usage.exit-threshold",
- "alu.write-usage.exit-threshold" },
- .type = GF_OPTION_TYPE_SIZET
- },
- { .key = { "scheduler.alu.read-usage.entry-threshold",
- "alu.read-usage.entry-threshold" },
- .type = GF_OPTION_TYPE_SIZET
- },
- { .key = { "scheduler.alu.read-usage.exit-threshold",
- "alu.read-usage.exit-threshold" },
- .type = GF_OPTION_TYPE_SIZET
- },
- { .key = { "scheduler.alu.open-files-usage.entry-threshold",
- "alu.open-files-usage.entry-threshold" },
- .type = GF_OPTION_TYPE_INT
- },
- { .key = { "scheduler.alu.open-files-usage.exit-threshold",
- "alu.open-files-usage.exit-threshold" },
- .type = GF_OPTION_TYPE_INT
- },
- { .key = { "scheduler.read-only-subvolumes",
- "alu.read-only-subvolumes" },
- .type = GF_OPTION_TYPE_ANY
- },
- { .key = { "scheduler.refresh-interval",
- "alu.refresh-interval",
- "alu.stat-refresh.interval" },
- .type = GF_OPTION_TYPE_TIME
- },
- { .key = { "scheduler.limits.min-free-disk",
- "alu.limits.min-free-disk" },
- .type = GF_OPTION_TYPE_PERCENT
- },
- { .key = { "scheduler.alu.stat-refresh.num-file-create"
- "alu.stat-refresh.num-file-create"},
- .type = GF_OPTION_TYPE_INT
- },
- { .key = {NULL}, }
-};