Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Use xbt/host module
[simgrid.git] / src / xbt / config.c
index 81c8fb4..1ab5aec 100644 (file)
@@ -9,14 +9,13 @@
 /* This program is free software; you can redistribute it and/or modify it
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
-#include <stdio.h> /* FIXME: killme */
-
 #include "xbt/misc.h"
 #include "xbt/sysdep.h"
 #include "xbt/log.h"
 #include "xbt/ex.h"
 #include "xbt/dynar.h"
 #include "xbt/dict.h"
+#include "xbt/host.h"
 
 #include "xbt/config.h" /* prototypes of this module */
 
@@ -54,13 +53,6 @@ static xbt_cfgelm_t xbt_cfgelm_get(xbt_cfg_t cfg, const char *name,
 static void xbt_cfg_str_free(void *d){
   free(*(void**)d);
 }
-static void xbt_cfg_host_free(void *d){
-  xbt_host_t *h=(xbt_host_t*) *(void**)d; 
-  if (h) {
-    if (h->name) free(h->name);
-    free(h);
-  }
-}
 
 /*----[ Memory management ]-----------------------------------------------*/
 
@@ -118,7 +110,7 @@ void xbt_cfg_dump(const char *name,const char *indent,xbt_cfg_t cfg) {
   int ival;
   char *sval;
   double dval;
-  xbt_host_t *hval;
+  xbt_host_t hval;
 
   if (name)
     printf("%s>> Dumping of the config set '%s':\n",indent,name);
@@ -157,7 +149,7 @@ void xbt_cfg_dump(const char *name,const char *indent,xbt_cfg_t cfg) {
 
     case xbt_cfgelm_host:
       for (i=0; i<size; i++) {
-       hval = xbt_dynar_get_as(variable->content,i,xbt_host_t*);
+       hval = xbt_dynar_get_as(variable->content,i,xbt_host_t);
        printf ("%s    %s:%d\n",indent,hval->name,hval->port);
       }
       break;
@@ -210,11 +202,12 @@ xbt_cfg_register(xbt_cfg_t cfg,
   xbt_assert4(type>=xbt_cfgelm_int && type<=xbt_cfgelm_host,
               "type of %s not valid (%d should be between %d and %d)",
               name,type,xbt_cfgelm_int, xbt_cfgelm_host);
-  DEBUG5("Register cfg elm %s (%d to %d %s (=%d))",name,min,max,xbt_cfgelm_type_name[type],type);
+  DEBUG5("Register cfg elm %s (%d to %d %s (=%d))",
+        name,min,max,xbt_cfgelm_type_name[type],type);
   TRY {
     res = xbt_dict_get((xbt_dict_t)cfg,name);
   } CATCH(e) {
-    if (e.category == mismatch_error) {
+    if (e.category == not_found_error) {
       found = 1;
       xbt_ex_free(e);
     } else {
@@ -249,7 +242,7 @@ xbt_cfg_register(xbt_cfg_t cfg,
    break;
 
   case xbt_cfgelm_host:
-   res->content = xbt_dynar_new(sizeof(xbt_host_t*),&xbt_cfg_host_free);
+   res->content = xbt_dynar_new(sizeof(xbt_host_t),&xbt_host_free_voidp);
    break;
 
   default:
@@ -265,11 +258,12 @@ xbt_cfg_register(xbt_cfg_t cfg,
  *  @arg name the name of the elem to be freed
  * 
  *  Note that it removes both the description and the actual content.
+ *  Throws not_found when no such element exists.
  */
 
-xbt_error_t
+void
 xbt_cfg_unregister(xbt_cfg_t cfg,const char *name) {
-  return xbt_dict_remove((xbt_dict_t)cfg,name);
+  xbt_dict_remove((xbt_dict_t)cfg,name);
 }
 
 /**
@@ -283,7 +277,7 @@ xbt_cfg_unregister(xbt_cfg_t cfg,const char *name) {
  * with type being one of  'string','int', 'host' or 'double'.
  */
 
-xbt_error_t
+void
 xbt_cfg_register_str(xbt_cfg_t cfg,const char *entry) {
   char *entrycpy=xbt_strdup(entry);
   char *tok;
@@ -292,66 +286,42 @@ xbt_cfg_register_str(xbt_cfg_t cfg,const char *entry) {
   e_xbt_cfgelm_type_t type;
 
   tok=strchr(entrycpy, ':');
-  if (!tok) {
-    ERROR3("%s%s%s",
-         "Invalid config element descriptor: ",entry,
-         "; Should be <name>:<min nb>_to_<max nb>_<type>");
-    free(entrycpy);
-    xbt_abort();
-  }
+  xbt_assert2(tok,"Invalid config element descriptor: %s%s",
+             entry,
+             "; Should be <name>:<min nb>_to_<max nb>_<type>");
   *(tok++)='\0';
 
   min=strtol(tok, &tok, 10);
-  if (!tok) {
-    ERROR1("Invalid minimum in config element descriptor %s",entry);
-    free(entrycpy);
-    xbt_abort();
-  }
+  xbt_assert1(tok,"Invalid minimum in config element descriptor %s",entry);
 
-  if (!strcmp(tok,"_to_")){
-    ERROR3("%s%s%s",
-         "Invalid config element descriptor: ",entry,
-         "; Should be <name>:<min nb>_to_<max nb>_<type>");
-    free(entrycpy);
-    xbt_abort();
-  }
+  xbt_assert2(strcmp(tok,"_to_"),
+             "Invalid config element descriptor : %s%s",           
+             entry,
+             "; Should be <name>:<min nb>_to_<max nb>_<type>");
   tok += strlen("_to_");
 
   max=strtol(tok, &tok, 10);
-  if (!tok) {
-    ERROR1("Invalid maximum in config element descriptor %s",entry);
-    free(entrycpy);
-    xbt_abort();
-  }
+  xbt_assert1(tok,"Invalid maximum in config element descriptor %s",entry);
 
-  if (*(tok++)!='_') {
-    ERROR3("%s%s%s",
-         "Invalid config element descriptor: ",entry,
-         "; Should be <name>:<min nb>_to_<max nb>_<type>");
-    free(entrycpy);
-    xbt_abort();
-  }
+  xbt_assert2( *(tok++) =='_',
+              "Invalid config element descriptor: %s%s",entry,
+              "; Should be <name>:<min nb>_to_<max nb>_<type>");
 
   for (type=0; 
        type<xbt_cfgelm_type_count && strcmp(tok,xbt_cfgelm_type_name[type]); 
        type++);
-  if (type == xbt_cfgelm_type_count) {
-    ERROR3("%s%s%s",
-         "Invalid type in config element descriptor: ",entry,
+  xbt_assert2(type < xbt_cfgelm_type_count,
+         "Invalid type in config element descriptor: %s%s",entry,
          "; Should be one of 'string', 'int', 'host' or 'double'.");
-    free(entrycpy);
-    xbt_abort();
-  }
 
   xbt_cfg_register(cfg,entrycpy,type,min,max,NULL,NULL);
 
   free(entrycpy); /* strdup'ed by dict mechanism, but cannot be const */
-  return no_error;
 }
 
 /** @brief Check that each variable have the right amount of values */
 
-xbt_error_t
+void
 xbt_cfg_check(xbt_cfg_t cfg) {
   xbt_dict_cursor_t cursor; 
   xbt_cfgelm_t variable;
@@ -363,44 +333,42 @@ xbt_cfg_check(xbt_cfg_t cfg) {
   xbt_dict_foreach((xbt_dict_t)cfg,cursor,name,variable) {
     size = xbt_dynar_length(variable->content);
     if (variable->min > size) { 
-      ERROR4("Config elem %s needs at least %d %s, but there is only %d values.",
+      xbt_dict_cursor_free(&cursor);
+      THROW4(mismatch_error,0,
+            "Config elem %s needs at least %d %s, but there is only %d values.",
             name,
             variable->min,
             xbt_cfgelm_type_name[variable->type],
             size); 
-      xbt_dict_cursor_free(&cursor);
-      return mismatch_error;
     }
 
     if (variable->max > 0 && variable->max < size) {
-      ERROR4("Config elem %s accepts at most %d %s, but there is %d values.",
+      xbt_dict_cursor_free(&cursor);
+      THROW4(mismatch_error,0,
+            "Config elem %s accepts at most %d %s, but there is %d values.",
             name,
             variable->max,
             xbt_cfgelm_type_name[variable->type],
             size);
-      xbt_dict_cursor_free(&cursor);
-      return mismatch_error;
     }
-
   }
 
   xbt_dict_cursor_free(&cursor);
-  return no_error;
 }
 
 static xbt_cfgelm_t xbt_cfgelm_get(xbt_cfg_t  cfg,
                                   const char *name,
                                   e_xbt_cfgelm_type_t type){
-  xbt_cfgelm_t res;
+  xbt_cfgelm_t res=NULL;
   xbt_ex_t e;
 
   TRY {
     res = xbt_dict_get((xbt_dict_t)cfg,name);
   } CATCH(e) {
-    if (e.category == mismatch_error) {
-      THROW1(mismatch_error,0,
-            "No registered variable '%s' in this config set",name);
+    if (e.category == not_found_error) {
       xbt_ex_free(e);
+      THROW1(not_found_error,0,
+            "No registered variable '%s' in this config set",name);
     }
     RETHROW;
   }
@@ -431,10 +399,10 @@ xbt_cfg_get_type(xbt_cfg_t cfg, const char *name) {
   TRY {
     variable = xbt_dict_get((xbt_dict_t)cfg,name);
   } CATCH(e) {
-    if (e.category == mismatch_error) {
-      THROW1(mismatch_error,0,
-            "Can't get the type of '%s' since this variable does not exist",name);
+    if (e.category == not_found_error) { 
       xbt_ex_free(e);
+      THROW1(not_found_error,0,
+            "Can't get the type of '%s' since this variable does not exist",name);
     }
     RETHROW;
   }
@@ -458,16 +426,16 @@ xbt_cfg_set_vargs(xbt_cfg_t cfg, const char *name, va_list pa) {
   char *str;
   int i;
   double d;
-  e_xbt_cfgelm_type_t type;
+  e_xbt_cfgelm_type_t type=0; /* Set a dummy value to make gcc happy. It cannot get uninitialized */
 
   xbt_ex_t e;
   
   TRY {
     type = xbt_cfg_get_type(cfg,name);
   } CATCH(e) {
-    if (e.category == mismatch_error) {
+    if (e.category == not_found_error) {
       xbt_ex_free(e);
-      THROW1(mismatch_error,0,"Can't set the property '%s' since it's not registered",name);
+      THROW1(not_found_error,0,"Can't set the property '%s' since it's not registered",name);
     }
     RETHROW;
   }
@@ -534,7 +502,7 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) {
   double d;
   char *str;
 
-  xbt_cfgelm_t variable;
+  xbt_cfgelm_t variable=NULL;
   char *optionlist_cpy;
   char *option,  *name,*val;
 
@@ -567,8 +535,8 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) {
       option=NULL; /* don't do next iteration */
 
     } else {
-      DEBUG3("Boundary on '%c'. len=%d;option-name=%d",
-            *option,len,option-name);
+      DEBUG3("Boundary on '%c'. len=%d;option-name=%ld",
+            *option,len,(long)(option-name));
 
       /* Pass the following blank chars */
       *(option++)='\0';
@@ -591,7 +559,7 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) {
     if (!val) {
       free(optionlist_cpy);
       xbt_assert1(FALSE,
-            "Malformated option: '%s'; Should be of the form 'name:value'",
+            "Option '%s' badly formated. Should be of the form 'name:value'",
                  name);
     }
     *(val++)='\0';
@@ -601,10 +569,12 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) {
     TRY {
       variable = xbt_dict_get((xbt_dict_t)cfg,name);
     } CATCH(e) {
+      /* put it back on what won't get freed, ie within "options" and out of "optionlist_cpy" */
+      name = (char*) (optionlist_cpy-name + options); 
       free(optionlist_cpy);
-      if (e.category == mismatch_error) {
+      if (e.category == not_found_error) {
        xbt_ex_free(e);
-       THROW1(mismatch_error,0,"No registrated variable corresponding to '%s'.",name);
+       THROW1(not_found_error,0,"No registrated variable corresponding to '%s'.",name);
       }
       RETHROW;
     }
@@ -784,13 +754,10 @@ void
 xbt_cfg_set_host(xbt_cfg_t cfg,const char*name, 
                  const char *host,int port) {
   xbt_cfgelm_t variable;
-  xbt_host_t *val=xbt_new(xbt_host_t,1);
+  xbt_host_t val=xbt_host_new(host,port);
 
   VERB3("Configuration setting: %s=%s:%d",name,host,port);
 
-  val->name = xbt_strdup(name);
-  val->port = port;
-
   variable = xbt_cfgelm_get(cfg,name,xbt_cfgelm_host);
 
   if (variable->max == 1) {
@@ -839,7 +806,7 @@ void xbt_cfg_rm_int(xbt_cfg_t cfg,const char*name, int val) {
     }
   }
 
-  THROW2(mismatch_error,0,
+  THROW2(not_found_error,0,
         "Can't remove the value %d of config element %s: value not found.",val,name);
 }
 
@@ -871,7 +838,7 @@ void xbt_cfg_rm_double(xbt_cfg_t cfg,const char*name, double val) {
     }
   }
 
-  THROW2(mismatch_error,0,
+  THROW2(not_found_error,0,
         "Can't remove the value %f of config element %s: value not found.",val,name);
 }
 
@@ -903,7 +870,7 @@ xbt_cfg_rm_string(xbt_cfg_t cfg,const char*name, const char *val) {
     }
   }
 
-  THROW2(mismatch_error,0,
+  THROW2(not_found_error,0,
         "Can't remove the value %s of config element %s: value not found.",val,name);
 }
 
@@ -919,7 +886,7 @@ void
 xbt_cfg_rm_host(xbt_cfg_t cfg,const char*name, const char *host,int port) {
   xbt_cfgelm_t variable;
   int cpt;
-  xbt_host_t *seen;
+  xbt_host_t seen;
 
   variable = xbt_cfgelm_get(cfg,name,xbt_cfgelm_host);
   
@@ -936,7 +903,7 @@ xbt_cfg_rm_host(xbt_cfg_t cfg,const char*name, const char *host,int port) {
     }
   }
 
-  THROW3(mismatch_error,0,
+  THROW3(not_found_error,0,
         "Can't remove the value %s:%d of config element %s: value not found.",
         host,port,name);
 }
@@ -966,18 +933,18 @@ void xbt_cfg_rm_at   (xbt_cfg_t cfg, const char *name, int pos) {
 
 void
 xbt_cfg_empty(xbt_cfg_t cfg,const char*name) {
-  xbt_cfgelm_t variable;
+  xbt_cfgelm_t variable=NULL;
   xbt_ex_t e;
 
   TRY {
     variable = xbt_dict_get((xbt_dict_t)cfg,name);
   } CATCH(e) {
-    if (e.category == mismatch_error) {
-      xbt_ex_free(e);
-      THROW1(mismatch_error,0,
-            "Can't empty  '%s' since this config element does not exist", name);
-    }
-    RETHROW;
+    if (e.category != not_found_error)
+      RETHROW;
+
+    xbt_ex_free(e);
+    THROW1(not_found_error,0,
+          "Can't empty  '%s' since this config element does not exist", name);
   }
 
   if (variable) {
@@ -1084,7 +1051,7 @@ char* xbt_cfg_get_string(xbt_cfg_t  cfg, const char *name) {
 void xbt_cfg_get_host  (xbt_cfg_t   cfg,  const char *name,
                        char      **host, int        *port) {
   xbt_cfgelm_t variable;
-  xbt_host_t  *val;
+  xbt_host_t  val;
 
   variable = xbt_cfgelm_get(cfg,name,xbt_cfgelm_host);
 
@@ -1093,7 +1060,7 @@ void xbt_cfg_get_host  (xbt_cfg_t   cfg,  const char *name,
             name, xbt_dynar_length(variable->content));
   }
 
-  val = xbt_dynar_get_as(variable->content, 0, xbt_host_t*);
+  val = xbt_dynar_get_as(variable->content, 0, xbt_host_t);
   *host=val->name;
   *port=val->port;
 }
@@ -1109,15 +1076,15 @@ void xbt_cfg_get_host  (xbt_cfg_t   cfg,  const char *name,
  * \warning the returned value is the actual content of the config set
  */
 xbt_dynar_t xbt_cfg_get_dynar (xbt_cfg_t    cfg, const char *name) {
-  xbt_cfgelm_t variable;
+  xbt_cfgelm_t variable=NULL;
   xbt_ex_t     e;
 
   TRY {
     variable = xbt_dict_get((xbt_dict_t)cfg,name);
   } CATCH(e) {
-    if (e.category == mismatch_error) {
+    if (e.category == not_found_error) {
       xbt_ex_free(e);
-      THROW1(mismatch_error,0,
+      THROW1(not_found_error,0,
             "No registered variable %s in this config set",name);
     }
     RETHROW;
@@ -1158,8 +1125,131 @@ xbt_cfg_get_host_at(xbt_cfg_t cfg, const char *name, int pos,
                     char **host, int *port) {
                   
   xbt_cfgelm_t variable = xbt_cfgelm_get(cfg,name,xbt_cfgelm_int);
-  xbt_host_t *val = xbt_dynar_get_ptr(variable->content, pos);
+  xbt_host_t val = xbt_dynar_get_ptr(variable->content, pos);
 
   *port = val->port;
   *host = val->name;
 }
+
+
+#ifdef SIMGRID_TEST
+#include "xbt.h"
+#include "xbt/ex.h"
+
+XBT_TEST_SUITE("config","Configuration support");
+
+static xbt_cfg_t make_set(){
+  xbt_cfg_t set=NULL; 
+
+  set = xbt_cfg_new();
+  xbt_cfg_register_str(set,"speed:1_to_2_int");
+  xbt_cfg_register_str(set,"hostname:1_to_1_string");
+  xbt_cfg_register_str(set,"user:1_to_10_string");
+
+  return set;
+} /* end_of_make_set */
+
+XBT_TEST_UNIT("memuse",test_config_memuse,"Alloc and free a config set") {
+  xbt_cfg_t set=make_set();
+  xbt_test_add0("Alloc and free a config set");
+  xbt_cfg_set_parse(set, "hostname:veloce user:mquinson\nuser:oaumage\tuser:alegrand");
+  xbt_cfg_free(&set);
+  xbt_cfg_free(&set);
+}
+
+XBT_TEST_UNIT("validation",test_config_validation,"Validation tests") {
+  xbt_cfg_t set = set=make_set();
+  xbt_ex_t e;
+  
+  xbt_test_add0("Having too few elements for speed");
+  xbt_cfg_set_parse(set, "hostname:veloce user:mquinson\nuser:oaumage\tuser:alegrand");
+  TRY {
+    xbt_cfg_check(set);
+  } CATCH(e) {
+    if (e.category != mismatch_error || 
+       strncmp(e.msg,"Config elem speed needs",strlen("Config elem speed needs")))
+      xbt_test_fail1("Got an exception. msg=%s",e.msg);
+    xbt_ex_free(e);
+  }
+  xbt_cfg_free(&set);
+  xbt_cfg_free(&set);
+
+
+
+  xbt_test_add0("Having too much values of 'speed'");
+  set=make_set(); 
+  xbt_cfg_set_parse(set,"hostname:toto:42 user:alegrand");
+  TRY {
+    xbt_cfg_set_parse(set,"speed:42 speed:24 speed:34");
+  } CATCH(e) {
+    if (e.category != mismatch_error ||
+       strncmp(e.msg,"Cannot add value 34 to the config elem speed",
+               strlen("Config elem speed needs")))
+      xbt_test_fail1("Got an exception. msg=%s",e.msg);
+    xbt_ex_free(e);
+  }
+  xbt_cfg_check(set);
+  xbt_cfg_free(&set);
+  xbt_cfg_free(&set);
+
+}
+
+XBT_TEST_UNIT("use",test_config_use,"Data retrieving tests") {
+  xbt_cfg_t set = set=make_set();
+
+  xbt_test_add0("Get a single value");
+  {    
+    /* get_single_value */
+    int ival;
+    xbt_cfg_t myset=make_set();
+    
+    xbt_cfg_set_parse(myset,"hostname:toto:42 speed:42");
+    ival = xbt_cfg_get_int(myset,"speed"); 
+    if (ival != 42) 
+      xbt_test_fail1("Speed value = %d, I expected 42",ival);
+    xbt_cfg_free(&myset);
+  }
+
+  xbt_test_add0("Get multiple values");
+  {    
+    /* get_multiple_value */
+    xbt_dynar_t dyn; 
+    xbt_cfg_t myset=make_set();
+    
+    xbt_cfg_set_parse(myset, "hostname:veloce user:foo\nuser:bar\tuser:toto");
+    xbt_cfg_set_parse(myset,"speed:42");
+    xbt_cfg_check(myset); 
+    dyn = xbt_cfg_get_dynar(myset,"user");
+
+    if (xbt_dynar_length(dyn) != 3) 
+      xbt_test_fail1("Dynar length = %d, I expected 3", (int)xbt_dynar_length(dyn));
+
+    if (strcmp(xbt_dynar_get_as(dyn,0,char*),"foo"))
+      xbt_test_fail1("Dynar[0] = %s, I expected foo",   xbt_dynar_get_as(dyn,0,char*));
+
+    if (strcmp(xbt_dynar_get_as(dyn,1,char*),"bar"))
+      xbt_test_fail1("Dynar[1] = %s, I expected bar",   xbt_dynar_get_as(dyn,1,char*));
+
+    if (strcmp(xbt_dynar_get_as(dyn,2,char*),"toto"))
+      xbt_test_fail1("Dynar[2] = %s, I expected toto",  xbt_dynar_get_as(dyn,2,char*));
+    xbt_cfg_free(&myset);    
+  }
+  
+  xbt_test_add0("Access to a non-existant entry");
+  {    
+    /* non-existant_entry */
+    xbt_cfg_t myset=make_set();
+    xbt_ex_t e;
+    
+    TRY {
+      xbt_cfg_set_parse(myset, "color:blue");
+    } CATCH(e) {
+      if (e.category != not_found_error)
+        xbt_test_exception(e);
+      xbt_ex_free(e);
+    }
+    xbt_cfg_free(&myset);    
+  }
+}
+#endif /* SIMGRID_TEST */