Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add MPI_Type*keyval and MPI_Type*attr functions
authordegomme <degomme@localhost.localdomain>
Sun, 5 Oct 2014 18:17:05 +0000 (20:17 +0200)
committerdegomme <degomme@localhost.localdomain>
Sun, 5 Oct 2014 18:17:05 +0000 (20:17 +0200)
src/smpi/private.h
src/smpi/smpi_comm.c
src/smpi/smpi_mpi_dt.c
src/smpi/smpi_pmpi.c
teshsuite/smpi/mpich3-test/attr/CMakeLists.txt
teshsuite/smpi/mpich3-test/attr/testlist

index d6b87e0..d799e81 100644 (file)
@@ -58,6 +58,7 @@ typedef struct s_smpi_mpi_datatype{
   MPI_Aint lb;
   MPI_Aint ub;
   int flags;
   MPI_Aint lb;
   MPI_Aint ub;
   int flags;
+  xbt_dict_t attributes;
   /* this let us know how to serialize and unserialize*/
   void *substruct;
   int in_use;
   /* this let us know how to serialize and unserialize*/
   void *substruct;
   int in_use;
@@ -119,6 +120,12 @@ typedef struct s_smpi_mpi_key_elem {
 } s_smpi_mpi_key_elem_t; 
 typedef struct s_smpi_mpi_key_elem *smpi_key_elem;
 
 } s_smpi_mpi_key_elem_t; 
 typedef struct s_smpi_mpi_key_elem *smpi_key_elem;
 
+typedef struct s_smpi_mpi_type_key_elem {
+  MPI_Type_copy_attr_function* copy_fn;
+  MPI_Type_delete_attr_function* delete_fn;
+} s_smpi_mpi_type_key_elem_t; 
+typedef struct s_smpi_mpi_type_key_elem *smpi_type_key_elem;
+
 void smpi_process_destroy(void);
 void smpi_process_finalize(void);
 int smpi_process_finalized(void);
 void smpi_process_destroy(void);
 void smpi_process_finalize(void);
 int smpi_process_finalized(void);
@@ -196,7 +203,7 @@ int is_datatype_valid(MPI_Datatype datatype);
 size_t smpi_datatype_size(MPI_Datatype datatype);
 MPI_Aint smpi_datatype_lb(MPI_Datatype datatype);
 MPI_Aint smpi_datatype_ub(MPI_Datatype datatype);
 size_t smpi_datatype_size(MPI_Datatype datatype);
 MPI_Aint smpi_datatype_lb(MPI_Datatype datatype);
 MPI_Aint smpi_datatype_ub(MPI_Datatype datatype);
-MPI_Datatype smpi_datatype_dup(MPI_Datatype datatype);
+int smpi_datatype_dup(MPI_Datatype datatype, MPI_Datatype* new_t);
 int smpi_datatype_extent(MPI_Datatype datatype, MPI_Aint * lb,
                          MPI_Aint * extent);
 MPI_Aint smpi_datatype_get_extent(MPI_Datatype datatype);
 int smpi_datatype_extent(MPI_Datatype datatype, MPI_Aint * lb,
                          MPI_Aint * extent);
 MPI_Aint smpi_datatype_get_extent(MPI_Datatype datatype);
@@ -415,8 +422,11 @@ int smpi_keyval_free(int* keyval);
 int smpi_attr_delete(MPI_Comm comm, int keyval);
 int smpi_attr_get(MPI_Comm comm, int keyval, void* attr_value, int* flag);
 int smpi_attr_put(MPI_Comm comm, int keyval, void* attr_value);
 int smpi_attr_delete(MPI_Comm comm, int keyval);
 int smpi_attr_get(MPI_Comm comm, int keyval, void* attr_value, int* flag);
 int smpi_attr_put(MPI_Comm comm, int keyval, void* attr_value);
-
-
+int smpi_type_attr_delete(MPI_Datatype type, int keyval);
+int smpi_type_attr_get(MPI_Datatype type, int keyval, void* attr_value, int* flag);
+int smpi_type_attr_put(MPI_Datatype type, int keyval, void* attr_value);
+int smpi_type_keyval_create(MPI_Type_copy_attr_function* copy_fn, MPI_Type_delete_attr_function* delete_fn, int* keyval, void* extra_state);
+int smpi_type_keyval_free(int* keyval);
 // utilities
 extern double smpi_cpu_threshold;
 extern double smpi_running_power;
 // utilities
 extern double smpi_cpu_threshold;
 extern double smpi_running_power;
