From 2c99bb99bc57d728fe93c17d0378fd13bcf69dd8 Mon Sep 17 00:00:00 2001 From: Danny Auble <da@llnl.gov> Date: Fri, 1 May 2009 19:14:09 +0000 Subject: [PATCH] added support for classification in a cluster. This doesn't work with sacctmgr yet. it should be easy to add --- src/common/parse_spec.c | 37 +++-------- src/common/slurm_accounting_storage.c | 63 +++++++++++++++++++ src/common/slurm_accounting_storage.h | 17 ++++- .../mysql/accounting_storage_mysql.c | 35 ++++++++--- 4 files changed, 114 insertions(+), 38 deletions(-) diff --git a/src/common/parse_spec.c b/src/common/parse_spec.c index 5989b01adfb..e559d39f7bb 100644 --- a/src/common/parse_spec.c +++ b/src/common/parse_spec.c @@ -41,6 +41,10 @@ # include "config.h" #endif +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -60,7 +64,6 @@ static int _load_long (long *destination, char *keyword, char *in_line) ; static int _load_integer (int *destination, char *keyword, char *in_line) ; static int _load_float (float *destination, char *keyword, char *in_line) ; -static char *_strcasestr(char *haystack, char *needle); /* * slurm_parser - parse the supplied specification into keyword/value pairs @@ -137,7 +140,7 @@ _load_float (float *destination, char *keyword, char *in_line) char *str_ptr1, *str_ptr2, *str_ptr3; int i, str_len1, str_len2; - str_ptr1 = (char *) _strcasestr (in_line, keyword); + str_ptr1 = (char *) strcasestr (in_line, keyword); if (str_ptr1 != NULL) { str_len1 = strlen (keyword); strcpy (scratch, str_ptr1 + str_len1); @@ -175,7 +178,7 @@ _load_integer (int *destination, char *keyword, char *in_line) char *str_ptr1, *str_ptr2, *str_ptr3; int i, str_len1, str_len2; - str_ptr1 = (char *) _strcasestr (in_line, keyword); + str_ptr1 = (char *) strcasestr (in_line, keyword); if (str_ptr1 != NULL) { str_len1 = strlen (keyword); strcpy (scratch, str_ptr1 + str_len1); @@ -232,7 +235,7 @@ _load_long (long *destination, char *keyword, char *in_line) char *str_ptr1, *str_ptr2, *str_ptr3; int i, str_len1, str_len2; - str_ptr1 = (char *) _strcasestr (in_line, keyword); + str_ptr1 = (char *) strcasestr (in_line, keyword); if (str_ptr1 != NULL) { str_len1 = strlen (keyword); strcpy (scratch, str_ptr1 + str_len1); @@ -290,7 +293,7 @@ load_string (char **destination, char *keyword, char *in_line) char *str_ptr1, *str_ptr2, *str_ptr3; int i, str_len1, str_len2; - str_ptr1 = (char *) _strcasestr (in_line, keyword); + str_ptr1 = (char *) strcasestr (in_line, keyword); if (str_ptr1 != NULL) { int quoted = 0; str_len1 = strlen (keyword); @@ -316,27 +319,3 @@ load_string (char **destination, char *keyword, char *in_line) } return 0; } - -/* case insensitve version of strstr() */ -static char * -_strcasestr(char *haystack, char *needle) -{ - int hay_inx, hay_size = strlen(haystack); - int need_inx, need_size = strlen(needle); - char *hay_ptr = haystack; - - for (hay_inx=0; hay_inx<hay_size; hay_inx++) { - for (need_inx=0; need_inx<need_size; need_inx++) { - if (tolower((int) hay_ptr[need_inx]) != - tolower((int) needle [need_inx])) - break; /* mis-match */ - } - - if (need_inx == need_size) /* it matched */ - return hay_ptr; - else /* keep looking */ - hay_ptr++; - } - - return NULL; /* no match anywhere in string */ -} diff --git a/src/common/slurm_accounting_storage.c b/src/common/slurm_accounting_storage.c index ff8c7c8f940..c31aab541ea 100644 --- a/src/common/slurm_accounting_storage.c +++ b/src/common/slurm_accounting_storage.c @@ -43,7 +43,12 @@ # include "config.h" #endif +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + #include <pthread.h> +#include <string.h> #include "src/common/list.h" #include "src/common/slurm_accounting_storage.h" @@ -1600,6 +1605,7 @@ extern void pack_acct_cluster_rec(void *in, uint16_t rpc_version, Buf buffer) if(rpc_version >= 5) { if(!object) { pack32(NO_VAL, buffer); + pack16(0, buffer); packnull(buffer); pack32(0, buffer); pack32(0, buffer); @@ -1628,6 +1634,7 @@ extern void pack_acct_cluster_rec(void *in, uint16_t rpc_version, Buf buffer) } count = NO_VAL; + pack16(object->classification, buffer); packstr(object->control_host, buffer); pack32(object->control_port, buffer); pack32(object->cpu_count, buffer); @@ -1757,6 +1764,7 @@ extern int unpack_acct_cluster_rec(void **object, uint16_t rpc_version, } } + safe_unpack16(&object_ptr->classification, buffer); safe_unpackstr_xmalloc(&object_ptr->control_host, &uint32_tmp, buffer); safe_unpack32(&object_ptr->control_port, buffer); @@ -3419,6 +3427,7 @@ extern void pack_acct_cluster_cond(void *in, uint16_t rpc_version, Buf buffer) if(rpc_version >= 5) { if(!object) { + pack16(0, buffer); pack32(NO_VAL, buffer); pack_time(0, buffer); pack_time(0, buffer); @@ -3426,6 +3435,8 @@ extern void pack_acct_cluster_cond(void *in, uint16_t rpc_version, Buf buffer) pack16(0, buffer); return; } + + pack16(object->classification, buffer); if(object->cluster_list) count = list_count(object->cluster_list); @@ -3490,6 +3501,7 @@ extern int unpack_acct_cluster_cond(void **object, uint16_t rpc_version, *object = object_ptr; if(rpc_version >= 5) { + safe_unpack16(&object_ptr->classification, buffer); safe_unpack32(&count, buffer); if(count && count != NO_VAL) { object_ptr->cluster_list = @@ -7211,6 +7223,57 @@ extern char *get_qos_complete_str(List qos_list, List num_qos_list) return print_this; } +extern char *get_classification_str(uint16_t class) +{ + bool classified = class & ACCT_CLASSIFIED_FLAG; + acct_classification_type_t type = class & ACCT_CLASS_BASE; + + switch(type) { + case ACCT_CLASS_CAPACITY: + if(classified) + return "*Capacity"; + else + return "Capacity"; + break; + case ACCT_CLASS_CAPABILITY: + if(classified) + return "*Capability"; + else + return "Capability"; + break; + case ACCT_CLASS_CAPAPACITY: + if(classified) + return "*Capapacity"; + else + return "Capapacity"; + break; + default: + if(classified) + return "*Unknown"; + else + return "Unknown"; + break; + } +} + +extern uint16_t str_2_classification(char *class) +{ + uint16_t type = 0; + if(!class) + return type; + + if(strcasestr(class, "capac")) + type = ACCT_CLASS_CAPACITY; + else if(strcasestr(class, "capab")) + type = ACCT_CLASS_CAPABILITY; + else if(strcasestr(class, "capap")) + type = ACCT_CLASS_CAPAPACITY; + + if(strcasestr(class, "class")) + type |= ACCT_CLASSIFIED_FLAG; + + return type; +} extern void log_assoc_rec(acct_association_rec_t *assoc_ptr, List qos_list) { diff --git a/src/common/slurm_accounting_storage.h b/src/common/slurm_accounting_storage.h index 75df53de3f7..09a49134921 100644 --- a/src/common/slurm_accounting_storage.h +++ b/src/common/slurm_accounting_storage.h @@ -72,6 +72,17 @@ typedef enum { ACCT_MODIFY_WCKEY, } acct_update_type_t; +typedef enum { + ACCT_CLASS_NONE, /* no class given */ + ACCT_CLASS_CAPABILITY, /* capability cluster */ + ACCT_CLASS_CAPACITY, /* capacity cluster */ + ACCT_CLASS_CAPAPACITY, /* a cluster that is both capability + * and capacity */ +} acct_classification_type_t; + +#define ACCT_CLASSIFIED_FLAG 0x0100 +#define ACCT_CLASS_BASE 0x00ff + /* Association conditions used for queries of the database */ typedef struct { List acct_list; /* list of char * */ @@ -228,6 +239,7 @@ typedef struct acct_association_rec { } acct_association_rec_t; typedef struct { + uint16_t classification; /* how this machine is classified */ List cluster_list; /* list of char * */ time_t usage_end; time_t usage_start; @@ -237,13 +249,13 @@ typedef struct { typedef struct { List accounting_list; /* list of cluster_accounting_rec_t *'s */ + uint16_t classification; /* how this machine is classified */ char *control_host; uint32_t control_port; uint32_t cpu_count; char *name; char *nodes; acct_association_rec_t *root_assoc; /* root association for cluster */ - uint16_t rpc_version; /* version of rpc this cluter is running */ } acct_cluster_rec_t; @@ -658,6 +670,9 @@ extern char *get_tree_acct_name(char *name, char *parent, List tree_list); extern char *get_qos_complete_str(List qos_list, List num_qos_list); +extern char *get_classification_str(uint16_t class); +extern uint16_t str_2_classification(char *class); + extern void log_assoc_rec(acct_association_rec_t *assoc_ptr, List qos_list); extern int slurm_acct_storage_init(char *loc); /* load the plugin */ diff --git a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c index c9b6f9f8c46..daa0dada86b 100644 --- a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c +++ b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c @@ -2887,7 +2887,7 @@ static int _mysql_acct_check_tables(MYSQL *db_conn) { "control_host", "tinytext not null default ''" }, { "control_port", "mediumint not null default 0" }, { "rpc_version", "mediumint not null default 0" }, - { "classification", "tinyint unsigned default 0" }, + { "classification", "smallint unsigned default 0" }, { NULL, NULL} }; @@ -3983,21 +3983,23 @@ extern int acct_storage_p_add_clusters(mysql_conn_t *mysql_conn, uint32_t uid, continue; } - xstrcat(cols, "creation_time, mod_time, acct, cluster"); + xstrcat(cols, "creation_time, mod_time, acct, " + "cluster, classification"); xstrfmtcat(vals, "%d, %d, 'root', \"%s\"", - now, now, object->name); + now, now, object->name, object->classification); xstrfmtcat(extra, ", mod_time=%d", now); if(object->root_assoc) _setup_association_limits(object->root_assoc, &cols, &vals, &extra, QOS_LEVEL_SET, 1); xstrfmtcat(query, - "insert into %s (creation_time, mod_time, name) " - "values (%d, %d, \"%s\") " + "insert into %s (creation_time, mod_time, " + "name, classification) " + "values (%d, %d, \"%s\", %u) " "on duplicate key update deleted=0, mod_time=%d, " "control_host='', control_port=0;", cluster_table, - now, now, object->name, + now, now, object->name, object->classification, now); debug3("%d(%d) query\n%s", mysql_conn->conn, __LINE__, query); @@ -5130,6 +5132,7 @@ extern List acct_storage_p_modify_clusters(mysql_conn_t *mysql_conn, int set = 0; MYSQL_RES *result = NULL; MYSQL_ROW row; + bool clust_reg = false; /* If you need to alter the default values of the cluster use * modify_associations since this is used only for registering @@ -5160,20 +5163,33 @@ extern List acct_storage_p_modify_clusters(mysql_conn_t *mysql_conn, xstrcat(extra, ")"); } + if(cluster_cond->classification) { + xstrfmtcat(extra, " && (classification & %u)", + cluster_cond->classification); + } + set = 0; if(cluster->control_host) { xstrfmtcat(vals, ", control_host='%s'", cluster->control_host); set++; + clust_reg = true; } if(cluster->control_port) { xstrfmtcat(vals, ", control_port=%u", cluster->control_port); set++; + clust_reg = true; } if(cluster->rpc_version) { xstrfmtcat(vals, ", rpc_version=%u", cluster->rpc_version); set++; + clust_reg = true; + } + + if(cluster->classification) { + xstrfmtcat(vals, ", classification=%u", + cluster->classification); } if(!vals) { @@ -5181,7 +5197,7 @@ extern List acct_storage_p_modify_clusters(mysql_conn_t *mysql_conn, errno = SLURM_NO_CHANGE_IN_DATA; error("Nothing to change"); return NULL; - } else if(set != 3) { + } else if(clust_reg && (set != 3)) { xfree(vals); xfree(extra); errno = EFAULT; @@ -5215,7 +5231,7 @@ extern List acct_storage_p_modify_clusters(mysql_conn_t *mysql_conn, object = xstrdup(row[0]); /* check to see if this is the first time to register */ - if(row[1][0] == '0') + if(clust_reg && (row[1][0] == '0')) set = 0; list_append(ret_list, object); @@ -7945,12 +7961,14 @@ extern List acct_storage_p_get_clusters(mysql_conn_t *mysql_conn, uid_t uid, /* if this changes you will need to edit the corresponding enum */ char *cluster_req_inx[] = { "name", + "classification", "control_host", "control_port", "rpc_version", }; enum { CLUSTER_REQ_NAME, + CLUSTER_REQ_CLASS, CLUSTER_REQ_CH, CLUSTER_REQ_CP, CLUSTER_REQ_VERSION, @@ -8040,6 +8058,7 @@ empty: cluster_cond->usage_end); } + cluster->classification = atoi(row[CLUSTER_REQ_CLASS]); cluster->control_host = xstrdup(row[CLUSTER_REQ_CH]); cluster->control_port = atoi(row[CLUSTER_REQ_CP]); cluster->rpc_version = atoi(row[CLUSTER_REQ_VERSION]); -- GitLab