Index: XIOS/trunk/src/registry.cpp
===================================================================
--- XIOS/trunk/src/registry.cpp	(revision 696)
+++ XIOS/trunk/src/registry.cpp	(revision 696)
@@ -0,0 +1,293 @@
+#include "registry.hpp"
+#include "type.hpp"
+#include <mpi.hpp>
+#include <fstream>
+#include <sstream>
+
+namespace xios
+{
+  using namespace std;
+
+  CRegistry::CRegistry(const CRegistry& reg) : communicator(reg.communicator)
+  {
+    for(map<string,pair<size_t,char*> >::const_iterator it=reg.registry.begin() ; it!=reg.registry.end() ; ++it)
+    {
+      char* buffer=new char[it->second.first] ;
+      memcpy(buffer,it->second.second,it->second.first) ;
+      registry.insert(pair<string, pair<size_t,char*> >(it->first, pair<size_t,char*>(it->second.first,buffer))) ; 
+    }
+  }
+
+        
+  void CRegistry::reset()
+  {
+    for(map<string,pair<size_t,char*> >::const_iterator it=registry.begin() ; it!=registry.end() ; ++it)
+    {
+      if (it->second.first>0) delete[] it->second.second ;
+    }
+    registry.clear() ;
+  }
+
+  void CRegistry::setKey_(const string& key_, const CBaseType& value)
+  {
+    const string key=path+key_ ;
+    if (!value.isEmpty())
+    {
+      size_t size=value.size();
+      
+      map<string,pair<size_t,char*> >::iterator it=registry.find(key) ;
+
+      if (it!=registry.end())
+      {
+        delete[] it->second.second ;
+        registry.erase(it) ;
+      }
+
+      char* buffer=new char[size] ;
+      CBufferOut tmpBuff(buffer,size) ;
+      value.toBuffer(tmpBuff) ;
+      registry.insert(pair<string, pair<size_t,char*> >(key, pair<size_t,char*>(size,buffer))) ;
+    }
+  }
+
+  void CRegistry::getKey_(const string& key_, CBaseType& value)
+  {
+    const string key=path+key_ ;
+    size_t size=value.size();
+      
+    map<string,pair<size_t,char*> >::iterator it=registry.find(key) ;
+
+    if (it!=registry.end())
+    {
+      CBufferIn tmpBuff(it->second.second,it->second.first) ;
+      value.fromBuffer(tmpBuff) ;
+    }
+    else value.reset() ;
+  }
+
+  bool CRegistry::foundKey(const string& key_) const
+  {
+    const string key=path+key_ ;
+    map<string,pair<size_t,char*> >::const_iterator it=registry.find(key) ;
+    if (it!=registry.end()) return true ;
+    else return false ;
+  }
+  
+  bool CRegistry::toBuffer(CBufferOut& buffer) const
+  {
+    buffer<<registry.size() ;
+    for(map<string,pair<size_t,char*> >::const_iterator it=registry.begin() ; it!=registry.end() ; ++it)
+    {
+      buffer<<it->first<<it->second.first ;
+      if (!buffer.put(it->second.second,it->second.first)) ERROR("bool CRegistry::toBuffer(CBufferOut& buffer) const)",
+                                                           << "Not enough free space in buffer to queue the data."); 
+    }
+    return true ;
+  }
+
+  size_t CRegistry::size() const
+  {
+    size_t s=0;
+    size_t size_t_size=CType<size_t>(0).size() ;
+    s+=size_t_size ;
+    for(map<string,pair<size_t,char*> >::const_iterator it=registry.begin() ; it!=registry.end() ; ++it)
+      s+=(CType<string>(it->first)).size() + size_t_size + it->second.first ;
+    return s ;
+  }
+
+  void CRegistry::fromString(const string& str)
+  {
+     ERROR("void CRegistry::fromString(const string& str)",<< "This method has not been implemented"); 
+  }
+
+  string CRegistry::toString() const
+  {
+    ostringstream oss;
+    
+    for(map<string,pair<size_t,char*> >::const_iterator it=registry.begin() ; it!=registry.end() ; ++it)
+    {
+      oss<<"Key = "<< it->first  <<" , size : "<<it->second.first<<"  ASCII value : "<<string((char*) it->second.second,it->second.first)<<endl ;
+    }
+    return oss.str() ;
+  }
+
+  
+
+  bool CRegistry::fromBuffer(CBufferIn& buffer)
+  {
+    string key ;
+    size_t size ;
+    char* value ;
+    size_t nKeys ;
+    buffer >> nKeys ;
+    for(size_t i=0;i<nKeys;++i)
+    {
+      buffer>>key>>size ;
+      if (size > 0)
+      {
+        value = new char[size] ;
+        buffer.get(value,size) ;
+      }
+      
+      map<string,pair<size_t,char*> >::iterator it=registry.find(key) ;
+      if (it!=registry.end())
+      {
+        delete[] it->second.second ;
+        registry.erase(it) ;
+      }
+      registry.insert(pair<string, pair<size_t,char*> >(key, pair<size_t,char*>(size,value))) ;        
+    }
+    return true ;
+  }  
+
+  void CRegistry::toFile(const string& filename)
+  {
+    if (registry.size()==0) return ;
+    
+    CBufferOut buffer(this->size()) ;
+    this->toBuffer(buffer) ;
+    ofstream file(filename.c_str(), ofstream::out ) ;
+    size_t size=buffer.count() ;
+    file.write((const char*) &size,sizeof(size)) ;
+    file.write((const char*) buffer.start(),size) ;
+    file.close() ;
+  }
+
+  void CRegistry::fromFile(const string& filename)
+  {
+    ifstream file(filename.c_str(), ifstream::in | ifstream::binary) ;
+    if (!file) return ;
+    size_t size;
+    file.read((char*) &size,sizeof(size)) ;
+    
+    CBufferIn buffer(size) ;
+    file.read((char*) buffer.ptr(),size) ;
+    this->fromBuffer(buffer) ;
+
+    file.close() ;
+  }
+    
+  void CRegistry::mergeRegistry(const CRegistry& inRegistry)
+  {
+    size_t size ;
+    char* value;
+    
+    for(map<string,pair<size_t,char*> >::const_iterator it=inRegistry.registry.begin() ; it!=inRegistry.registry.end() ; ++it)
+    {
+      const string& key=it->first ;
+      map<string,pair<size_t,char*> >::iterator it2=registry.find(key) ;
+      if (it2==registry.end())
+      {
+        size=it->second.first ;
+        value=new char[size] ;
+        memcpy(value,it->second.second,size) ;
+        registry.insert(pair<string, pair<size_t,char*> >(key, pair<size_t,char*>(size,value))) ;      
+      }
+    }
+  }
+
+  
+  void CRegistry::bcastRegistry(void)
+  {
+    int rank ;
+    MPI_Comm_rank(communicator,&rank);
+    if (rank==0)
+    {
+      CBufferOut buffer(this->size()) ;
+      this->toBuffer(buffer) ;
+      int size=buffer.count() ;
+      MPI_Bcast(&size,1,MPI_INT,0,communicator) ;
+      MPI_Bcast(buffer.start(),size,MPI_CHAR,0,communicator) ;
+    }
+    else
+    {
+      int size ;
+      MPI_Bcast(&size,1,MPI_INT,0,communicator) ;
+      CBufferIn buffer(size) ;
+      MPI_Bcast(buffer.start(),size,MPI_CHAR,0,communicator) ;
+      this->fromBuffer(buffer) ;
+    }
+  }
+  void CRegistry::gatherRegistry(void)
+  {
+    gatherRegistry(communicator) ;
+  }
+
+  void CRegistry::gatherRegistry(const MPI_Comm& comm)
+  {
+    int rank,mpiSize ;
+    MPI_Comm_rank(comm,&rank);
+    MPI_Comm_size(comm,&mpiSize);
+
+    int* sizes=new int[mpiSize] ;
+    CBufferOut localBuffer(this->size()) ;
+    this->toBuffer(localBuffer) ;
+    int localSize=localBuffer.count() ;
+    MPI_Gather(&localSize,1,MPI_INT,sizes,1,MPI_INT,0,comm) ;
+
+    char* globalBuffer ;
+    int*   displs ;
+    
+    if (rank==0)
+    {
+      size_t globalBufferSize=0 ;
+      displs=new int[mpiSize] ;
+      for (int i=0;i<mpiSize;++i)
+      {
+        displs[i]=globalBufferSize ;
+        globalBufferSize+=sizes[i] ;
+      }
+
+      globalBuffer=new char[globalBufferSize] ;
+      MPI_Gatherv(localBuffer.start(),localSize,MPI_CHAR,globalBuffer,sizes,displs,MPI_CHAR,0,comm) ;
+      for(int i=1;i<mpiSize;++i)
+      {
+        CBufferIn buffer(globalBuffer+displs[i],sizes[i]) ;
+        CRegistry reg ;
+        reg.fromBuffer(buffer) ;
+        mergeRegistry(reg) ;
+      }
+      delete[] displs ;
+      delete[] globalBuffer ;
+    }
+    else  MPI_Gatherv(localBuffer.start(),localSize,MPI_CHAR,globalBuffer,sizes,displs,MPI_CHAR,0,comm) ;   
+    delete[] sizes ;
+    
+  }
+
+  void CRegistry::hierarchicalGatherRegistry(void)
+  {
+    hierarchicalGatherRegistry(communicator) ;
+  }
+
+  void CRegistry::hierarchicalGatherRegistry(const MPI_Comm& comm)
+  {
+    int mpiRank,mpiSize ;
+    MPI_Comm_rank(comm,&mpiRank);
+    MPI_Comm_size(comm,&mpiSize);    
+
+    if (mpiSize>2)
+    {
+      int color ;
+      if (mpiRank<mpiSize/2+mpiSize%2) color=0 ;
+      else color=1 ;
+      MPI_Comm commUp ;
+      MPI_Comm_split(comm,color,mpiRank,&commUp) ,
+      hierarchicalGatherRegistry(commUp) ;
+      MPI_Comm_free(&commUp) ;
+    }
+
+    if (mpiSize>1)
+    {
+      MPI_Comm commDown ;
+      int color ;
+      
+      if (mpiRank==0 || mpiRank==mpiSize/2+mpiSize%2) color=0 ;
+      else color=1 ;
+      MPI_Comm_split(comm,color,mpiRank,&commDown) ;
+      if (color==0) gatherRegistry(commDown) ;
+      MPI_Comm_free(&commDown) ;    
+    }
+  }
+
+}
Index: XIOS/trunk/src/registry.hpp
===================================================================
--- XIOS/trunk/src/registry.hpp	(revision 696)
+++ XIOS/trunk/src/registry.hpp	(revision 696)
@@ -0,0 +1,133 @@
+#ifndef __XIOS_REGISTRY_HPP__
+#define __XIOS_REGISTRY_HPP__
+
+#include "base_type.hpp"
+#include "type.hpp"
+#include "mpi.hpp"
+#include "message.hpp"
+
+namespace xios
+{
+/*!
+  \class CRegistry
+ This class is a registry database which store key with an associated value. Internaly the value is stored as a memory bloc
+ and the key is a string. The registry can be gathered and merge between mpi process, broadcasted and read or wrote from a file
+*/
+  class CRegistry : virtual public CBaseType
+  {
+    public:
+
+/** Constructor, the communicator is used for bcast or gather operation between MPI processes */
+      CRegistry(const MPI_Comm& comm=MPI_COMM_WORLD) : communicator(comm) {}
+      
+/** Copy constructor */
+      CRegistry(const CRegistry& reg) ;
+      
+
+/** insert a value associated to a key*/
+      void setKey(const std::string& key, const CBaseType& value) {this->setKey(key,value); }
+
+/** insert a value associated to a key*/
+      template<typename T> void setKey(const std::string& key, const CType<T>& value) {this->setKey_(key,value); }
+
+
+/** retreive a value from a key */
+      void getKey(const std::string& key, CBaseType& value ) {this->getKey_(key,value); }
+
+/** retreive a value from a key */
+      template<typename T> void getKey(const std::string& key, CType<T>&  value ) {this->getKey_(key,value); }
+
+
+/** query for an already inserted key */
+      bool foundKey(const std::string& key) const ;
+      
+/** The registry is wrote into a memory buffer */
+      bool toBuffer(CBufferOut& buffer) const ;
+
+/** The registry is read from a memory buffer */
+      bool fromBuffer(CBufferIn& buffer) ;
+
+/** The registry is wrote to the file given by "filename". If the registry is empty no file is wrote */
+      void toFile(const string& filename) ;
+
+/** The registry is read from the file given by "filename". If no file exist, the registry remain empty */     
+      void fromFile(const string& filename) ;
+
+/** Merge the registry with an other. Existing keys in the current registry are not overwritten */         
+      void mergeRegistry(const CRegistry& inRegistry) ;
+
+/** Broadcast registry from the root process (rank 0) to the other processes of the communicator */    
+      void bcastRegistry(void) ;
+
+/** Gather registry to the root process (rank 0) from the other processes of the communicator */          
+      void gatherRegistry(void) ;
+
+/** Gather registry with a hierachical algorithm which avoid root process to get registries from whole processes of the communicator.
+   Registry are merged two by two hirarchicaly. */
+      void hierarchicalGatherRegistry(void) ;
+
+/** Destructor */
+       ~CRegistry() { reset() ; }
+
+/** Unimplemented, do not use (need for CBaseType pure virtual class) */
+      void fromString(const string& str) ;
+
+/** Dump registry to a string (need for CBaseType pure virtual class)*/      
+      string toString(void) const ;
+
+/** Clone the registry (need for CBaseType pure virtual class)*/      
+      CRegistry* clone(void) const { return new CRegistry(*this); }
+
+/** return the size needed to bufferized the registry (need for CBaseType pure virtual class)*/        
+      size_t size(void) const ;
+
+/** return true if the registry is empty (need for CBaseType pure virtual class)*/ 
+      bool isEmpty(void) const { return registry.empty(); }
+
+/** Clean the registry and delete associated memory (need for CBaseType pure virtual class)*/ 
+      void reset(void) ;
+
+/** Set the prefix added systematicaly to the keys, with "::" as separator*/       
+      void setPath(const string& str) { path=str+"::" ; }
+       
+    private:
+
+/** insert a value associated to a key (internal use)*/
+      void setKey_(const std::string& key, const CBaseType& value) ;
+
+/** retreive a value from a key (internal use)*/
+      void getKey_(const std::string& key, CBaseType& value ) ;
+      
+/** use internally for recursivity */
+      void gatherRegistry(const MPI_Comm& comm) ;
+
+/** use internally for recursivity */
+      void hierarchicalGatherRegistry(const MPI_Comm& comm) ;
+
+
+/** Prefix added systematicaly to the keys, with "::" as separator*/
+      std::string path ;
+
+/** Map containing registry, the key is a string type and the value is stored in a pair with the size
+ *  of the memory bloc and the associated pointer*/      
+      std::map<std::string,std::pair<size_t,char*> > registry ;
+
+/** MPI communicator used for broadcast and gather operation */
+      MPI_Comm communicator ;
+  } ;
+
+  inline CMessage& operator<<(CMessage& msg, CRegistry& registry)
+  {
+      msg.push(registry) ;
+      return msg ;
+  }
+
+  inline CMessage& operator<<(CMessage& msg, const CRegistry& registry)
+  {
+      msg.push(registry) ;
+      return msg ;
+  }
+
+}
+
+#endif