index ee2a7c3..b1fb5b2 100644 (file)
@@ -556,7 +556,6 @@ int smpi_comm_attr_get(MPI_Comm comm, int keyval, void* attr_value, int* flag){
     *flag=0;
     xbt_ex_free(ex);
   }
     *flag=0;
     xbt_ex_free(ex);
   }
-  
   return MPI_SUCCESS;
 }
 
   return MPI_SUCCESS;
 }
 
index e943324..2a9a464 100644 (file)
@@ -20,6 +20,9 @@
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_mpi_dt, smpi,
                                 "Logging specific to SMPI (datatype)");
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_mpi_dt, smpi,
                                 "Logging specific to SMPI (datatype)");
 
+xbt_dict_t smpi_type_keyvals = NULL;
+int type_keyval_id=0;//avoid collisions
+
 #define CREATE_MPI_DATATYPE(name, type)       \
   static s_smpi_mpi_datatype_t mpi_##name = { \
     (char*) # name,                                   \
 #define CREATE_MPI_DATATYPE(name, type)       \
   static s_smpi_mpi_datatype_t mpi_##name = { \
     (char*) # name,                                   \
@@ -28,7 +31,8 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_mpi_dt, smpi,
     0,             /* lb */                   \
     sizeof(type),  /* ub = lb + size */       \
     DT_FLAG_BASIC,  /* flags */              \
     0,             /* lb */                   \
     sizeof(type),  /* ub = lb + size */       \
     DT_FLAG_BASIC,  /* flags */              \
-    NULL           /* pointer on extended struct*/ \
+    NULL,           /* attributes */         \
+    NULL,           /* pointer on extended struct*/ \
   };                                          \
 MPI_Datatype name = &mpi_##name;
 
   };                                          \
 MPI_Datatype name = &mpi_##name;
 
@@ -40,6 +44,7 @@ MPI_Datatype name = &mpi_##name;
     0,             /* lb */                   \
     0,  /* ub = lb + size */       \
     DT_FLAG_BASIC,  /* flags */              \
     0,             /* lb */                   \
     0,  /* ub = lb + size */       \
     DT_FLAG_BASIC,  /* flags */              \
+    NULL,           /* attributes */         \
     NULL           /* pointer on extended struct*/ \
   };                                          \
 MPI_Datatype name = &mpi_##name;
     NULL           /* pointer on extended struct*/ \
   };                                          \
 MPI_Datatype name = &mpi_##name;
@@ -168,15 +173,39 @@ MPI_Aint smpi_datatype_ub(MPI_Datatype datatype)
   return datatype->ub;
 }
 
   return datatype->ub;
 }
 
-MPI_Datatype smpi_datatype_dup(MPI_Datatype datatype)
+int smpi_datatype_dup(MPI_Datatype datatype, MPI_Datatype* new_t)
 {
 {
-  MPI_Datatype new_t= xbt_new(s_smpi_mpi_datatype_t,1);
-  memcpy(new_t, datatype, sizeof(s_smpi_mpi_datatype_t));
-  if (datatype->has_subtype)
-    memcpy(new_t->substruct, datatype->substruct, sizeof(s_smpi_subtype_t));
+  int ret=MPI_SUCCESS;
+  *new_t= xbt_new(s_smpi_mpi_datatype_t,1);
+  memcpy(*new_t, datatype, sizeof(s_smpi_mpi_datatype_t));
+  if (datatype->has_subtype){
+    //FIXME: may copy too much information.
+    (*new_t)->substruct=xbt_malloc(sizeof(s_smpi_mpi_struct_t));
+    memcpy((*new_t)->substruct, datatype->substruct, sizeof(s_smpi_mpi_struct_t));
+  }
   if(datatype->name)
   if(datatype->name)
-    new_t->name = strdup(datatype->name);
-  return new_t;
+    (*new_t)->name = strdup(datatype->name);
+  if(datatype->attributes !=NULL){
+      (*new_t)->attributes=xbt_dict_new();
+      xbt_dict_cursor_t cursor = NULL;
+      int *key;
+      int flag;
+      void* value_in;
+      void* value_out;
+      xbt_dict_foreach(datatype->attributes, cursor, key, value_in){
+        smpi_type_key_elem elem = xbt_dict_get_or_null(smpi_type_keyvals, (const char*)key);
+        if(elem && elem->copy_fn!=MPI_NULL_COPY_FN){
+          ret = elem->copy_fn(datatype, atoi((const char*)key), NULL, value_in, &value_out, &flag );
+          if(ret!=MPI_SUCCESS){
+            *new_t=MPI_DATATYPE_NULL;
+            return ret;
+          }
+          if(flag)
+            xbt_dict_set((*new_t)->attributes, (const char*)key,value_out, NULL);
+        }
+      }
+    }
+  return ret;
 }
 
 int smpi_datatype_extent(MPI_Datatype datatype, MPI_Aint * lb,
 }
 
 int smpi_datatype_extent(MPI_Datatype datatype, MPI_Aint * lb,
@@ -364,6 +393,7 @@ void smpi_datatype_create(MPI_Datatype* new_type, int size,int lb, int ub, int h
   new_t->flags = flags;
   new_t->substruct = struct_type;
   new_t->in_use=0;
   new_t->flags = flags;
   new_t->substruct = struct_type;
   new_t->in_use=0;
+  new_t->attributes=NULL;
   *new_type = new_t;
 
 #ifdef HAVE_MC
   *new_type = new_t;
 
 #ifdef HAVE_MC
@@ -373,6 +403,17 @@ void smpi_datatype_create(MPI_Datatype* new_type, int size,int lb, int ub, int h
 }
 
 void smpi_datatype_free(MPI_Datatype* type){
 }
 
 void smpi_datatype_free(MPI_Datatype* type){
+  if((*type)->attributes !=NULL){
+      xbt_dict_cursor_t cursor = NULL;
+      int* key;
+      void * value;
+      int flag;
+      xbt_dict_foreach((*type)->attributes, cursor, key, value){
+        smpi_type_key_elem elem = xbt_dict_get_or_null(smpi_type_keyvals, (const char*)key);
+        if(elem)
+          elem->delete_fn(*type, atoi((const char*)key), &value, &flag);
+      }
+  }
 
   if((*type)->flags & DT_FLAG_PREDEFINED)return;
 
 
   if((*type)->flags & DT_FLAG_PREDEFINED)return;
 
@@ -1626,3 +1667,99 @@ void smpi_op_apply(MPI_Op op, void *invec, void *inoutvec, int *len,
   if(!smpi_process_get_replaying())
   op->func(invec, inoutvec, len, datatype);
 }
   if(!smpi_process_get_replaying())
   op->func(invec, inoutvec, len, datatype);
 }
+
+int smpi_type_attr_delete(MPI_Datatype type, int keyval){
+  char* tmpkey=xbt_malloc(sizeof(int));
+  sprintf(tmpkey, "%d", keyval);
+  smpi_type_key_elem elem = xbt_dict_get_or_null(smpi_type_keyvals, (const char*)tmpkey);
+  if(!elem)
+    return MPI_ERR_ARG;
+  if(elem->delete_fn!=MPI_NULL_DELETE_FN){
+    void * value;
+    int flag;
+    if(smpi_type_attr_get(type, keyval, &value, &flag)==MPI_SUCCESS){
+      int ret = elem->delete_fn(type, keyval, &value, &flag);
+      if(ret!=MPI_SUCCESS) return ret;
+    }
+  }  
+  if(type->attributes==NULL)
+    return MPI_ERR_ARG;
+
+  xbt_dict_remove(type->attributes, (const char*)tmpkey);
+  return MPI_SUCCESS;
+}
+
+int smpi_type_attr_get(MPI_Datatype type, int keyval, void* attr_value, int* flag){
+  char* tmpkey=xbt_malloc(sizeof(int));
+  sprintf(tmpkey, "%d", keyval);
+  smpi_type_key_elem elem = xbt_dict_get_or_null(smpi_type_keyvals, (const char*)tmpkey);
+  if(!elem)
+    return MPI_ERR_ARG;
+  xbt_ex_t ex;
+  if(type->attributes==NULL){
+    *flag=0;
+    return MPI_SUCCESS;
+  }
+  TRY {
+  char* tmpkey=xbt_malloc(sizeof(int));
+  sprintf(tmpkey, "%d", keyval);
+    *(void**)attr_value = xbt_dict_get(type->attributes, (const char*)tmpkey);
+    *flag=1;
+  }
+  CATCH(ex) {
+    *flag=0;
+    xbt_ex_free(ex);
+  }
+  return MPI_SUCCESS;
+}
+
+int smpi_type_attr_put(MPI_Datatype type, int keyval, void* attr_value){
+  if(!smpi_type_keyvals)
+  smpi_type_keyvals = xbt_dict_new();
+  char* tmpkey=xbt_malloc(sizeof(int));
+  sprintf(tmpkey, "%d", keyval);
+  smpi_type_key_elem elem = xbt_dict_get_or_null(smpi_type_keyvals, (const char*)tmpkey);
+  if(!elem )
+    return MPI_ERR_ARG;
+  int flag;
+  void* value;
+  smpi_type_attr_get(type, keyval, &value, &flag);
+  if(flag && elem->delete_fn!=MPI_NULL_DELETE_FN){
+    int ret = elem->delete_fn(type, keyval, &value, &flag);
+    if(ret!=MPI_SUCCESS) return ret;
+  }
+  if(type->attributes==NULL)
+    type->attributes=xbt_dict_new();
+
+  xbt_dict_set(type->attributes, (const char*)tmpkey, attr_value, NULL);
+  return MPI_SUCCESS;
+}
+
+int smpi_type_keyval_create(MPI_Type_copy_attr_function* copy_fn, MPI_Type_delete_attr_function* delete_fn, int* keyval, void* extra_state){
+
+  if(!smpi_type_keyvals)
+  smpi_type_keyvals = xbt_dict_new();
+  
+  smpi_type_key_elem value = (smpi_type_key_elem) xbt_new0(s_smpi_mpi_type_key_elem_t,1);
+  
+  value->copy_fn=copy_fn;
+  value->delete_fn=delete_fn;
+  
+  *keyval = type_keyval_id;
+  char* tmpkey=xbt_malloc(sizeof(int));
+  sprintf(tmpkey, "%d", *keyval);
+  xbt_dict_set(smpi_type_keyvals,(const char*)tmpkey,(void*)value, NULL);
+  type_keyval_id++;
+  return MPI_SUCCESS;
+}
+
+int smpi_type_keyval_free(int* keyval){
+  smpi_type_key_elem elem = xbt_dict_get_or_null(smpi_type_keyvals, (const char*)keyval);
+  if(!elem)
+    return MPI_ERR_ARG;
+  char* tmpkey=xbt_malloc(sizeof(int));
+  sprintf(tmpkey, "%d", *keyval);
+  xbt_dict_remove(smpi_type_keyvals, (const char*)tmpkey);
+  xbt_free(elem);
+  return MPI_SUCCESS;
+}
index a40bccb..6d6f958 100644 (file)
@@ -253,8 +253,7 @@ int PMPI_Type_dup(MPI_Datatype datatype, MPI_Datatype *newtype){
   if (datatype == MPI_DATATYPE_NULL) {
     retval = MPI_ERR_TYPE;
   } else {
   if (datatype == MPI_DATATYPE_NULL) {
     retval = MPI_ERR_TYPE;
   } else {
-    *newtype = smpi_datatype_dup(datatype);
-    retval = MPI_SUCCESS;
+    retval = smpi_datatype_dup(datatype, newtype);
   }
   return retval;
 }
   }
   return retval;
 }
@@ -3001,7 +3000,6 @@ int PMPI_Attr_put(MPI_Comm comm, int keyval, void* attr_value) {
   return smpi_attr_put(comm, keyval, attr_value);
 }
 
   return smpi_attr_put(comm, keyval, attr_value);
 }
 
-
 int PMPI_Comm_get_attr (MPI_Comm comm, int comm_keyval, void *attribute_val, int *flag)
 {
   return PMPI_Attr_get(comm, comm_keyval, attribute_val,flag);
 int PMPI_Comm_get_attr (MPI_Comm comm, int comm_keyval, void *attribute_val, int *flag)
 {
   return PMPI_Attr_get(comm, comm_keyval, attribute_val,flag);
@@ -3026,6 +3024,40 @@ int PMPI_Comm_free_keyval(int* keyval) {
   return PMPI_Keyval_free(keyval);
 }
 
   return PMPI_Keyval_free(keyval);
 }
 
+
+int PMPI_Type_get_attr (MPI_Datatype type, int type_keyval, void *attribute_val, int* flag)
+{
+  if (type==MPI_DATATYPE_NULL)
+    return MPI_ERR_TYPE;
+  else
+    return smpi_type_attr_get(type, type_keyval, attribute_val, flag);
+}
+
+int PMPI_Type_set_attr (MPI_Datatype type, int type_keyval, void *attribute_val)
+{
+  if (type==MPI_DATATYPE_NULL)
+    return MPI_ERR_TYPE;
+  else
+    return smpi_type_attr_put(type, type_keyval, attribute_val);
+}
+
+int PMPI_Type_delete_attr (MPI_Datatype type, int type_keyval)
+{
+  if (type==MPI_DATATYPE_NULL)
+    return MPI_ERR_TYPE;
+  else
+    return smpi_type_attr_delete(type, type_keyval);
+}
+
+int PMPI_Type_create_keyval(MPI_Type_copy_attr_function* copy_fn, MPI_Type_delete_attr_function* delete_fn, int* keyval, void* extra_state)
+{
+  return smpi_type_keyval_create(copy_fn, delete_fn, keyval, extra_state);
+}
+
+int PMPI_Type_free_keyval(int* keyval) {
+  return smpi_type_keyval_free(keyval);
+}
+
 /* The following calls are not yet implemented and will fail at runtime. */
 /* Once implemented, please move them above this notice. */
 
 /* The following calls are not yet implemented and will fail at runtime. */
 /* Once implemented, please move them above this notice. */
 
@@ -3146,30 +3178,6 @@ int PMPI_Unpack(void* inbuf, int insize, int* position, void* outbuf, int outcou
   NOT_YET_IMPLEMENTED
 }
 
   NOT_YET_IMPLEMENTED
 }
 
-int PMPI_Type_get_attr (MPI_Datatype type, int type_keyval, void *attribute_val, int* flag)
-{
-  NOT_YET_IMPLEMENTED
-}
-
-int PMPI_Type_set_attr (MPI_Datatype type, int type_keyval, void *attribute_val)
-{
-  NOT_YET_IMPLEMENTED
-}
-
-int PMPI_Type_delete_attr (MPI_Datatype type, int comm_keyval)
-{
-  NOT_YET_IMPLEMENTED
-}
-
-int PMPI_Type_create_keyval(MPI_Type_copy_attr_function* copy_fn, MPI_Type_delete_attr_function* delete_fn, int* keyval, void* extra_state)
-{
-  NOT_YET_IMPLEMENTED
-}
-
-int PMPI_Type_free_keyval(int* keyval) {
-  NOT_YET_IMPLEMENTED
-}
-
 int PMPI_Intercomm_create(MPI_Comm local_comm, int local_leader, MPI_Comm peer_comm, int remote_leader, int tag, MPI_Comm* comm_out) {
   NOT_YET_IMPLEMENTED
 }
 int PMPI_Intercomm_create(MPI_Comm local_comm, int local_leader, MPI_Comm peer_comm, int remote_leader, int tag, MPI_Comm* comm_out) {
   NOT_YET_IMPLEMENTED
 }
index c477207..3d71bdf 100644 (file)
@@ -13,16 +13,16 @@ if(enable_smpi AND enable_smpi_MPICH3_testsuite)
   include_directories("${CMAKE_HOME_DIRECTORY}/include/smpi")
   include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../include/")
 
   include_directories("${CMAKE_HOME_DIRECTORY}/include/smpi")
   include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../include/")
 
-#  add_executable(attr2type attr2type.c)
+  add_executable(attr2type attr2type.c)
   add_executable(attrend2 attrend2.c)
   add_executable(attrend attrend.c)
   add_executable(attrerr attrerr.c)
   add_executable(attrerrcomm attrerrcomm.c)
   add_executable(attrend2 attrend2.c)
   add_executable(attrend attrend.c)
   add_executable(attrerr attrerr.c)
   add_executable(attrerrcomm attrerrcomm.c)
-#  add_executable(attrerrtype attrerrtype.c)
+  add_executable(attrerrtype attrerrtype.c)
 #  add_executable(attric attric.c)
   add_executable(attrorder attrorder.c)
   add_executable(attrordercomm attrordercomm.c)
 #  add_executable(attric attric.c)
   add_executable(attrorder attrorder.c)
   add_executable(attrordercomm attrordercomm.c)
-#  add_executable(attrordertype attrordertype.c)
+  add_executable(attrordertype attrordertype.c)
   add_executable(attrt attrt.c)
   add_executable(baseattr2 baseattr2.c)
   add_executable(baseattrcomm baseattrcomm.c)
   add_executable(attrt attrt.c)
   add_executable(baseattr2 baseattr2.c)
   add_executable(baseattrcomm baseattrcomm.c)
@@ -31,16 +31,16 @@ if(enable_smpi AND enable_smpi_MPICH3_testsuite)
 #  add_executable(fkeyvaltype fkeyvaltype.c)
 #  add_executable(keyval_double_free keyval_double_free.c)
 
 #  add_executable(fkeyvaltype fkeyvaltype.c)
 #  add_executable(keyval_double_free keyval_double_free.c)
 
-#  target_link_libraries(attr2type simgrid mtest_c)
+  target_link_libraries(attr2type simgrid mtest_c)
   target_link_libraries(attrend2 simgrid mtest_c)
   target_link_libraries(attrend simgrid mtest_c)
   target_link_libraries(attrerr simgrid mtest_c)
   target_link_libraries(attrerrcomm simgrid mtest_c)
   target_link_libraries(attrend2 simgrid mtest_c)
   target_link_libraries(attrend simgrid mtest_c)
   target_link_libraries(attrerr simgrid mtest_c)
   target_link_libraries(attrerrcomm simgrid mtest_c)
-#  target_link_libraries(attrerrtype simgrid mtest_c)
+  target_link_libraries(attrerrtype simgrid mtest_c)
 #  target_link_libraries(attric simgrid mtest_c)
   target_link_libraries(attrorder simgrid mtest_c)
   target_link_libraries(attrordercomm simgrid mtest_c)
 #  target_link_libraries(attric simgrid mtest_c)
   target_link_libraries(attrorder simgrid mtest_c)
   target_link_libraries(attrordercomm simgrid mtest_c)
-#  target_link_libraries(attrordertype simgrid mtest_c)
+  target_link_libraries(attrordertype simgrid mtest_c)
   target_link_libraries(attrt simgrid mtest_c)
   target_link_libraries(baseattr2 simgrid mtest_c)
   target_link_libraries(baseattrcomm simgrid mtest_c)
   target_link_libraries(attrt simgrid mtest_c)
   target_link_libraries(baseattr2 simgrid mtest_c)
   target_link_libraries(baseattrcomm simgrid mtest_c)
index c687935..b18c619 100644 (file)
@@ -12,17 +12,14 @@ attrerr 1
 attrend2 1
 attrend2 5
 attrerrcomm 1
 attrend2 1
 attrend2 5
 attrerrcomm 1
-#needs MPI_Errhandler_set, MPI_Type_create_keyval, MPI_Type_dup, MPI_Type_set_attr, MPI_Type_delete_attr
-#attrerrtype 1
-#needs MPI_Type_create_keyval, MPI_Type_dup, MPI_Type_set_attr
-#attr2type 1
+attrerrtype 1
+attr2type 1
 attrorder 1
 attrordercomm 1
 attrorder 1
 attrordercomm 1
-#needs MPI_Type_create_keyval, MPI_Type_delete_keyval, MPI_Type_set_attr, MPI_Type_delete_attr
-#attrordertype 1
+attrordertype 1
 baseattr2 1
 baseattrcomm 1
 baseattr2 1
 baseattrcomm 1
-#MPI_Keyval_create, MPI_Keyval_free for type and comm also
+#would need a refcount in keyval and attr
 #fkeyval 1
 #fkeyvalcomm 1
 #fkeyvaltype 1
 #fkeyval 1
 #fkeyvalcomm 1
 #fkeyvaltype 1