Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/context_client.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/context_client.cpp	(revision 2342)
+++ 	(revision )
@@ -1,573 +1,0 @@
-#include "xios_spl.hpp"
-#include "context_client.hpp"
-#include "context_server.hpp"
-#include "event_client.hpp"
-#include "buffer_out.hpp"
-#include "buffer_client.hpp"
-#include "type.hpp"
-#include "event_client.hpp"
-#include "context.hpp"
-#include "mpi.hpp"
-#include "timer.hpp"
-#include "cxios.hpp"
-#include "server.hpp"
-#include "services.hpp"
-#include <boost/functional/hash.hpp>
-#include <random>
-#include <chrono>
-
-namespace xios
-{
-    /*!
-    \param [in] parent Pointer to context on client side
-    \param [in] intraComm_ communicator of group client
-    \param [in] interComm_ communicator of group server
-    \cxtSer [in] cxtSer Pointer to context of server side. (It is only used in case of attached mode).
-    */
-    CContextClient::CContextClient(CContext* parent, MPI_Comm intraComm_, MPI_Comm interComm_, CContext* cxtSer)
-     : mapBufferSize_(), parentServer(cxtSer), maxBufferedEvents(4), associatedServer_(nullptr)
-    {
-      
-      context_ = parent;
-      intraComm = intraComm_;
-      interComm = interComm_;
-      MPI_Comm_rank(intraComm, &clientRank);
-      MPI_Comm_size(intraComm, &clientSize);
-
-      int flag;
-      MPI_Comm_test_inter(interComm, &flag);
-      if (flag) isAttached_=false ;
-      else  isAttached_=true ;
-
-      pureOneSided=CXios::getin<bool>("pure_one_sided",false); // pure one sided communication (for test)
-      if (isAttachedModeEnabled()) pureOneSided=false ; // no one sided in attach mode
-      
-
-
-      if (flag) MPI_Comm_remote_size(interComm, &serverSize);
-      else  MPI_Comm_size(interComm, &serverSize);
-
-      computeLeader(clientRank, clientSize, serverSize, ranksServerLeader, ranksServerNotLeader);
-
-      if (flag) MPI_Intercomm_merge(interComm_,false, &interCommMerged_) ;
-      
-      MPI_Comm_split(intraComm_,clientRank,clientRank, &commSelf_) ; // for windows
-
-      auto time=chrono::system_clock::now().time_since_epoch().count() ;
-      std::default_random_engine rd(time); // not reproducible from a run to another
-      std::uniform_int_distribution<size_t> dist;
-      hashId_=dist(rd) ;
-      MPI_Bcast(&hashId_,1,MPI_SIZE_T,0,intraComm) ; // Bcast to all server of the context
-
-      timeLine = 1;
-    }
-
-    void CContextClient::computeLeader(int clientRank, int clientSize, int serverSize,
-                                       std::list<int>& rankRecvLeader,
-                                       std::list<int>& rankRecvNotLeader)
-    {
-      if ((0 == clientSize) || (0 == serverSize)) return;
-
-      if (clientSize < serverSize)
-      {
-        int serverByClient = serverSize / clientSize;
-        int remain = serverSize % clientSize;
-        int rankStart = serverByClient * clientRank;
-
-        if (clientRank < remain)
-        {
-          serverByClient++;
-          rankStart += clientRank;
-        }
-        else
-          rankStart += remain;
-
-        for (int i = 0; i < serverByClient; i++)
-          rankRecvLeader.push_back(rankStart + i);
-
-        rankRecvNotLeader.resize(0);
-      }
-      else
-      {
-        int clientByServer = clientSize / serverSize;
-        int remain = clientSize % serverSize;
-
-        if (clientRank < (clientByServer + 1) * remain)
-        {
-          if (clientRank % (clientByServer + 1) == 0)
-            rankRecvLeader.push_back(clientRank / (clientByServer + 1));
-          else
-            rankRecvNotLeader.push_back(clientRank / (clientByServer + 1));
-        }
-        else
-        {
-          int rank = clientRank - (clientByServer + 1) * remain;
-          if (rank % clientByServer == 0)
-            rankRecvLeader.push_back(remain + rank / clientByServer);
-          else
-            rankRecvNotLeader.push_back(remain + rank / clientByServer);
-        }
-      }
-    }
-
-    /*!
-    In case of attached mode, the current context must be reset to context for client
-    \param [in] event Event sent to server
-    */
-    void CContextClient::sendEvent(CEventClient& event)
-    {
-      list<int> ranks = event.getRanks();
- 
-//      ostringstream str ;
-//      for(auto& rank : ranks) str<<rank<<" ; " ;
-//      info(100)<<"Event "<<timeLine<<" of context "<<context_->getId()<<"  for ranks : "<<str.str()<<endl ;
-
-      if (CXios::checkEventSync)
-      {
-        int typeId, classId, typeId_in, classId_in;
-        long long timeLine_out;
-        long long timeLine_in( timeLine );
-        typeId_in=event.getTypeId() ;
-        classId_in=event.getClassId() ;
-//        MPI_Allreduce(&timeLine,&timeLine_out, 1, MPI_UINT64_T, MPI_SUM, intraComm) ; // MPI_UINT64_T standardized by MPI 3
-        MPI_Allreduce(&timeLine_in,&timeLine_out, 1, MPI_LONG_LONG_INT, MPI_SUM, intraComm) ; 
-        MPI_Allreduce(&typeId_in,&typeId, 1, MPI_INT, MPI_SUM, intraComm) ;
-        MPI_Allreduce(&classId_in,&classId, 1, MPI_INT, MPI_SUM, intraComm) ;
-        if (typeId/clientSize!=event.getTypeId() || classId/clientSize!=event.getClassId() || timeLine_out/clientSize!=timeLine)
-        {
-           ERROR("void CContextClient::sendEvent(CEventClient& event)",
-               << "Event are not coherent between client for timeline = "<<timeLine);
-        }
-        
-        vector<int> servers(serverSize,0) ;
-        auto ranks=event.getRanks() ;
-        for(auto& rank : ranks) servers[rank]=1 ;
-        MPI_Allreduce(MPI_IN_PLACE, servers.data(), serverSize,MPI_INT,MPI_SUM,intraComm) ;
-        ostringstream osstr ;
-        for(int i=0;i<serverSize;i++)  if (servers[i]==0) osstr<<i<<" , " ;
-        if (!osstr.str().empty())
-        {
-          ERROR("void CContextClient::sendEvent(CEventClient& event)",
-                 <<" Some servers will not receive the message for timeline = "<<timeLine<<endl
-                 <<"Servers are : "<<osstr.str()) ;
-        }
-
-
-      }
-
-      if (!event.isEmpty())
-      {
-        list<int> sizes = event.getSizes();
-
-         // We force the getBuffers call to be non-blocking on classical servers
-        list<CBufferOut*> buffList;
-        getBuffers(timeLine, ranks, sizes, buffList) ;
-
-        event.send(timeLine, sizes, buffList);
-       
-        //for (auto itRank = ranks.begin(); itRank != ranks.end(); itRank++) buffers[*itRank]->infoBuffer() ;
-
-        unlockBuffers(ranks) ;
-        checkBuffers(ranks);
-        
-      }
-      
-      if (isAttachedModeEnabled()) // couldBuffer is always true in attached mode
-      {
-        while (checkBuffers(ranks)) callGlobalEventLoop() ;
-      
-        CXios::getDaemonsManager()->scheduleContext(hashId_) ;
-        while (CXios::getDaemonsManager()->isScheduledContext(hashId_)) callGlobalEventLoop() ;
-      }
-      
-      timeLine++;
-    }
-
-    /*!
-    If client is also server (attached mode), after sending event, it should process right away
-    the incoming event.
-    \param [in] ranks list rank of server connected this client
-    */
-    void CContextClient::waitEvent(list<int>& ranks)
-    {
-      while (checkBuffers(ranks))
-      {
-        context_->eventLoop() ;
-      }
-
-      MPI_Request req ;
-      MPI_Status status ;
-
-      MPI_Ibarrier(intraComm,&req) ;
-      int flag=false ;
-
-      do  
-      {
-        CXios::getDaemonsManager()->eventLoop() ;
-        MPI_Test(&req,&flag,&status) ;
-      } while (!flag) ;
-
-
-    }
-
-
-    void CContextClient::waitEvent_old(list<int>& ranks)
-    {
-      parentServer->server->setPendingEvent();
-      while (checkBuffers(ranks))
-      {
-        parentServer->server->listen();
-        parentServer->server->checkPendingRequest();
-      }
-
-      while (parentServer->server->hasPendingEvent())
-      {
-       parentServer->server->eventLoop();
-      }
-    }
-
-    /*!
-     * Get buffers for each connection to the servers. This function blocks until there is enough room in the buffers unless
-     * it is explicitly requested to be non-blocking.
-     *
-     *
-     * \param [in] timeLine time line of the event which will be sent to servers
-     * \param [in] serverList list of rank of connected server
-     * \param [in] sizeList size of message corresponding to each connection
-     * \param [out] retBuffers list of buffers that can be used to store an event
-     * \param [in] nonBlocking whether this function should be non-blocking
-     * \return whether the already allocated buffers could be used
-    */
-    bool CContextClient::getBuffers(const size_t timeLine, const list<int>& serverList, const list<int>& sizeList, list<CBufferOut*>& retBuffers,
-                                    bool nonBlocking /*= false*/)
-    {
-      list<int>::const_iterator itServer, itSize;
-      list<CClientBuffer*> bufferList;
-      map<int,CClientBuffer*>::const_iterator it;
-      list<CClientBuffer*>::iterator itBuffer;
-      bool areBuffersFree;
-
-      for (itServer = serverList.begin(); itServer != serverList.end(); itServer++)
-      {
-        it = buffers.find(*itServer);
-        if (it == buffers.end())
-        {
-          newBuffer(*itServer);
-          it = buffers.find(*itServer);
-        }
-        bufferList.push_back(it->second);
-      }
-
-      double lastTimeBuffersNotFree=0. ;
-      double time ;
-      bool doUnlockBuffers ;
-      CTimer::get("Blocking time").resume();
-      do
-      {
-        areBuffersFree = true;
-        doUnlockBuffers=false ;
-        time=MPI_Wtime() ;
-        if (time-lastTimeBuffersNotFree > latency_)
-        {
-          for (itBuffer = bufferList.begin(), itSize = sizeList.begin(); itBuffer != bufferList.end(); itBuffer++, itSize++)
-          {
-            areBuffersFree &= (*itBuffer)->isBufferFree(*itSize);
-          }
-          if (!areBuffersFree)
-          {
-            lastTimeBuffersNotFree = time ;
-            doUnlockBuffers=true ;
-          }          
-        }
-        else areBuffersFree = false ;
-
-        if (!areBuffersFree)
-        {
-          if (doUnlockBuffers) for (itBuffer = bufferList.begin(); itBuffer != bufferList.end(); itBuffer++) (*itBuffer)->unlockBuffer();
-          checkBuffers();
-
-          callGlobalEventLoop() ;
-        }
-
-      } while (!areBuffersFree && !nonBlocking);
-      CTimer::get("Blocking time").suspend();
-
-      if (areBuffersFree)
-      {
-        for (itBuffer = bufferList.begin(), itSize = sizeList.begin(); itBuffer != bufferList.end(); itBuffer++, itSize++)
-          retBuffers.push_back((*itBuffer)->getBuffer(timeLine, *itSize));
-      }
-      return areBuffersFree;
-   }
-
-   void CContextClient::eventLoop(void)
-   {
-      if (!locked_) checkBuffers() ;
-   }
-
-   void CContextClient::callGlobalEventLoop(void)
-   {
-     locked_=true ;
-     context_->globalEventLoop() ;
-     locked_=false ;
-   }
-   /*!
-   Make a new buffer for a certain connection to server with specific rank
-   \param [in] rank rank of connected server
-   */
-   void CContextClient::newBuffer(int rank)
-   {
-      if (!mapBufferSize_.count(rank))
-      {
-        error(0) << "WARNING: Unexpected request for buffer to communicate with server " << rank << std::endl;
-        mapBufferSize_[rank] = CXios::minBufferSize;
-        maxEventSizes[rank] = CXios::minBufferSize;
-      }
-      
-      CClientBuffer* buffer = buffers[rank] = new CClientBuffer(interComm, rank, mapBufferSize_[rank], maxEventSizes[rank]);
-      if (isGrowableBuffer_) buffer->setGrowableBuffer(1.2) ;
-      else buffer->fixBuffer() ;
-      // Notify the server
-      CBufferOut* bufOut = buffer->getBuffer(0, 4*sizeof(MPI_Aint));
-      MPI_Aint sendBuff[4] ;
-      sendBuff[0]=hashId_;
-      sendBuff[1]=mapBufferSize_[rank];
-      sendBuff[2]=buffers[rank]->getWinAddress(0); 
-      sendBuff[3]=buffers[rank]->getWinAddress(1); 
-      info(100)<<"CContextClient::newBuffer : rank "<<rank<<" winAdress[0] "<<buffers[rank]->getWinAddress(0)<<" winAdress[1] "<<buffers[rank]->getWinAddress(1)<<endl;
-      bufOut->put(sendBuff, 4); 
-      buffer->checkBuffer(true);
-      
-       // create windows dynamically for one-sided
-      if (!isAttachedModeEnabled())
-      { 
-        CTimer::get("create Windows").resume() ;
-        MPI_Comm interComm ;
-        MPI_Intercomm_create(commSelf_, 0, interCommMerged_, clientSize+rank, 0, &interComm) ;
-        MPI_Intercomm_merge(interComm, false, &winComm_[rank]) ;
-        CXios::getMpiGarbageCollector().registerCommunicator(winComm_[rank]) ;
-        MPI_Comm_free(&interComm) ;
-        windows_[rank].resize(2) ;
-        
-        MPI_Win_create_dynamic(MPI_INFO_NULL, winComm_[rank], &windows_[rank][0]);
-        CXios::getMpiGarbageCollector().registerWindow(windows_[rank][0]) ;
-        
-        MPI_Win_create_dynamic(MPI_INFO_NULL, winComm_[rank], &windows_[rank][1]);   
-        CXios::getMpiGarbageCollector().registerWindow(windows_[rank][1]) ;
-
-        CTimer::get("create Windows").suspend() ;
-      }
-      else
-      {
-        winComm_[rank] = MPI_COMM_NULL ;
-        windows_[rank].resize(2) ;
-        windows_[rank][0] = MPI_WIN_NULL ;
-        windows_[rank][1] = MPI_WIN_NULL ;
-      }
-      buffer->attachWindows(windows_[rank]) ;
-      if (!isAttachedModeEnabled()) MPI_Barrier(winComm_[rank]) ;
-       
-   }
-
-   /*!
-   Verify state of buffers. Buffer is under pending state if there is no message on it
-   \return state of buffers, pending(true), ready(false)
-   */
-   bool CContextClient::checkBuffers(void)
-   {
-      map<int,CClientBuffer*>::iterator itBuff;
-      bool pending = false;
-      for (itBuff = buffers.begin(); itBuff != buffers.end(); itBuff++)
-        pending |= itBuff->second->checkBuffer(!pureOneSided);
-      return pending;
-   }
-
-   //! Release all buffers
-   void CContextClient::releaseBuffers()
-   {
-      map<int,CClientBuffer*>::iterator itBuff;
-      for (itBuff = buffers.begin(); itBuff != buffers.end(); itBuff++)
-      {
-         delete itBuff->second;
-      }
-      buffers.clear();
-
-// don't know when release windows
-
-      //if (!isAttachedModeEnabled())
-      //{  
-      //  for(auto& it : winComm_)
-      //  {
-      //    int rank = it.first ;
-      //    MPI_Win_free(&windows_[rank][0]);
-      //    MPI_Win_free(&windows_[rank][1]);
-      //    MPI_Comm_free(&winComm_[rank]) ;
-      //  }
-      //} 
-   }
-
-      
-  /*!
-   Lock the buffers for one sided communications
-   \param [in] ranks list rank of server to which client connects to
-   */
-   void CContextClient::lockBuffers(list<int>& ranks)
-   {
-      list<int>::iterator it;
-      for (it = ranks.begin(); it != ranks.end(); it++) buffers[*it]->lockBuffer();
-   }
-
-  /*!
-   Unlock the buffers for one sided communications
-   \param [in] ranks list rank of server to which client connects to
-   */
-   void CContextClient::unlockBuffers(list<int>& ranks)
-   {
-      list<int>::iterator it;
-      for (it = ranks.begin(); it != ranks.end(); it++) buffers[*it]->unlockBuffer();
-   }
-      
-   /*!
-   Verify state of buffers corresponding to a connection
-   \param [in] ranks list rank of server to which client connects to
-   \return state of buffers, pending(true), ready(false)
-   */
-   bool CContextClient::checkBuffers(list<int>& ranks)
-   {
-      list<int>::iterator it;
-      bool pending = false;
-      for (it = ranks.begin(); it != ranks.end(); it++) pending |= buffers[*it]->checkBuffer(!pureOneSided);
-      return pending;
-   }
-
-   /*!
-    * Set the buffer size for each connection. Warning: This function is collective.
-    *
-    * \param [in] mapSize maps the rank of the connected servers to the size of the correspoinding buffer
-    * \param [in] maxEventSize maps the rank of the connected servers to the size of the biggest event
-   */
-   void CContextClient::setBufferSize(const std::map<int,StdSize>& mapSize)
-   {
-     setFixedBuffer() ;
-     for(auto& it : mapSize)
-     {
-      size_t size=std::max(CXios::minBufferSize*1.0,std::min(it.second*CXios::bufferSizeFactor*1.01,CXios::maxBufferSize*1.0)) ;
-      mapBufferSize_[it.first]=size ;
-      if (buffers.count(it.first)>0) buffers[it.first]->fixBufferSize(size);
-     }
-   }
-
-  /*!
-  Get leading server in the group of connected server
-  \return ranks of leading servers
-  */
-  const std::list<int>& CContextClient::getRanksServerNotLeader(void) const
-  {
-    return ranksServerNotLeader;
-  }
-
-  /*!
-  Check if client connects to leading server
-  \return connected(true), not connected (false)
-  */
-  bool CContextClient::isServerNotLeader(void) const
-  {
-    return !ranksServerNotLeader.empty();
-  }
-
-  /*!
-  Get leading server in the group of connected server
-  \return ranks of leading servers
-  */
-  const std::list<int>& CContextClient::getRanksServerLeader(void) const
-  {
-    return ranksServerLeader;
-  }
-
-  /*!
-  Check if client connects to leading server
-  \return connected(true), not connected (false)
-  */
-  bool CContextClient::isServerLeader(void) const
-  {
-    return !ranksServerLeader.empty();
-  }
-
-   /*!
-   * Finalize context client and do some reports. Function is non-blocking.
-   */
-  void CContextClient::finalize(void)
-  {
-    map<int,CClientBuffer*>::iterator itBuff;
-    std::list<int>::iterator ItServerLeader; 
-    
-    bool stop = false;
-
-    int* nbServerConnectionLocal  = new int[serverSize] ;
-    int* nbServerConnectionGlobal  = new int[serverSize] ;
-    for(int i=0;i<serverSize;++i) nbServerConnectionLocal[i]=0 ;
-    for (itBuff = buffers.begin(); itBuff != buffers.end(); itBuff++)  nbServerConnectionLocal[itBuff->first]=1 ;
-    for (ItServerLeader = ranksServerLeader.begin(); ItServerLeader != ranksServerLeader.end(); ItServerLeader++)  nbServerConnectionLocal[*ItServerLeader]=1 ;
-    
-    MPI_Allreduce(nbServerConnectionLocal, nbServerConnectionGlobal, serverSize, MPI_INT, MPI_SUM, intraComm);
-    
-    CEventClient event(CContext::GetType(), CContext::EVENT_ID_CONTEXT_FINALIZE);
-    CMessage msg;
-
-    for (int i=0;i<serverSize;++i) if (nbServerConnectionLocal[i]==1) event.push(i, nbServerConnectionGlobal[i], msg) ;
-    sendEvent(event);
-
-    delete[] nbServerConnectionLocal ;
-    delete[] nbServerConnectionGlobal ;
-
-
-    CTimer::get("Blocking time").resume();
-    checkBuffers();
-    CTimer::get("Blocking time").suspend();
-
-    std::map<int,StdSize>::const_iterator itbMap = mapBufferSize_.begin(),
-                                          iteMap = mapBufferSize_.end(), itMap;
-
-    StdSize totalBuf = 0;
-    for (itMap = itbMap; itMap != iteMap; ++itMap)
-    {
-      report(10) << " Memory report : Context <" << context_->getId() << "> : client side : memory used for buffer of each connection to server" << endl
-                 << "  +) To server with rank " << itMap->first << " : " << itMap->second << " bytes " << endl;
-      totalBuf += itMap->second;
-    }
-    report(0) << " Memory report : Context <" << context_->getId() << "> : client side : total memory used for buffer " << totalBuf << " bytes" << endl;
-
-  }
-
-
-  /*!
-  */
-  bool CContextClient::havePendingRequests(void)
-  {
-    bool pending = false;
-    map<int,CClientBuffer*>::iterator itBuff;
-    for (itBuff = buffers.begin(); itBuff != buffers.end(); itBuff++)
-      pending |= itBuff->second->hasPendingRequest();
-    return pending;
-  }
-  
-  bool CContextClient::havePendingRequests(list<int>& ranks)
-  {
-      list<int>::iterator it;
-      bool pending = false;
-      for (it = ranks.begin(); it != ranks.end(); it++) pending |= buffers[*it]->hasPendingRequest();
-      return pending;
-  }
-
-  bool CContextClient::isNotifiedFinalized(void)
-  {
-    if (isAttachedModeEnabled()) return true ;
-
-    bool finalized = true;
-    map<int,CClientBuffer*>::iterator itBuff;
-    for (itBuff = buffers.begin(); itBuff != buffers.end(); itBuff++)
-      finalized &= itBuff->second->isNotifiedFinalized();
-    return finalized;
-  }
-
-}
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/context_client.hpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/context_client.hpp	(revision 2342)
+++ 	(revision )
@@ -1,138 +1,0 @@
-#ifndef __CONTEXT_CLIENT_HPP__
-#define __CONTEXT_CLIENT_HPP__
-
-#include "xios_spl.hpp"
-#include "buffer_out.hpp"
-#include "buffer_in.hpp"
-#include "buffer_client.hpp"
-#include "event_client.hpp"
-#include "event_server.hpp"
-#include "mpi.hpp"
-#include "registry.hpp"
-
-namespace xios
-{
-  class CContext;
-  class CContextServer ;
-  /*!
-  \class CContextClient
-  A context can be both on client and on server side. In order to differenciate the role of
-  context on each side, e.x client sending events, server receiving and processing events, there is a need of
-  concrete "context" classes for both sides.
-  CContextClient processes and sends events from client to server where CContextServer receives these events
-  and processes them.
-  */
-  class CContextClient
-  {
-    public:
-      // Contructor
-      CContextClient(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer = 0);
-
-      // Send event to server
-      void sendEvent(CEventClient& event);
-      void waitEvent(list<int>& ranks);
-      void waitEvent_old(list<int>& ranks);
-
-      // Functions to set/get buffers
-      bool getBuffers(const size_t timeLine, const list<int>& serverList, const list<int>& sizeList, list<CBufferOut*>& retBuffers, bool nonBlocking = false);
-      void newBuffer(int rank);
-      bool checkBuffers(list<int>& ranks);
-      bool checkBuffers(void);
-      void eventLoop(void) ;
-      void callGlobalEventLoop() ;
-      void releaseBuffers(void);
-      bool havePendingRequests(void);
-      bool havePendingRequests(list<int>& ranks) ;
-
-      bool isServerLeader(void) const;
-      bool isServerNotLeader(void) const;
-      const std::list<int>& getRanksServerLeader(void) const;
-      const std::list<int>& getRanksServerNotLeader(void) const;
-
-  /*!
-   * Check if the attached mode is used.
-   *
-   * \return true if and only if attached mode is used
-   */
-      bool isAttachedModeEnabled() const { return isAttached_ ; } 
-
-      static void computeLeader(int clientRank, int clientSize, int serverSize,
-                                std::list<int>& rankRecvLeader,
-                                std::list<int>& rankRecvNotLeader);
-
-      // Close and finalize context client
-//      void closeContext(void);  Never been implemented.
-      bool isNotifiedFinalized(void) ;
-      void finalize(void);
-
-      void setBufferSize(const std::map<int,StdSize>& mapSize);
-
-      int getRemoteSize(void) {return serverSize;}
-      int getServerSize(void) {return serverSize;}
-      MPI_Comm getIntraComm(void)  {return intraComm ;} 
-      int getIntraCommSize(void) {return clientSize ;}
-      int getIntraCommRank(void) {return clientRank ;}
-
-      /*! set the associated server (dual chanel client/server) */      
-      void setAssociatedServer(CContextServer* associatedServer) { associatedServer=associatedServer_;}
-      /*! get the associated server (dual chanel client/server) */      
-      CContextServer* getAssociatedServer(void) { return associatedServer_;}
-      void setGrowableBuffer(void) { isGrowableBuffer_=true;}
-      void setFixedBuffer(void) { isGrowableBuffer_=false;}
-    public:
-      CContext* context_; //!< Context for client
-
-      size_t timeLine; //!< Timeline of each event
-
-      int clientRank; //!< Rank of current client
-
-      int clientSize; //!< Size of client group
-
-      int serverSize; //!< Size of server group
-
-      MPI_Comm interComm; //!< Communicator of server group (interCommunicator)
-
-      MPI_Comm interCommMerged_; //!< Communicator of the client group + server group (intraCommunicator) needed for one sided communication.
-      MPI_Comm commSelf_ ; //!< Communicator for proc alone from interCommMerged 
-
-      MPI_Comm intraComm; //!< Communicator of client group
-
-      map<int,CClientBuffer*> buffers; //!< Buffers for connection to servers
-
-      bool pureOneSided ; //!< if true, client will communicated with servers only trough one sided communication. Otherwise the hybrid mode P2P /One sided is used.
-
-      size_t hashId_ ; //!< hash id on the context client that will be used for context server to identify the remote calling context client.
-
-    private:
-      void lockBuffers(list<int>& ranks) ;
-      void unlockBuffers(list<int>& ranks) ;
-      
-      //! Mapping of server and buffer size for each connection to server
-      std::map<int,StdSize> mapBufferSize_;
-      //! Maximum event sizes estimated for each connection to server
-      std::map<int,StdSize> maxEventSizes;
-      //! Maximum number of events that can be buffered
-      StdSize maxBufferedEvents;
-
-      //! Context for server (Only used in attached mode)
-      CContext* parentServer;
-
-      //! List of server ranks for which the client is leader
-      std::list<int> ranksServerLeader;
-
-      //! List of server ranks for which the client is not leader
-      std::list<int> ranksServerNotLeader;
-
-      std::map<int, MPI_Comm> winComm_ ; //! Window communicators
-      std::map<int, std::vector<MPI_Win> >windows_ ; //! one sided mpi windows to expose client buffers to servers == windows[nbServers][2]
-      bool isAttached_ ;
-      CContextServer* associatedServer_ ; //!< The server associated to the pair client/server
-      bool isGrowableBuffer_ = true ;
-
-      double latency_=0e-2 ;
-
-      bool locked_ = false ; //!< The context client is locked to avoid recursive checkBuffer
-  };
-}
-
-#endif // __CONTEXT_CLIENT_HPP__
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/context_server.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/context_server.cpp	(revision 2342)
+++ 	(revision )
@@ -1,504 +1,0 @@
-#include "context_server.hpp"
-#include "buffer_in.hpp"
-#include "type.hpp"
-#include "context.hpp"
-#include "object_template.hpp"
-#include "group_template.hpp"
-#include "attribute_template.hpp"
-#include "domain.hpp"
-#include "field.hpp"
-#include "file.hpp"
-#include "grid.hpp"
-#include "mpi.hpp"
-#include "tracer.hpp"
-#include "timer.hpp"
-#include "cxios.hpp"
-#include "event_scheduler.hpp"
-#include "server.hpp"
-#include "servers_ressource.hpp"
-#include "pool_ressource.hpp"
-#include "services.hpp"
-#include "contexts_manager.hpp"
-#include "timeline_events.hpp"
-
-#include <boost/functional/hash.hpp>
-#include <random>
-#include <chrono>
-
-
-namespace xios
-{
-  using namespace std ;
-
-  CContextServer::CContextServer(CContext* parent,MPI_Comm intraComm_,MPI_Comm interComm_) 
-    : eventScheduler_(nullptr), isProcessingEvent_(false), associatedClient_(nullptr)
-  {
-    context=parent;
-    intraComm=intraComm_;
-    MPI_Comm_size(intraComm,&intraCommSize);
-    MPI_Comm_rank(intraComm,&intraCommRank);
-
-    interComm=interComm_;
-    int flag;
-    MPI_Comm_test_inter(interComm,&flag);
-
-    if (flag) attachedMode=false ;
-    else  attachedMode=true ;
-    
-    if (flag) MPI_Comm_remote_size(interComm,&clientSize_);
-    else  MPI_Comm_size(interComm,&clientSize_);
-
-   
-    SRegisterContextInfo contextInfo ;
-    CXios::getContextsManager()->getContextInfo(context->getId(), contextInfo, intraComm) ;
-
-  //  if (contextInfo.serviceType != CServicesManager::CLIENT) // we must have an event scheduler => to be retrieve from the associated services
-  //  {
-      //if (!isAttachedModeEnabled()) eventScheduler_=CXios::getPoolRessource()->getService(contextInfo.serviceId,contextInfo.partitionId)->getEventScheduler() ;
-    eventScheduler_=CXios::getPoolRessource()->getService(contextInfo.serviceId,contextInfo.partitionId)->getEventScheduler() ;
-    MPI_Comm_dup(intraComm, &processEventBarrier_) ;
-  //  }
-
-
-    currentTimeLine=1;
-    scheduled=false;
-    finished=false;
-
-    // generate unique hash for server
-    auto time=chrono::system_clock::now().time_since_epoch().count() ;
-    std::default_random_engine rd(time); // not reproducible from a run to another
-    std::uniform_int_distribution<size_t> dist;
-    hashId=dist(rd) ;
-    MPI_Bcast(&hashId,1,MPI_SIZE_T,0,intraComm) ; // Bcast to all server of the context
-
-
-    if (!isAttachedModeEnabled()) MPI_Intercomm_merge(interComm_,true,&interCommMerged_) ;
-    MPI_Comm_split(intraComm_, intraCommRank, intraCommRank, &commSelf_) ; // for windows
-    
-    itLastTimeLine=lastTimeLine.begin() ;
-
-    pureOneSided=CXios::getin<bool>("pure_one_sided",false); // pure one sided communication (for test)
-    if (isAttachedModeEnabled()) pureOneSided=false ; // no one sided in attach mode
-      
-  }
-
-//! Attached mode is used ?
-//! \return true if attached mode is used, false otherwise
-  bool CContextServer::isAttachedModeEnabled() const
-  {
-    return attachedMode ;
-  }
-  
-  void CContextServer::setPendingEvent(void)
-  {
-    pendingEvent=true;
-  }
-
-  bool CContextServer::hasPendingEvent(void)
-  {
-    return pendingEvent;
-  }
-
-  bool CContextServer::hasFinished(void)
-  {
-    return finished;
-  }
-
-  bool CContextServer::eventLoop(bool enableEventsProcessing /*= true*/)
-  {
-    CTimer::get("listen request").resume();
-    listen();
-    CTimer::get("listen request").suspend();
-    CTimer::get("check pending request").resume();
-    checkPendingRequest();
-    checkPendingProbe() ;
-    CTimer::get("check pending request").suspend();
-    CTimer::get("check event process").resume();
-    processEvents(enableEventsProcessing);
-    CTimer::get("check event process").suspend();
-    return finished;
-  }
-
- void CContextServer::listen(void)
-  {
-    int rank;
-    int flag;
-    int count;
-    char * addr;
-    MPI_Status status;
-    MPI_Message message ;
-    map<int,CServerBuffer*>::iterator it;
-    bool okLoop;
-
-    traceOff();
-    MPI_Improbe(MPI_ANY_SOURCE, 20,interComm,&flag,&message, &status);
-    traceOn();
-    if (flag==true) listenPendingRequest(message, status) ;
-  }
-
-  bool CContextServer::listenPendingRequest( MPI_Message &message, MPI_Status& status)
-  {
-    int count;
-    char * addr;
-    map<int,CServerBuffer*>::iterator it;
-    int rank=status.MPI_SOURCE ;
-
-    it=buffers.find(rank);
-    if (it==buffers.end()) // Receive the buffer size and allocate the buffer
-    {
-      MPI_Aint recvBuff[4] ;
-      MPI_Mrecv(recvBuff, 4, MPI_AINT,  &message, &status);
-      remoteHashId_ = recvBuff[0] ;
-      StdSize buffSize = recvBuff[1];
-      vector<MPI_Aint> winAdress(2) ;
-      winAdress[0]=recvBuff[2] ; winAdress[1]=recvBuff[3] ;
-      mapBufferSize_.insert(std::make_pair(rank, buffSize));
-
-      // create windows dynamically for one-sided
-      if (!isAttachedModeEnabled())
-      { 
-        CTimer::get("create Windows").resume() ;
-        MPI_Comm interComm ;
-        MPI_Intercomm_create(commSelf_, 0, interCommMerged_, rank, 0 , &interComm) ;
-        MPI_Intercomm_merge(interComm, true, &winComm_[rank]) ;
-        CXios::getMpiGarbageCollector().registerCommunicator(winComm_[rank]) ;
-        MPI_Comm_free(&interComm) ;
-        windows_[rank].resize(2) ;
-        MPI_Win_create_dynamic(MPI_INFO_NULL, winComm_[rank], &windows_[rank][0]);
-        CXios::getMpiGarbageCollector().registerWindow(windows_[rank][0]) ;
-        MPI_Win_create_dynamic(MPI_INFO_NULL, winComm_[rank], &windows_[rank][1]);
-        CXios::getMpiGarbageCollector().registerWindow(windows_[rank][1]) ;
-        CTimer::get("create Windows").suspend() ;
-        MPI_Barrier(winComm_[rank]) ;
-      }
-      else
-      {
-        winComm_[rank] = MPI_COMM_NULL ;
-        windows_[rank].resize(2) ;
-        windows_[rank][0] = MPI_WIN_NULL ;
-        windows_[rank][1] = MPI_WIN_NULL ;
-      }   
-
-      it=(buffers.insert(pair<int,CServerBuffer*>(rank,new CServerBuffer(windows_[rank], winAdress, 0, buffSize)))).first;
-      lastTimeLine[rank]=0 ;
-      itLastTimeLine=lastTimeLine.begin() ;
-
-      return true;
-    }
-    else
-    {
-        std::pair<MPI_Message,MPI_Status> mypair(message,status) ;
-        pendingProbe[rank].push_back(mypair) ;
-        return false;
-    }
-  }
-
-  void CContextServer::checkPendingProbe(void)
-  {
-    
-    list<int> recvProbe ;
-    list<int>::iterator itRecv ;
-    map<int, list<std::pair<MPI_Message,MPI_Status> > >::iterator itProbe;
-
-    for(itProbe=pendingProbe.begin();itProbe!=pendingProbe.end();itProbe++)
-    {
-      int rank=itProbe->first ;
-      if (pendingRequest.count(rank)==0)
-      {
-        MPI_Message& message = itProbe->second.front().first ;
-        MPI_Status& status = itProbe->second.front().second ;
-        int count ;
-        MPI_Get_count(&status,MPI_CHAR,&count);
-        map<int,CServerBuffer*>::iterator it = buffers.find(rank);
-        if ( (it->second->isBufferFree(count) && !it->second->isResizing()) // accept new request if buffer is free
-          || (it->second->isResizing() && it->second->isBufferEmpty()) )    // or if resizing wait for buffer is empty
-        {
-          char * addr;
-          addr=(char*)it->second->getBuffer(count);
-          MPI_Imrecv(addr,count,MPI_CHAR, &message, &pendingRequest[rank]);
-          bufferRequest[rank]=addr;
-          recvProbe.push_back(rank) ;
-          itProbe->second.pop_front() ;
-        }
-      }
-    }
-
-    for(itRecv=recvProbe.begin(); itRecv!=recvProbe.end(); itRecv++) if (pendingProbe[*itRecv].empty()) pendingProbe.erase(*itRecv) ;
-  }
-
-
-  void CContextServer::checkPendingRequest(void)
-  {
-    map<int,MPI_Request>::iterator it;
-    list<int> recvRequest;
-    list<int>::iterator itRecv;
-    int rank;
-    int flag;
-    int count;
-    MPI_Status status;
-   
-    if (!pendingRequest.empty()) CTimer::get("receiving requests").resume();
-    else CTimer::get("receiving requests").suspend();
-
-    for(it=pendingRequest.begin();it!=pendingRequest.end();it++)
-    {
-      rank=it->first;
-      traceOff();
-      MPI_Test(& it->second, &flag, &status);
-      traceOn();
-      if (flag==true)
-      {
-        buffers[rank]->updateCurrentWindows() ;
-        recvRequest.push_back(rank);
-        MPI_Get_count(&status,MPI_CHAR,&count);
-        processRequest(rank,bufferRequest[rank],count);
-      }
-    }
-
-    for(itRecv=recvRequest.begin();itRecv!=recvRequest.end();itRecv++)
-    {
-      pendingRequest.erase(*itRecv);
-      bufferRequest.erase(*itRecv);
-    }
-  }
-
-  void CContextServer::getBufferFromClient(size_t timeLine)
-  {
-    CTimer::get("CContextServer::getBufferFromClient").resume() ;
-    if (!isAttachedModeEnabled()) // one sided desactivated in attached mode
-    {  
-      int rank ;
-      char *buffer ;
-      size_t count ; 
-
-      if (itLastTimeLine==lastTimeLine.end()) itLastTimeLine=lastTimeLine.begin() ;
-      for(;itLastTimeLine!=lastTimeLine.end();++itLastTimeLine)
-      {
-        rank=itLastTimeLine->first ;
-        if (itLastTimeLine->second < timeLine &&  pendingRequest.count(rank)==0 && buffers[rank]->isBufferEmpty())
-        {
-          if (buffers[rank]->getBufferFromClient(timeLine, buffer, count)) processRequest(rank, buffer, count);
-          if (count >= 0) ++itLastTimeLine ;
-          break ;
-        }
-      }
-    }
-    CTimer::get("CContextServer::getBufferFromClient").suspend() ;
-  }
-         
-       
-  void CContextServer::processRequest(int rank, char* buff,int count)
-  {
-
-    CBufferIn buffer(buff,count);
-    char* startBuffer,endBuffer;
-    int size, offset;
-    size_t timeLine=0;
-    map<size_t,CEventServer*>::iterator it;
-
-    
-    CTimer::get("Process request").resume();
-    while(count>0)
-    {
-      char* startBuffer=(char*)buffer.ptr();
-      CBufferIn newBuffer(startBuffer,buffer.remain());
-      newBuffer>>size>>timeLine;
-
-      if (timeLine==timelineEventNotifyChangeBufferSize)
-      {
-        buffers[rank]->notifyBufferResizing() ;
-        buffers[rank]->updateCurrentWindows() ;
-        buffers[rank]->popBuffer(count) ;
-        info(100)<<"Context id "<<context->getId()<<" : Receive NotifyChangeBufferSize from client rank "<<rank<<endl
-                 <<"isBufferEmpty ? "<<buffers[rank]->isBufferEmpty()<<"  remaining count : "<<buffers[rank]->getUsed()<<endl;
-      } 
-      else if (timeLine==timelineEventChangeBufferSize)
-      {
-        size_t newSize ;
-        vector<MPI_Aint> winAdress(2) ;
-        newBuffer>>newSize>>winAdress[0]>>winAdress[1] ;
-        buffers[rank]->freeBuffer(count) ;
-        delete buffers[rank] ;
-        buffers[rank] = new CServerBuffer(windows_[rank], winAdress, 0, 2*newSize) ;
-        info(100)<<"Context id "<<context->getId()<<" : Receive ChangeBufferSize from client rank "<<rank
-                 <<"  newSize : "<<newSize<<" Address : "<<winAdress[0]<<" & "<<winAdress[1]<<endl ;
-      }
-      else
-      {
-        info(100)<<"Context id "<<context->getId()<<" : Receive standard event from client rank "<<rank<<"  with timeLine : "<<timeLine<<endl ;
-        it=events.find(timeLine);
-        if (it==events.end()) it=events.insert(pair<int,CEventServer*>(timeLine,new CEventServer(this))).first;
-        it->second->push(rank,buffers[rank],startBuffer,size);
-        if (timeLine>0) lastTimeLine[rank]=timeLine ;
-      }
-      buffer.advance(size);
-      count=buffer.remain();
-    }
-    
-    CTimer::get("Process request").suspend();
-  }
-
-  void CContextServer::processEvents(bool enableEventsProcessing)
-  {
-    map<size_t,CEventServer*>::iterator it;
-    CEventServer* event;
-    
-//    if (context->isProcessingEvent()) return ;
-    if (isProcessingEvent_) return ;
-    if (isAttachedModeEnabled())
-      if (!CXios::getDaemonsManager()->isScheduledContext(remoteHashId_)) return ;
-
-    it=events.find(currentTimeLine);
-    if (it!=events.end())
-    {
-      event=it->second;
-
-      if (event->isFull())
-      {
-        if (!scheduled && !isAttachedModeEnabled()) // Skip event scheduling for attached mode and reception on client side
-        {
-          eventScheduler_->registerEvent(currentTimeLine,hashId);
-          scheduled=true;
-        }
-        else if (isAttachedModeEnabled() || eventScheduler_->queryEvent(currentTimeLine,hashId) )
-        {
-          if (!enableEventsProcessing && isCollectiveEvent(*event)) return ;
-
-          if (!eventScheduled_) 
-          {
-            MPI_Ibarrier(processEventBarrier_,&processEventRequest_) ;
-            eventScheduled_=true ;
-            return ;
-          }
-          else 
-          {
-            MPI_Status status ;
-            int flag ;
-            MPI_Test(&processEventRequest_, &flag, &status) ;
-            if (!flag) return ;
-            eventScheduled_=false ;
-          }
-
-          if (!isAttachedModeEnabled()) eventScheduler_->popEvent() ;
-          //MPI_Barrier(intraComm) ;
-         // When using attached mode, synchronise the processes to avoid that differents event be scheduled by differents processes
-         // The best way to properly solve this problem will be to use the event scheduler also in attached mode
-         // for now just set up a MPI barrier
-//ym to be check later
-//         if (!eventScheduler_ && CXios::isServer) MPI_Barrier(intraComm) ;
-
-//         context->setProcessingEvent() ;
-         isProcessingEvent_=true ;
-         CTimer::get("Process events").resume();
-         info(100)<<"Context id "<<context->getId()<<" : Process Event "<<currentTimeLine<<" of class "<<event->classId<<" of type "<<event->type<<endl ;
-         dispatchEvent(*event);
-         CTimer::get("Process events").suspend();
-         isProcessingEvent_=false ;
-//         context->unsetProcessingEvent() ;
-         pendingEvent=false;
-         delete event;
-         events.erase(it);
-         currentTimeLine++;
-         scheduled = false;
-         if (isAttachedModeEnabled()) CXios::getDaemonsManager()->unscheduleContext() ;
-        }
-      }
-      else if (pendingRequest.empty()) getBufferFromClient(currentTimeLine) ;
-    }
-    else if (pendingRequest.empty()) getBufferFromClient(currentTimeLine) ; // if pure one sided check buffer even if no event recorded at current time line
-  }
-
-  CContextServer::~CContextServer()
-  {
-    map<int,CServerBuffer*>::iterator it;
-    for(it=buffers.begin();it!=buffers.end();++it) delete it->second;
-    buffers.clear() ;
-  }
-
-  void CContextServer::releaseBuffers()
-  {
-    //for(auto it=buffers.begin();it!=buffers.end();++it) delete it->second ;
-    //buffers.clear() ; 
-    freeWindows() ;
-  }
-
-  void CContextServer::freeWindows()
-  {
-    //if (!isAttachedModeEnabled())
-    //{
-    //  for(auto& it : winComm_)
-    //  {
-    //    int rank = it.first ;
-    //    MPI_Win_free(&windows_[rank][0]);
-    //    MPI_Win_free(&windows_[rank][1]);
-    //    MPI_Comm_free(&winComm_[rank]) ;
-    //  }
-    //}
-  }
-
-  void CContextServer::notifyClientsFinalize(void)
-  {
-    for(auto it=buffers.begin();it!=buffers.end();++it)
-    {
-      it->second->notifyClientFinalize() ;
-    }
-  }
-
-  void CContextServer::dispatchEvent(CEventServer& event)
-  {
-    string contextName;
-    string buff;
-    int MsgSize;
-    int rank;
-    list<CEventServer::SSubEvent>::iterator it;
-    StdString ctxId = context->getId();
-    CContext::setCurrent(ctxId);
-    StdSize totalBuf = 0;
-
-    if (event.classId==CContext::GetType() && event.type==CContext::EVENT_ID_CONTEXT_FINALIZE)
-    {
-      finished=true;
-      info(20)<<" CContextServer: Receive context <"<<context->getId()<<"> finalize."<<endl;
-      notifyClientsFinalize() ;
-      CTimer::get("receiving requests").suspend();
-      context->finalize();
-      
-      std::map<int, StdSize>::const_iterator itbMap = mapBufferSize_.begin(),
-                           iteMap = mapBufferSize_.end(), itMap;
-      for (itMap = itbMap; itMap != iteMap; ++itMap)
-      {
-        rank = itMap->first;
-        report(10)<< " Memory report : Context <"<<ctxId<<"> : server side : memory used for buffer of each connection to client" << endl
-            << "  +) With client of rank " << rank << " : " << itMap->second << " bytes " << endl;
-        totalBuf += itMap->second;
-      }
-      report(0)<< " Memory report : Context <"<<ctxId<<"> : server side : total memory used for buffer "<<totalBuf<<" bytes"<<endl;
-    }
-    else if (event.classId==CContext::GetType()) CContext::dispatchEvent(event);
-    else if (event.classId==CContextGroup::GetType()) CContextGroup::dispatchEvent(event);
-    else if (event.classId==CCalendarWrapper::GetType()) CCalendarWrapper::dispatchEvent(event);
-    else if (event.classId==CDomain::GetType()) CDomain::dispatchEvent(event);
-    else if (event.classId==CDomainGroup::GetType()) CDomainGroup::dispatchEvent(event);
-    else if (event.classId==CAxis::GetType()) CAxis::dispatchEvent(event);
-    else if (event.classId==CAxisGroup::GetType()) CAxisGroup::dispatchEvent(event);
-    else if (event.classId==CScalar::GetType()) CScalar::dispatchEvent(event);
-    else if (event.classId==CScalarGroup::GetType()) CScalarGroup::dispatchEvent(event);
-    else if (event.classId==CGrid::GetType()) CGrid::dispatchEvent(event);
-    else if (event.classId==CGridGroup::GetType()) CGridGroup::dispatchEvent(event);
-    else if (event.classId==CField::GetType()) CField::dispatchEvent(event);
-    else if (event.classId==CFieldGroup::GetType()) CFieldGroup::dispatchEvent(event);
-    else if (event.classId==CFile::GetType()) CFile::dispatchEvent(event);
-    else if (event.classId==CFileGroup::GetType()) CFileGroup::dispatchEvent(event);
-    else if (event.classId==CVariable::GetType()) CVariable::dispatchEvent(event);
-    else
-    {
-      ERROR("void CContextServer::dispatchEvent(CEventServer& event)",<<" Bad event class Id"<<endl);
-    }
-  }
-
-  bool CContextServer::isCollectiveEvent(CEventServer& event)
-  {
-    if (event.type>1000) return false ;
-    else return true ;
-  }
-}
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/context_server.hpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/context_server.hpp	(revision 2342)
+++ 	(revision )
@@ -1,90 +1,0 @@
-#ifndef __CONTEXT_SERVER_HPP__
-#define __CONTEXT_SERVER_HPP__
-#include "xios_spl.hpp"
-#include "event_server.hpp"
-#include "buffer_server.hpp"
-#include "mpi.hpp"
-#include "event_scheduler.hpp"
-
-namespace xios
-{
-  class CContext ;
-  class CContextClient;
-
-  class CContextServer
-  {
-    public:
-
-    CContextServer(CContext* parent,MPI_Comm intraComm,MPI_Comm interComm) ;
-    bool eventLoop(bool enableEventsProcessing = true);
-    void listen(void) ;
-//    bool listenPendingRequest(MPI_Status& status) ;
-    bool listenPendingRequest(MPI_Message &message, MPI_Status& status) ;
-    void checkPendingProbe(void) ;
-    void checkPendingRequest(void) ;
-    void getBufferFromClient(size_t timeLine) ;
-    void processRequest(int rank, char* buff,int count) ;
-    void processEvents(bool enableEventsProcessing) ;
-    bool hasFinished(void);
-    void dispatchEvent(CEventServer& event) ;
-    bool isCollectiveEvent(CEventServer& event) ;
-    void setPendingEvent(void) ;
-    bool hasPendingEvent(void) ;
-    bool isAttachedModeEnabled() const;
-    void releaseBuffers(void) ;
-    void notifyClientsFinalize(void) ;
-    void freeWindows(void) ; // !<< free Windows for one sided communication
-    
-    MPI_Comm intraComm ;
-    int intraCommSize ;
-    int intraCommRank ;
-
-    MPI_Comm interComm ;
-    int commSize ;
-    int clientSize_ ;
-
-    MPI_Comm interCommMerged_; //!< Communicator of the client group + server group (intraCommunicator) needed for one sided communication.
-    MPI_Comm commSelf_ ; //!< Communicator for proc alone from interCommMerged 
-
-    map<int,CServerBuffer*> buffers ;
-    map<int,size_t> lastTimeLine ; //!< last event time line for a processed request
-    map<int,size_t>::iterator itLastTimeLine ; //!< iterator on lastTimeLine
-    map<int, list<std::pair<MPI_Message,MPI_Status> > > pendingProbe;
-    map<int,MPI_Request> pendingRequest ;
-    map<int,char*> bufferRequest ;
-
-    map<size_t,CEventServer*> events ;
-    size_t currentTimeLine ;
-    CContext* context ;
-      
-    bool finished ;
-    bool pendingEvent ;
-    bool scheduled  ;    /*!< event of current timeline is alreading scheduled ? */
-    bool attachedMode ;  //! true if attached mode is enabled otherwise false
-    bool pureOneSided ; //!< if true, client will communicated with servers only trough one sided communication. Otherwise the hybrid mode P2P /One sided is used.
-         
-    size_t hashId ;
-
-    void setAssociatedClient(CContextClient* associatedClient) {associatedClient_=associatedClient ;}
-    CContextClient* getAssociatedClient(void) { return associatedClient_ ;}
-
-    ~CContextServer() ;
-
-    private:
-  
-      std::map<int, StdSize> mapBufferSize_;
-      std::map<int,MPI_Comm> winComm_ ; //! Window communicators
-      std::map<int,std::vector<MPI_Win> >windows_ ; //! one sided mpi windows to expose client buffers to servers ; No memory will be attached on server side.
-      CEventScheduler* eventScheduler_ ;
-      bool isProcessingEvent_ ;
-      CContextClient* associatedClient_ ;
-      size_t remoteHashId_; //!< the hash is of the calling context client
-      
-      MPI_Comm processEventBarrier_ ;
-      bool eventScheduled_=false;
-      MPI_Request processEventRequest_ ;
-  } ;
-
-}
-
-#endif
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/event_client.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/event_client.cpp	(revision 2342)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/event_client.cpp	(revision 2343)
@@ -56,3 +56,6 @@
      }
    }
+
+   void CEventClient::send(size_t timeLine, int size, CBufferOut* buffer) { *buffer << size << timeLine << *itNbSenders << classId << typeId << **itMessages;}
+ 
 }
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/event_client.hpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/event_client.hpp	(revision 2342)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/event_client.hpp	(revision 2343)
@@ -17,5 +17,4 @@
       void push(int rank, int nbSender, CMessage& msg);
       void send(size_t timeLine, const std::list<int>& sizes, std::list<CBufferOut*>&); 
-
       bool isEmpty(void);
       std::list<int> getRanks(void);
@@ -24,4 +23,48 @@
       int getTypeId(void) { return typeId; }
       
+      void setFirst(void)
+      {
+        itRanks=ranks.begin() ;
+        itNbSenders=nbSenders.begin() ;
+        itMessages=messages.begin() ;
+      }
+
+      bool isFirst(void)
+      {
+        return itRanks==ranks.begin() ;
+      }
+
+      void next(void)
+      {
+        itRanks++ ;
+        if (itRanks==ranks.end()) itRanks=ranks.begin() ;
+        itNbSenders++ ;
+        if (itNbSenders==nbSenders.end()) itNbSenders=nbSenders.begin() ;
+        itMessages++ ;
+        if (itMessages==messages.end()) itMessages=messages.begin() ;
+      }
+      
+      void remove(void)
+      {
+        auto removedRank = itRanks;
+        itRanks++ ;
+        ranks.erase(removedRank) ;
+        if (itRanks==ranks.end()) itRanks=ranks.begin() ;
+
+        auto removedNbSender = itNbSenders ;
+        itNbSenders++ ;
+        nbSenders.erase(removedNbSender) ;
+        if (itNbSenders==nbSenders.end()) itNbSenders=nbSenders.begin() ;
+
+        auto removedMessage = itMessages ;
+        itMessages++ ;
+        messages.erase(removedMessage) ;
+        if (itMessages==messages.end()) itMessages=messages.begin() ;
+      }
+
+      int getRank(void) { return *itRanks ;}
+      int getNbSender(void) { return *itNbSenders ;}
+      int getSize(void) { return (*itMessages)->size() + headerSize;}
+      void send(size_t timeLine, int size, CBufferOut* buffer) ;
     private:
       int classId;
@@ -30,4 +73,8 @@
       std::list<int> nbSenders;
       std::list<CMessage*> messages;
+      
+      std::list<int>::iterator       itRanks;
+      std::list<int>::iterator       itNbSenders;
+      std::list<CMessage*>::iterator itMessages;
   };
 }
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/event_server.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/event_server.cpp	(revision 2342)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/event_server.cpp	(revision 2343)
@@ -35,4 +35,5 @@
     ev.buffer = new CBufferIn(buffer.ptr(), buffer.remain());
     ev.size = size;  
+    ev.startBuffer = startBuffer ; // for one sided, take ownership of buffer for now
     subEvents.push_back(ev);
   
@@ -44,4 +45,5 @@
     }
   }
+
 
   bool CEventServer::isFull(void)  
@@ -55,6 +57,14 @@
     for (it = subEvents.begin(); it != subEvents.end(); it++)
     {
-      it->serverBuffer->freeBuffer(it->size);
-      delete it->buffer;
+      if (it->serverBuffer==nullptr) // one_sided case
+      {
+        delete [] it->startBuffer ;
+        delete it->buffer;
+      }
+      else // legacy case
+      {
+        it->serverBuffer->freeBuffer(it->size);
+        delete it->buffer;
+      }
     }
   }
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/event_server.hpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/event_server.hpp	(revision 2342)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/event_server.hpp	(revision 2343)
@@ -21,4 +21,6 @@
 
     void push(int rank,CServerBuffer* serverBuffer ,char* startBuffer,int size) ;
+    int getNbSender(void) {return nbSender ;}
+
     CContextServer* getContextServer(void) { return contextServer_ ;}
     
@@ -26,4 +28,5 @@
     {
       int rank ;
+      char* startBuffer ;
       CServerBuffer* serverBuffer ;
       CBufferIn*  buffer ;
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.cpp	(revision 2342)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.cpp	(revision 2343)
@@ -190,6 +190,6 @@
      {
        // size estimation for sendDistributedValue
-       std::unordered_map<int, vector<size_t> >::const_iterator it, ite = indSrv_[client->serverSize].end();
-       for (it = indSrv_[client->serverSize].begin(); it != ite; ++it)
+       std::unordered_map<int, vector<size_t> >::const_iterator it, ite = indSrv_[client->getRemoteSize()].end();
+       for (it = indSrv_[client->getRemoteSize()].begin(); it != ite; ++it)
        {
          size_t size = 6 * sizeof(size_t);
@@ -890,7 +890,7 @@
     if (type==EDistributionType::BANDS) // Bands distribution to send to file server
     {
-      int nbServer = client->serverSize;
-      int nbClient = client->clientSize ;
-      int rankClient = client->clientRank ;
+      int nbServer = client->getRemoteSize();
+      int nbClient = client->getIntraCommSize() ;
+      int rankClient = client->getIntraCommRank() ;
       int size = nbServer / nbClient ;
       int start ;
@@ -921,5 +921,5 @@
     else if (type==EDistributionType::NONE) // domain is not distributed ie all servers get the same local domain
     {
-      int nbServer = client->serverSize;
+      int nbServer = client->getRemoteSize();
       size_t nglo=n_glo ;
       CArray<size_t,1> indGlo(nglo) ;
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/context.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/node/context.cpp	(revision 2342)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/node/context.cpp	(revision 2343)
@@ -7,6 +7,8 @@
 #include "duration.hpp"
 
-#include "context_client.hpp"
-#include "context_server.hpp"
+#include "legacy_context_client.hpp"
+#include "legacy_context_server.hpp"
+#include "one_sided_context_client.hpp"
+#include "one_sided_context_server.hpp"
 #include "nc4_data_output.hpp"
 #include "node_type.hpp"
@@ -532,6 +534,6 @@
     comms.push_back(intraCommClient);
     // attached_mode=parentServerContext_->isAttachedMode() ; //ym probably inherited from source context
-    server = new CContextServer(this,intraComm_, interCommServer); // check if we need to dupl. intraComm_ ?
-    client = new CContextClient(this,intraCommClient,interCommClient);
+    server = CContextServer::getNew(this,intraComm_, interCommServer); // check if we need to dupl. intraComm_ ?
+    client = CContextClient::getNew(this,intraCommClient,interCommClient);
     client->setAssociatedServer(server) ;  
     server->setAssociatedClient(client) ;  
@@ -594,6 +596,6 @@
       intraCommClient=intraComm_ ;
       MPI_Comm_dup(intraComm_, &intraCommServer) ;
-      client = new CContextClient(this, intraCommClient, interCommClient);
-      server = new CContextServer(this, intraCommServer, interCommServer);
+      client = CContextClient::getNew(this, intraCommClient, interCommClient);
+      server = CContextServer::getNew(this, intraCommServer, interCommServer);
       client->setAssociatedServer(server) ;
       server->setAssociatedClient(client) ;
@@ -631,6 +633,6 @@
         MPI_Comm_dup(intraComm_, &intraCommServer) ;
 
-        CContextClient* client = new CContextClient(this, intraCommClient, interCommClient) ;
-        CContextServer* server = new CContextServer(this, intraCommServer, interCommServer) ;
+        CContextClient* client = CContextClient::getNew(this, intraCommClient, interCommClient) ;
+        CContextServer* server = CContextServer::getNew(this, intraCommServer, interCommServer) ;
         client->setAssociatedServer(server) ;
         server->setAssociatedClient(client) ;
@@ -728,6 +730,6 @@
         MPI_Comm_dup(interComm, &interCommClient) ;
         MPI_Comm_dup(interComm, &interCommServer) ;
-        CContextClient* client = new CContextClient(this, intraCommClient, interCommClient);
-        CContextServer* server = new CContextServer(this, intraCommServer, interCommServer);
+        CContextClient* client = CContextClient::getNew(this, intraCommClient, interCommClient);
+        CContextServer* server = CContextServer::getNew(this, intraCommServer, interCommServer);
         client->setAssociatedServer(server) ;
         server->setAssociatedClient(client) ;
@@ -750,6 +752,6 @@
        MPI_Comm_dup(interComm, &interCommServer) ;
        MPI_Comm_dup(interComm, &interCommClient) ;
-       CContextServer* server = new CContextServer(this, intraCommServer, interCommServer);
-       CContextClient* client = new CContextClient(this, intraCommClient, interCommClient);
+       CContextServer* server = CContextServer::getNew(this, intraCommServer, interCommServer);
+       CContextClient* client = CContextClient::getNew(this, intraCommClient, interCommClient);
        client->setAssociatedServer(server) ;
        server->setAssociatedClient(client) ;
@@ -765,5 +767,5 @@
    {
       registryOut->hierarchicalGatherRegistry() ;
-      if (server->intraCommRank==0) CXios::getRegistryManager()->merge(*registryOut) ;
+      if (server->getIntraCommRank()==0) CXios::getRegistryManager()->merge(*registryOut) ;
 
       if (serviceType_==CServicesManager::CLIENT)
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.cpp	(revision 2342)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.cpp	(revision 2343)
@@ -162,10 +162,10 @@
      }
 
-     std::unordered_map<int, vector<size_t> >::const_iterator itIndexEnd = indSrv_[client->serverSize].end();
+     std::unordered_map<int, vector<size_t> >::const_iterator itIndexEnd = indSrv_[client->getRemoteSize()].end();
      // std::map<int, std::vector<int> >::const_iterator itWrittenIndexEnd = indWrittenSrv_.end();
-     for (size_t k = 0; k < connectedServerRank_[client->serverSize].size(); ++k)
-     {
-       int rank = connectedServerRank_[client->serverSize][k];
-       std::unordered_map<int, std::vector<size_t> >::const_iterator it = indSrv_[client->serverSize].find(rank);
+     for (size_t k = 0; k < connectedServerRank_[client->getRemoteSize()].size(); ++k)
+     {
+       int rank = connectedServerRank_[client->getRemoteSize()][k];
+       std::unordered_map<int, std::vector<size_t> >::const_iterator it = indSrv_[client->getRemoteSize()].find(rank);
        size_t idxCount = (it != itIndexEnd) ? it->second.size() : 0;
 
@@ -1883,5 +1883,5 @@
     if (type==EDistributionType::BANDS) // Bands distribution to send to file server
     {
-      int nbServer = client->serverSize;
+      int nbServer = client->getRemoteSize();
       std::vector<int> nGlobDomain(2);
       nGlobDomain[0] = this->ni_glo;
@@ -1919,7 +1919,7 @@
     if (distType==EDistributionType::BANDS) // Bands distribution to send to file server
     {
-      int nbServer = client->serverSize;
-      int nbClient = client->clientSize ;
-      int rankClient = client->clientRank ;
+      int nbServer = client->getRemoteSize();
+      int nbClient = client->getIntraCommSize() ;
+      int rankClient = client->getIntraCommRank() ;
       int size = nbServer / nbClient ;
       int start ;
@@ -1952,7 +1952,7 @@
     else if (distType==EDistributionType::COLUMNS) // Bands distribution to send to file server
     {
-      int nbServer = client->serverSize;
-      int nbClient = client->clientSize ;
-      int rankClient = client->clientRank ;
+      int nbServer = client->getRemoteSize();
+      int nbClient = client->getIntraCommSize() ;
+      int rankClient = client->getIntraCommRank() ;
       int size = nbServer / nbClient ;
       int start ;
@@ -1988,5 +1988,5 @@
     else if (distType==EDistributionType::NONE) // domain is not distributed ie all servers get the same local domain
     {
-      int nbServer = client->serverSize;
+      int nbServer = client->getRemoteSize();
       int nglo=ni_glo*nj_glo ;
       CArray<size_t,1> indGlo ;
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.cpp	(revision 2342)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.cpp	(revision 2343)
@@ -944,5 +944,5 @@
 
      std::map<int, StdSize> dataSizes;
-     int receiverSize = client->serverSize;
+     int receiverSize = client->getRemoteSize();
      std::map<int,size_t>& dataSizeMap = bufferForWriting ? connectedDataSize_[receiverSize]: connectedDataSizeRead_;
      std::vector<int>& connectedServerRanks = bufferForWriting ? connectedServerRank_[receiverSize] : connectedServerRankRead_;
@@ -1395,5 +1395,5 @@
     else if (0 != client)
     {
-      return  (isDataDistributed() ||  (1 != client->clientSize) || (1 != client->serverSize));
+      return  (isDataDistributed() ||  (1 != client->getRemoteSize()) || (1 != client->getRemoteSize()));
     }
     else
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/scalar.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/node/scalar.cpp	(revision 2342)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/node/scalar.cpp	(revision 2343)
@@ -411,5 +411,5 @@
     else if (type==EDistributionType::NONE) // domain is not distributed ie all servers get the same local domain
     {
-      int nbServer = client->serverSize;
+      int nbServer = client->getRemoteSize();
       CArray<size_t,1> indGlo(nglo) ;
       for(size_t i=0;i<nglo;i++) indGlo(i) = i ;
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/context_client.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/context_client.cpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/context_client.cpp	(revision 2343)
@@ -0,0 +1,166 @@
+#include "xios_spl.hpp"
+#include "context_client.hpp"
+#include "context_server.hpp"
+#include "event_client.hpp"
+#include "buffer_out.hpp"
+#include "buffer_client.hpp"
+#include "type.hpp"
+#include "event_client.hpp"
+#include "context.hpp"
+#include "mpi.hpp"
+#include "timer.hpp"
+#include "cxios.hpp"
+#include "server.hpp"
+#include "services.hpp"
+#include <boost/functional/hash.hpp>
+#include <random>
+#include <chrono>
+#include "one_sided_context_client.hpp"
+#include "legacy_context_client.hpp"
+
+namespace xios
+{
+    /*!
+    \param [in] parent Pointer to context on client side
+    \param [in] intraComm_ communicator of group client
+    \param [in] interComm_ communicator of group server
+    \cxtSer [in] cxtSer Pointer to context of server side. (It is only used in case of attached mode).
+    */
+    CContextClient::CContextClient(CContext* parent, MPI_Comm intraComm_, MPI_Comm interComm_, CContext* cxtSer)
+     : parentServer(cxtSer),  associatedServer_(nullptr)
+    {
+      
+      context_ = parent;
+      intraComm = intraComm_;
+      interComm = interComm_;
+      MPI_Comm_rank(intraComm, &clientRank);
+      MPI_Comm_size(intraComm, &clientSize);
+
+      int flag;
+      MPI_Comm_test_inter(interComm, &flag);
+      if (flag) isAttached_=false ;
+      else  isAttached_=true ;
+
+      if (flag) MPI_Comm_remote_size(interComm, &serverSize);
+      else  MPI_Comm_size(interComm, &serverSize);
+
+      computeLeader(clientRank, clientSize, serverSize, ranksServerLeader, ranksServerNotLeader);
+
+      auto time=chrono::system_clock::now().time_since_epoch().count() ;
+      std::default_random_engine rd(time); // not reproducible from a run to another
+      std::uniform_int_distribution<size_t> dist;
+      hashId_=dist(rd) ;
+      MPI_Bcast(&hashId_,1,MPI_SIZE_T,0,intraComm) ; // Bcast to all server of the context
+
+    }
+
+    template<>
+    CContextClient* CContextClient::getNew<CContextClient::generic>(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer)
+    { 
+      string defaultProtocol = CXios::getin<string>("transport_protocol", "default") ;
+      if (defaultProtocol=="one_sided") return getNew<CContextClient::oneSided>(parent, intraComm, interComm) ;
+      else if  (defaultProtocol=="legacy") return getNew<CContextClient::legacy>(parent, intraComm, interComm) ;
+      else if  (defaultProtocol=="default") return getNew<CContextClient::legacy>(parent, intraComm, interComm) ;
+      else ERROR("CContextClient* CContextClient::getNew<CContextClient::generic>(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer)",
+                <<"Protocol name <"<<defaultProtocol<<"> is undefined,  must be <default>, <one_sided> or <legacy>" ) ;  
+    }
+
+    template<>
+    CContextClient* CContextClient::getNew<CContextClient::oneSided>(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer)
+    { 
+      return new COneSidedContextClient(parent, intraComm, interComm, parentServer); 
+    }
+
+    template<>
+    CContextClient* CContextClient::getNew<CContextClient::legacy>(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer)
+    { 
+      return new CLegacyContextClient(parent, intraComm, interComm, parentServer); 
+    }
+
+    void CContextClient::computeLeader(int clientRank, int clientSize, int serverSize,
+                                       std::list<int>& rankRecvLeader,
+                                       std::list<int>& rankRecvNotLeader)
+    {
+      if ((0 == clientSize) || (0 == serverSize)) return;
+
+      if (clientSize < serverSize)
+      {
+        int serverByClient = serverSize / clientSize;
+        int remain = serverSize % clientSize;
+        int rankStart = serverByClient * clientRank;
+
+        if (clientRank < remain)
+        {
+          serverByClient++;
+          rankStart += clientRank;
+        }
+        else
+          rankStart += remain;
+
+        for (int i = 0; i < serverByClient; i++)
+          rankRecvLeader.push_back(rankStart + i);
+
+        rankRecvNotLeader.resize(0);
+      }
+      else
+      {
+        int clientByServer = clientSize / serverSize;
+        int remain = clientSize % serverSize;
+
+        if (clientRank < (clientByServer + 1) * remain)
+        {
+          if (clientRank % (clientByServer + 1) == 0)
+            rankRecvLeader.push_back(clientRank / (clientByServer + 1));
+          else
+            rankRecvNotLeader.push_back(clientRank / (clientByServer + 1));
+        }
+        else
+        {
+          int rank = clientRank - (clientByServer + 1) * remain;
+          if (rank % clientByServer == 0)
+            rankRecvLeader.push_back(remain + rank / clientByServer);
+          else
+            rankRecvNotLeader.push_back(remain + rank / clientByServer);
+        }
+      }
+    }
+
+  /*!
+  Get leading server in the group of connected server
+  \return ranks of leading servers
+  */
+  const std::list<int>& CContextClient::getRanksServerNotLeader(void) const
+  {
+    return ranksServerNotLeader;
+  }
+
+  /*!
+  Check if client connects to leading server
+  \return connected(true), not connected (false)
+  */
+  bool CContextClient::isServerNotLeader(void) const
+  {
+    return !ranksServerNotLeader.empty();
+  }
+
+  /*!
+  Get leading server in the group of connected server
+  \return ranks of leading servers
+  */
+  const std::list<int>& CContextClient::getRanksServerLeader(void) const
+  {
+    return ranksServerLeader;
+  }
+
+  /*!
+  Check if client connects to leading server
+  \return connected(true), not connected (false)
+  */
+  bool CContextClient::isServerLeader(void) const
+  {
+    return !ranksServerLeader.empty();
+  }
+
+
+
+}
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/context_client.cpp.old
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/context_client.cpp.old	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/context_client.cpp.old	(revision 2343)
@@ -0,0 +1,532 @@
+#include "xios_spl.hpp"
+#include "context_client.hpp"
+#include "context_server.hpp"
+#include "event_client.hpp"
+#include "buffer_out.hpp"
+#include "buffer_client.hpp"
+#include "type.hpp"
+#include "event_client.hpp"
+#include "context.hpp"
+#include "mpi.hpp"
+#include "timer.hpp"
+#include "cxios.hpp"
+#include "server.hpp"
+#include "services.hpp"
+#include <boost/functional/hash.hpp>
+#include <random>
+#include <chrono>
+
+namespace xios
+{
+    /*!
+    \param [in] parent Pointer to context on client side
+    \param [in] intraComm_ communicator of group client
+    \param [in] interComm_ communicator of group server
+    \cxtSer [in] cxtSer Pointer to context of server side. (It is only used in case of attached mode).
+    */
+    CContextClient::CContextClient(CContext* parent, MPI_Comm intraComm_, MPI_Comm interComm_, CContext* cxtSer)
+     : mapBufferSize_(), parentServer(cxtSer), maxBufferedEvents(4), associatedServer_(nullptr)
+    {
+      
+      context_ = parent;
+      intraComm = intraComm_;
+      interComm = interComm_;
+      MPI_Comm_rank(intraComm, &clientRank);
+      MPI_Comm_size(intraComm, &clientSize);
+
+      int flag;
+      MPI_Comm_test_inter(interComm, &flag);
+      if (flag) isAttached_=false ;
+      else  isAttached_=true ;
+
+      pureOneSided=CXios::getin<bool>("pure_one_sided",false); // pure one sided communication (for test)
+      if (isAttachedModeEnabled()) pureOneSided=false ; // no one sided in attach mode
+      
+
+
+      if (flag) MPI_Comm_remote_size(interComm, &serverSize);
+      else  MPI_Comm_size(interComm, &serverSize);
+
+      computeLeader(clientRank, clientSize, serverSize, ranksServerLeader, ranksServerNotLeader);
+
+      if (flag) MPI_Intercomm_merge(interComm_,false, &interCommMerged_) ;
+      
+      MPI_Comm_split(intraComm_,clientRank,clientRank, &commSelf_) ; // for windows
+
+      auto time=chrono::system_clock::now().time_since_epoch().count() ;
+      std::default_random_engine rd(time); // not reproducible from a run to another
+      std::uniform_int_distribution<size_t> dist;
+      hashId_=dist(rd) ;
+      MPI_Bcast(&hashId_,1,MPI_SIZE_T,0,intraComm) ; // Bcast to all server of the context
+
+      timeLine = 1;
+    }
+
+    void CContextClient::computeLeader(int clientRank, int clientSize, int serverSize,
+                                       std::list<int>& rankRecvLeader,
+                                       std::list<int>& rankRecvNotLeader)
+    {
+      if ((0 == clientSize) || (0 == serverSize)) return;
+
+      if (clientSize < serverSize)
+      {
+        int serverByClient = serverSize / clientSize;
+        int remain = serverSize % clientSize;
+        int rankStart = serverByClient * clientRank;
+
+        if (clientRank < remain)
+        {
+          serverByClient++;
+          rankStart += clientRank;
+        }
+        else
+          rankStart += remain;
+
+        for (int i = 0; i < serverByClient; i++)
+          rankRecvLeader.push_back(rankStart + i);
+
+        rankRecvNotLeader.resize(0);
+      }
+      else
+      {
+        int clientByServer = clientSize / serverSize;
+        int remain = clientSize % serverSize;
+
+        if (clientRank < (clientByServer + 1) * remain)
+        {
+          if (clientRank % (clientByServer + 1) == 0)
+            rankRecvLeader.push_back(clientRank / (clientByServer + 1));
+          else
+            rankRecvNotLeader.push_back(clientRank / (clientByServer + 1));
+        }
+        else
+        {
+          int rank = clientRank - (clientByServer + 1) * remain;
+          if (rank % clientByServer == 0)
+            rankRecvLeader.push_back(remain + rank / clientByServer);
+          else
+            rankRecvNotLeader.push_back(remain + rank / clientByServer);
+        }
+      }
+    }
+
+    /*!
+    In case of attached mode, the current context must be reset to context for client
+    \param [in] event Event sent to server
+    */
+
+    void CContextClient::sendEvent(CEventClient& event)
+    {
+      list<int> ranks = event.getRanks();
+ 
+//      ostringstream str ;
+//      for(auto& rank : ranks) str<<rank<<" ; " ;
+//      info(100)<<"Event "<<timeLine<<" of context "<<context_->getId()<<"  for ranks : "<<str.str()<<endl ;
+
+      if (CXios::checkEventSync)
+      {
+        int typeId, classId, typeId_in, classId_in;
+        long long timeLine_out;
+        long long timeLine_in( timeLine );
+        typeId_in=event.getTypeId() ;
+        classId_in=event.getClassId() ;
+//        MPI_Allreduce(&timeLine,&timeLine_out, 1, MPI_UINT64_T, MPI_SUM, intraComm) ; // MPI_UINT64_T standardized by MPI 3
+        MPI_Allreduce(&timeLine_in,&timeLine_out, 1, MPI_LONG_LONG_INT, MPI_SUM, intraComm) ; 
+        MPI_Allreduce(&typeId_in,&typeId, 1, MPI_INT, MPI_SUM, intraComm) ;
+        MPI_Allreduce(&classId_in,&classId, 1, MPI_INT, MPI_SUM, intraComm) ;
+        if (typeId/clientSize!=event.getTypeId() || classId/clientSize!=event.getClassId() || timeLine_out/clientSize!=timeLine)
+        {
+           ERROR("void CContextClient::sendEvent(CEventClient& event)",
+               << "Event are not coherent between client for timeline = "<<timeLine);
+        }
+        
+        vector<int> servers(serverSize,0) ;
+        auto ranks=event.getRanks() ;
+        for(auto& rank : ranks) servers[rank]=1 ;
+        MPI_Allreduce(MPI_IN_PLACE, servers.data(), serverSize,MPI_INT,MPI_SUM,intraComm) ;
+        ostringstream osstr ;
+        for(int i=0;i<serverSize;i++)  if (servers[i]==0) osstr<<i<<" , " ;
+        if (!osstr.str().empty())
+        {
+          ERROR("void CContextClient::sendEvent(CEventClient& event)",
+                 <<" Some servers will not receive the message for timeline = "<<timeLine<<endl
+                 <<"Servers are : "<<osstr.str()) ;
+        }
+
+
+      }
+
+      if (!event.isEmpty())
+      {
+        list<int> sizes = event.getSizes();
+
+         // We force the getBuffers call to be non-blocking on classical servers
+        list<CBufferOut*> buffList;
+        getBuffers(timeLine, ranks, sizes, buffList) ;
+
+        event.send(timeLine, sizes, buffList);
+       
+        //for (auto itRank = ranks.begin(); itRank != ranks.end(); itRank++) buffers[*itRank]->infoBuffer() ;
+
+        unlockBuffers(ranks) ;
+        checkBuffers(ranks);
+        
+      }
+      
+      if (isAttachedModeEnabled()) // couldBuffer is always true in attached mode
+      {
+        while (checkBuffers(ranks)) callGlobalEventLoop() ;
+      
+        CXios::getDaemonsManager()->scheduleContext(hashId_) ;
+        while (CXios::getDaemonsManager()->isScheduledContext(hashId_)) callGlobalEventLoop() ;
+      }
+      
+      timeLine++;
+    }
+
+  
+    /*!
+     * Get buffers for each connection to the servers. This function blocks until there is enough room in the buffers unless
+     * it is explicitly requested to be non-blocking.
+     *
+     *
+     * \param [in] timeLine time line of the event which will be sent to servers
+     * \param [in] serverList list of rank of connected server
+     * \param [in] sizeList size of message corresponding to each connection
+     * \param [out] retBuffers list of buffers that can be used to store an event
+     * \param [in] nonBlocking whether this function should be non-blocking
+     * \return whether the already allocated buffers could be used
+    */
+    bool CContextClient::getBuffers(const size_t timeLine, const list<int>& serverList, const list<int>& sizeList, list<CBufferOut*>& retBuffers,
+                                    bool nonBlocking /*= false*/)
+    {
+      list<int>::const_iterator itServer, itSize;
+      list<CClientBuffer*> bufferList;
+      map<int,CClientBuffer*>::const_iterator it;
+      list<CClientBuffer*>::iterator itBuffer;
+      bool areBuffersFree;
+
+      for (itServer = serverList.begin(); itServer != serverList.end(); itServer++)
+      {
+        it = buffers.find(*itServer);
+        if (it == buffers.end())
+        {
+          newBuffer(*itServer);
+          it = buffers.find(*itServer);
+        }
+        bufferList.push_back(it->second);
+      }
+
+      double lastTimeBuffersNotFree=0. ;
+      double time ;
+      bool doUnlockBuffers ;
+      CTimer::get("Blocking time").resume();
+      do
+      {
+        areBuffersFree = true;
+        doUnlockBuffers=false ;
+        time=MPI_Wtime() ;
+        if (time-lastTimeBuffersNotFree > latency_)
+        {
+          for (itBuffer = bufferList.begin(), itSize = sizeList.begin(); itBuffer != bufferList.end(); itBuffer++, itSize++)
+          {
+            areBuffersFree &= (*itBuffer)->isBufferFree(*itSize);
+          }
+          if (!areBuffersFree)
+          {
+            lastTimeBuffersNotFree = time ;
+            doUnlockBuffers=true ;
+          }          
+        }
+        else areBuffersFree = false ;
+
+        if (!areBuffersFree)
+        {
+          if (doUnlockBuffers) for (itBuffer = bufferList.begin(); itBuffer != bufferList.end(); itBuffer++) (*itBuffer)->unlockBuffer();
+          checkBuffers();
+
+          callGlobalEventLoop() ;
+        }
+
+      } while (!areBuffersFree && !nonBlocking);
+      CTimer::get("Blocking time").suspend();
+
+      if (areBuffersFree)
+      {
+        for (itBuffer = bufferList.begin(), itSize = sizeList.begin(); itBuffer != bufferList.end(); itBuffer++, itSize++)
+          retBuffers.push_back((*itBuffer)->getBuffer(timeLine, *itSize));
+      }
+      return areBuffersFree;
+   }
+
+   void CContextClient::eventLoop(void)
+   {
+      if (!locked_) checkBuffers() ;
+   }
+
+   void CContextClient::callGlobalEventLoop(void)
+   {
+     locked_=true ;
+     context_->globalEventLoop() ;
+     locked_=false ;
+   }
+   /*!
+   Make a new buffer for a certain connection to server with specific rank
+   \param [in] rank rank of connected server
+   */
+   void CContextClient::newBuffer(int rank)
+   {
+      if (!mapBufferSize_.count(rank))
+      {
+        error(0) << "WARNING: Unexpected request for buffer to communicate with server " << rank << std::endl;
+        mapBufferSize_[rank] = CXios::minBufferSize;
+        maxEventSizes[rank] = CXios::minBufferSize;
+      }
+      
+      CClientBuffer* buffer = buffers[rank] = new CClientBuffer(interComm, rank, mapBufferSize_[rank], maxEventSizes[rank]);
+      if (isGrowableBuffer_) buffer->setGrowableBuffer(1.2) ;
+      else buffer->fixBuffer() ;
+      // Notify the server
+      CBufferOut* bufOut = buffer->getBuffer(0, 4*sizeof(MPI_Aint));
+      MPI_Aint sendBuff[4] ;
+      sendBuff[0]=hashId_;
+      sendBuff[1]=mapBufferSize_[rank];
+      sendBuff[2]=buffers[rank]->getWinAddress(0); 
+      sendBuff[3]=buffers[rank]->getWinAddress(1); 
+      info(100)<<"CContextClient::newBuffer : rank "<<rank<<" winAdress[0] "<<buffers[rank]->getWinAddress(0)<<" winAdress[1] "<<buffers[rank]->getWinAddress(1)<<endl;
+      bufOut->put(sendBuff, 4); 
+      buffer->checkBuffer(true);
+      
+       // create windows dynamically for one-sided
+      if (!isAttachedModeEnabled())
+      { 
+        CTimer::get("create Windows").resume() ;
+        MPI_Comm interComm ;
+        MPI_Intercomm_create(commSelf_, 0, interCommMerged_, clientSize+rank, 0, &interComm) ;
+        MPI_Intercomm_merge(interComm, false, &winComm_[rank]) ;
+        CXios::getMpiGarbageCollector().registerCommunicator(winComm_[rank]) ;
+        MPI_Comm_free(&interComm) ;
+        windows_[rank].resize(2) ;
+        
+        MPI_Win_create_dynamic(MPI_INFO_NULL, winComm_[rank], &windows_[rank][0]);
+        CXios::getMpiGarbageCollector().registerWindow(windows_[rank][0]) ;
+        
+        MPI_Win_create_dynamic(MPI_INFO_NULL, winComm_[rank], &windows_[rank][1]);   
+        CXios::getMpiGarbageCollector().registerWindow(windows_[rank][1]) ;
+
+        CTimer::get("create Windows").suspend() ;
+      }
+      else
+      {
+        winComm_[rank] = MPI_COMM_NULL ;
+        windows_[rank].resize(2) ;
+        windows_[rank][0] = MPI_WIN_NULL ;
+        windows_[rank][1] = MPI_WIN_NULL ;
+      }
+      buffer->attachWindows(windows_[rank]) ;
+      if (!isAttachedModeEnabled()) MPI_Barrier(winComm_[rank]) ;
+       
+   }
+
+   /*!
+   Verify state of buffers. Buffer is under pending state if there is no message on it
+   \return state of buffers, pending(true), ready(false)
+   */
+   bool CContextClient::checkBuffers(void)
+   {
+      map<int,CClientBuffer*>::iterator itBuff;
+      bool pending = false;
+      for (itBuff = buffers.begin(); itBuff != buffers.end(); itBuff++)
+        pending |= itBuff->second->checkBuffer(!pureOneSided);
+      return pending;
+   }
+
+   //! Release all buffers
+   void CContextClient::releaseBuffers()
+   {
+      map<int,CClientBuffer*>::iterator itBuff;
+      for (itBuff = buffers.begin(); itBuff != buffers.end(); itBuff++)
+      {
+         delete itBuff->second;
+      }
+      buffers.clear();
+
+// don't know when release windows
+
+      //if (!isAttachedModeEnabled())
+      //{  
+      //  for(auto& it : winComm_)
+      //  {
+      //    int rank = it.first ;
+      //    MPI_Win_free(&windows_[rank][0]);
+      //    MPI_Win_free(&windows_[rank][1]);
+      //    MPI_Comm_free(&winComm_[rank]) ;
+      //  }
+      //} 
+   }
+
+      
+  /*!
+   Lock the buffers for one sided communications
+   \param [in] ranks list rank of server to which client connects to
+   */
+   void CContextClient::lockBuffers(list<int>& ranks)
+   {
+      list<int>::iterator it;
+      for (it = ranks.begin(); it != ranks.end(); it++) buffers[*it]->lockBuffer();
+   }
+
+  /*!
+   Unlock the buffers for one sided communications
+   \param [in] ranks list rank of server to which client connects to
+   */
+   void CContextClient::unlockBuffers(list<int>& ranks)
+   {
+      list<int>::iterator it;
+      for (it = ranks.begin(); it != ranks.end(); it++) buffers[*it]->unlockBuffer();
+   }
+      
+   /*!
+   Verify state of buffers corresponding to a connection
+   \param [in] ranks list rank of server to which client connects to
+   \return state of buffers, pending(true), ready(false)
+   */
+   bool CContextClient::checkBuffers(list<int>& ranks)
+   {
+      list<int>::iterator it;
+      bool pending = false;
+      for (it = ranks.begin(); it != ranks.end(); it++) pending |= buffers[*it]->checkBuffer(!pureOneSided);
+      return pending;
+   }
+
+   /*!
+    * Set the buffer size for each connection. Warning: This function is collective.
+    *
+    * \param [in] mapSize maps the rank of the connected servers to the size of the correspoinding buffer
+    * \param [in] maxEventSize maps the rank of the connected servers to the size of the biggest event
+   */
+   void CContextClient::setBufferSize(const std::map<int,StdSize>& mapSize)
+   {
+     setFixedBuffer() ;
+     for(auto& it : mapSize)
+     {
+      size_t size=std::max(CXios::minBufferSize*1.0,std::min(it.second*CXios::bufferSizeFactor*1.01,CXios::maxBufferSize*1.0)) ;
+      mapBufferSize_[it.first]=size ;
+      if (buffers.count(it.first)>0) buffers[it.first]->fixBufferSize(size);
+     }
+   }
+
+  /*!
+  Get leading server in the group of connected server
+  \return ranks of leading servers
+  */
+  const std::list<int>& CContextClient::getRanksServerNotLeader(void) const
+  {
+    return ranksServerNotLeader;
+  }
+
+  /*!
+  Check if client connects to leading server
+  \return connected(true), not connected (false)
+  */
+  bool CContextClient::isServerNotLeader(void) const
+  {
+    return !ranksServerNotLeader.empty();
+  }
+
+  /*!
+  Get leading server in the group of connected server
+  \return ranks of leading servers
+  */
+  const std::list<int>& CContextClient::getRanksServerLeader(void) const
+  {
+    return ranksServerLeader;
+  }
+
+  /*!
+  Check if client connects to leading server
+  \return connected(true), not connected (false)
+  */
+  bool CContextClient::isServerLeader(void) const
+  {
+    return !ranksServerLeader.empty();
+  }
+
+   /*!
+   * Finalize context client and do some reports. Function is non-blocking.
+   */
+  void CContextClient::finalize(void)
+  {
+    map<int,CClientBuffer*>::iterator itBuff;
+    std::list<int>::iterator ItServerLeader; 
+    
+    bool stop = false;
+
+    int* nbServerConnectionLocal  = new int[serverSize] ;
+    int* nbServerConnectionGlobal  = new int[serverSize] ;
+    for(int i=0;i<serverSize;++i) nbServerConnectionLocal[i]=0 ;
+    for (itBuff = buffers.begin(); itBuff != buffers.end(); itBuff++)  nbServerConnectionLocal[itBuff->first]=1 ;
+    for (ItServerLeader = ranksServerLeader.begin(); ItServerLeader != ranksServerLeader.end(); ItServerLeader++)  nbServerConnectionLocal[*ItServerLeader]=1 ;
+    
+    MPI_Allreduce(nbServerConnectionLocal, nbServerConnectionGlobal, serverSize, MPI_INT, MPI_SUM, intraComm);
+    
+    CEventClient event(CContext::GetType(), CContext::EVENT_ID_CONTEXT_FINALIZE);
+    CMessage msg;
+
+    for (int i=0;i<serverSize;++i) if (nbServerConnectionLocal[i]==1) event.push(i, nbServerConnectionGlobal[i], msg) ;
+    sendEvent(event);
+
+    delete[] nbServerConnectionLocal ;
+    delete[] nbServerConnectionGlobal ;
+
+
+    CTimer::get("Blocking time").resume();
+    checkBuffers();
+    CTimer::get("Blocking time").suspend();
+
+    std::map<int,StdSize>::const_iterator itbMap = mapBufferSize_.begin(),
+                                          iteMap = mapBufferSize_.end(), itMap;
+
+    StdSize totalBuf = 0;
+    for (itMap = itbMap; itMap != iteMap; ++itMap)
+    {
+      report(10) << " Memory report : Context <" << context_->getId() << "> : client side : memory used for buffer of each connection to server" << endl
+                 << "  +) To server with rank " << itMap->first << " : " << itMap->second << " bytes " << endl;
+      totalBuf += itMap->second;
+    }
+    report(0) << " Memory report : Context <" << context_->getId() << "> : client side : total memory used for buffer " << totalBuf << " bytes" << endl;
+
+  }
+
+
+  /*!
+  */
+  bool CContextClient::havePendingRequests(void)
+  {
+    bool pending = false;
+    map<int,CClientBuffer*>::iterator itBuff;
+    for (itBuff = buffers.begin(); itBuff != buffers.end(); itBuff++)
+      pending |= itBuff->second->hasPendingRequest();
+    return pending;
+  }
+  
+  bool CContextClient::havePendingRequests(list<int>& ranks)
+  {
+      list<int>::iterator it;
+      bool pending = false;
+      for (it = ranks.begin(); it != ranks.end(); it++) pending |= buffers[*it]->hasPendingRequest();
+      return pending;
+  }
+
+  bool CContextClient::isNotifiedFinalized(void)
+  {
+    if (isAttachedModeEnabled()) return true ;
+
+    bool finalized = true;
+    map<int,CClientBuffer*>::iterator itBuff;
+    for (itBuff = buffers.begin(); itBuff != buffers.end(); itBuff++)
+      finalized &= itBuff->second->isNotifiedFinalized();
+    return finalized;
+  }
+
+}
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/context_client.hpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/context_client.hpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/context_client.hpp	(revision 2343)
@@ -0,0 +1,109 @@
+#ifndef __CONTEXT_CLIENT_HPP__
+#define __CONTEXT_CLIENT_HPP__
+
+#include "xios_spl.hpp"
+#include "buffer_out.hpp"
+#include "buffer_in.hpp"
+#include "buffer_client.hpp"
+#include "event_client.hpp"
+#include "event_server.hpp"
+#include "mpi.hpp"
+#include "registry.hpp"
+
+namespace xios
+{
+  class CContext;
+  class CContextServer ;
+  /*!
+  \class CContextClient
+  A context can be both on client and on server side. In order to differenciate the role of
+  context on each side, e.x client sending events, server receiving and processing events, there is a need of
+  concrete "context" classes for both sides.
+  CContextClient processes and sends events from client to server where CContextServer receives these events
+  and processes them.
+  */
+  class COneSidedContextClient ;
+
+  class CContextClient
+  {
+    public:
+      enum ETransport { generic, legacy, oneSided}  ;
+      
+      template<ETransport transport=generic> 
+      static CContextClient* getNew(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer = 0) ;
+
+            // Contructor
+      CContextClient(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer = 0);
+
+      bool isServerLeader(void) const;
+      bool isServerNotLeader(void) const;
+      const std::list<int>& getRanksServerLeader(void) const;
+      const std::list<int>& getRanksServerNotLeader(void) const;
+      bool isAttachedModeEnabled() const { return isAttached_ ; } 
+      static void computeLeader(int clientRank, int clientSize, int serverSize,
+                                std::list<int>& rankRecvLeader,
+                                std::list<int>& rankRecvNotLeader);
+      int getRemoteSize(void) {return serverSize;}
+      int getServerSize(void) {return serverSize;}
+      MPI_Comm getIntraComm(void)  {return intraComm ;} 
+      int getIntraCommSize(void) {return clientSize ;}
+      int getIntraCommRank(void) {return clientRank ;}
+      /*! set the associated server (dual chanel client/server) */      
+      void setAssociatedServer(CContextServer* associatedServer) { associatedServer=associatedServer_;}
+      /*! get the associated server (dual chanel client/server) */      
+      CContextServer* getAssociatedServer(void) { return associatedServer_;}
+      
+
+
+      // Send event to server
+      virtual void sendEvent(CEventClient& event)=0;
+      virtual void eventLoop(void)=0 ;
+      virtual void releaseBuffers(void)=0;
+      virtual bool havePendingRequests(void)=0;
+
+
+      virtual bool isNotifiedFinalized(void)=0 ;
+      virtual void finalize(void)=0;
+
+      virtual void setBufferSize(const std::map<int,StdSize>& mapSize)=0;
+
+
+    protected:
+
+      CContext* context_; //!< Context for client
+
+      CContext* parentServer; //!< Context for server (Only used in attached mode)
+
+      int clientRank; //!< Rank of current client
+
+      int clientSize; //!< Size of client group
+
+      int serverSize; //!< Size of server group
+
+      MPI_Comm interComm; //!< Communicator of server group (interCommunicator)
+
+      MPI_Comm intraComm; //!< Communicator of client group
+     
+      std::list<int> ranksServerLeader; //!< List of server ranks for which the client is leader
+
+      std::list<int> ranksServerNotLeader; //!< List of server ranks for which the client is not leader
+
+      size_t hashId_ ; //!< hash id on the context client that will be used for context server to identify the remote calling context client.
+
+      bool isAttached_ ;
+      CContextServer* associatedServer_ ; //!< The server associated to the pair client/server
+  };
+
+  template<>
+  CContextClient* CContextClient::getNew<CContextClient::generic>(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer) ;
+ 
+  template<>
+  CContextClient* CContextClient::getNew<CContextClient::oneSided>(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer) ;
+
+  template<>
+  CContextClient* CContextClient::getNew<CContextClient::legacy>(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer) ;
+
+
+}
+
+#endif // __CONTEXT_CLIENT_HPP__
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/context_server.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/context_server.cpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/context_server.cpp	(revision 2343)
@@ -0,0 +1,98 @@
+#include "context_server.hpp"
+#include "buffer_in.hpp"
+#include "type.hpp"
+#include "context.hpp"
+#include "object_template.hpp"
+#include "group_template.hpp"
+#include "attribute_template.hpp"
+#include "domain.hpp"
+#include "field.hpp"
+#include "file.hpp"
+#include "grid.hpp"
+#include "mpi.hpp"
+#include "tracer.hpp"
+#include "timer.hpp"
+#include "cxios.hpp"
+#include "event_scheduler.hpp"
+#include "server.hpp"
+#include "servers_ressource.hpp"
+#include "pool_ressource.hpp"
+#include "services.hpp"
+#include "contexts_manager.hpp"
+#include "timeline_events.hpp"
+#include "one_sided_context_server.hpp"
+#include "legacy_context_server.hpp"
+
+
+
+#include <boost/functional/hash.hpp>
+#include <random>
+#include <chrono>
+
+
+namespace xios
+{
+  using namespace std ;
+
+  CContextServer::CContextServer(CContext* parent,MPI_Comm intraComm_,MPI_Comm interComm_) 
+    : associatedClient_(nullptr)
+  {
+    context=parent;
+    intraComm=intraComm_;
+    MPI_Comm_size(intraComm,&intraCommSize);
+    MPI_Comm_rank(intraComm,&intraCommRank);
+
+    interComm=interComm_;
+    int flag;
+    MPI_Comm_test_inter(interComm,&flag);
+
+    if (flag) attachedMode=false ;
+    else  attachedMode=true ;
+    
+    if (flag) MPI_Comm_remote_size(interComm,&clientSize_);
+    else  MPI_Comm_size(interComm,&clientSize_);
+
+    SRegisterContextInfo contextInfo ;
+    CXios::getContextsManager()->getContextInfo(context->getId(), contextInfo, intraComm) ;
+    eventScheduler_=CXios::getPoolRessource()->getService(contextInfo.serviceId,contextInfo.partitionId)->getEventScheduler() ;
+
+    // generate unique hash for server
+    auto time=chrono::system_clock::now().time_since_epoch().count() ;
+    std::default_random_engine rd(time); // not reproducible from a run to another
+    std::uniform_int_distribution<size_t> dist;
+    hashId=dist(rd) ;
+    MPI_Bcast(&hashId,1,MPI_SIZE_T,0,intraComm) ; // Bcast to all server of the context
+      
+  }
+
+  template<>
+  CContextServer* CContextServer::getNew<CContextServer::generic>(CContext* parent,MPI_Comm intraComm,MPI_Comm interComm) 
+  { 
+    string defaultProtocol = CXios::getin<string>("transport_protocol", "default") ;
+    if (defaultProtocol=="one_sided") return new COneSidedContextServer(parent, intraComm, interComm) ;
+    else if  (defaultProtocol=="legacy") return new CLegacyContextServer(parent, intraComm, interComm) ;
+    else if  (defaultProtocol=="default") return new CLegacyContextServer(parent, intraComm, interComm) ;
+    else ERROR("CContextServer* CContextServer::getNew<CContextServer::generic>(CContext* parent,MPI_Comm intraComm,MPI_Comm interComm)",
+              <<"Protocol name <"<<defaultProtocol<<"> is undefined,  must be <default>, <one_sided> or <legacy>" ) ;     
+  }
+
+  template<>
+  CContextServer* CContextServer::getNew<CContextServer::oneSided>(CContext* parent,MPI_Comm intraComm,MPI_Comm interComm) 
+  { 
+    return new COneSidedContextServer(parent, intraComm, interComm) ; 
+  }
+
+  template<>
+  CContextServer* CContextServer::getNew<CContextServer::legacy>(CContext* parent,MPI_Comm intraComm,MPI_Comm interComm) 
+  { 
+    return new COneSidedContextServer(parent, intraComm, interComm) ; 
+  }
+
+//! Attached mode is used ?
+//! \return true if attached mode is used, false otherwise
+  bool CContextServer::isAttachedModeEnabled() const
+  {
+    return attachedMode ;
+  }
+
+}
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/context_server.hpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/context_server.hpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/context_server.hpp	(revision 2343)
@@ -0,0 +1,64 @@
+#ifndef __CONTEXT_SERVER_HPP__
+#define __CONTEXT_SERVER_HPP__
+#include "xios_spl.hpp"
+#include "event_server.hpp"
+#include "buffer_server.hpp"
+#include "mpi.hpp"
+#include "event_scheduler.hpp"
+
+namespace xios
+{
+  class CContext ;
+  class CContextClient;
+
+  class CContextServer
+  {
+    public:
+    
+    enum ETransport { generic, legacy, oneSided}  ;
+      
+    template<ETransport transport=generic> 
+    static CContextServer* getNew(CContext* parent,MPI_Comm intraComm,MPI_Comm interComm) ;
+    
+    CContextServer(CContext* parent,MPI_Comm intraComm,MPI_Comm interComm) ;
+    ~CContextServer() {} 
+    bool isAttachedModeEnabled() const ;
+    void setAssociatedClient(CContextClient* associatedClient) {associatedClient_=associatedClient ;}
+    CContextClient* getAssociatedClient(void) { return associatedClient_ ;}
+    int getIntraCommRank(void) { return intraCommRank ;}
+    int getIntraCommSize(void) { return intraCommSize ;}
+
+    virtual bool eventLoop(bool enableEventsProcessing = true) = 0 ;
+    virtual void releaseBuffers(void)=0;
+    
+    protected :
+
+      MPI_Comm intraComm ;
+      int intraCommSize ;
+      int intraCommRank ;
+
+      MPI_Comm interComm ;
+      int commSize ;
+      int clientSize_ ;
+
+      bool attachedMode ;  //! true if attached mode is enabled otherwise false
+
+      CContext* context ;
+      CContextClient* associatedClient_ ;
+
+      size_t hashId ;
+      CEventScheduler* eventScheduler_=nullptr ;
+  } ;
+  
+  template<>
+  CContextServer* CContextServer::getNew<CContextServer::generic>(CContext* parent,MPI_Comm intraComm,MPI_Comm interComm) ;
+ 
+  template<>
+  CContextServer* CContextServer::getNew<CContextServer::oneSided>(CContext* parent,MPI_Comm intraComm,MPI_Comm interComm) ;
+
+  template<>
+  CContextServer* CContextServer::getNew<CContextServer::legacy>(CContext* parent,MPI_Comm intraComm,MPI_Comm interComm) ;
+
+}
+
+#endif
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/legacy_context_client.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/legacy_context_client.cpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/legacy_context_client.cpp	(revision 2343)
@@ -0,0 +1,424 @@
+#include "xios_spl.hpp"
+#include "legacy_context_client.hpp"
+#include "context_server.hpp"
+#include "event_client.hpp"
+#include "buffer_out.hpp"
+#include "buffer_client.hpp"
+#include "type.hpp"
+#include "event_client.hpp"
+#include "context.hpp"
+#include "mpi.hpp"
+#include "timer.hpp"
+#include "cxios.hpp"
+#include "server.hpp"
+#include "services.hpp"
+#include <boost/functional/hash.hpp>
+#include <random>
+#include <chrono>
+
+namespace xios
+{
+    /*!
+    \param [in] parent Pointer to context on client side
+    \param [in] intraComm_ communicator of group client
+    \param [in] interComm_ communicator of group server
+    \cxtSer [in] cxtSer Pointer to context of server side. (It is only used in case of attached mode).
+    */
+    CLegacyContextClient::CLegacyContextClient(CContext* parent, MPI_Comm intraComm_, MPI_Comm interComm_, CContext* cxtSer)
+                         : CContextClient(parent, intraComm_, interComm_, cxtSer),
+                           mapBufferSize_(),  maxBufferedEvents(4)
+    {
+      pureOneSided=CXios::getin<bool>("pure_one_sided",false); // pure one sided communication (for test)
+      if (isAttachedModeEnabled()) pureOneSided=false ; // no one sided in attach mode
+
+      if (!isAttachedModeEnabled()) MPI_Intercomm_merge(interComm_,false, &interCommMerged_) ;
+      
+      MPI_Comm_split(intraComm_,clientRank,clientRank, &commSelf_) ; // for windows
+
+      timeLine = 1;
+    }
+
+
+    /*!
+    In case of attached mode, the current context must be reset to context for client
+    \param [in] event Event sent to server
+    */
+    void CLegacyContextClient::sendEvent(CEventClient& event)
+    {
+      list<int> ranks = event.getRanks();
+ 
+//      ostringstream str ;
+//      for(auto& rank : ranks) str<<rank<<" ; " ;
+//      info(100)<<"Event "<<timeLine<<" of context "<<context_->getId()<<"  for ranks : "<<str.str()<<endl ;
+
+      if (CXios::checkEventSync)
+      {
+        int typeId, classId, typeId_in, classId_in;
+        long long timeLine_out;
+        long long timeLine_in( timeLine );
+        typeId_in=event.getTypeId() ;
+        classId_in=event.getClassId() ;
+//        MPI_Allreduce(&timeLine,&timeLine_out, 1, MPI_UINT64_T, MPI_SUM, intraComm) ; // MPI_UINT64_T standardized by MPI 3
+        MPI_Allreduce(&timeLine_in,&timeLine_out, 1, MPI_LONG_LONG_INT, MPI_SUM, intraComm) ; 
+        MPI_Allreduce(&typeId_in,&typeId, 1, MPI_INT, MPI_SUM, intraComm) ;
+        MPI_Allreduce(&classId_in,&classId, 1, MPI_INT, MPI_SUM, intraComm) ;
+        if (typeId/clientSize!=event.getTypeId() || classId/clientSize!=event.getClassId() || timeLine_out/clientSize!=timeLine)
+        {
+           ERROR("void CLegacyContextClient::sendEvent(CEventClient& event)",
+               << "Event are not coherent between client for timeline = "<<timeLine);
+        }
+        
+        vector<int> servers(serverSize,0) ;
+        auto ranks=event.getRanks() ;
+        for(auto& rank : ranks) servers[rank]=1 ;
+        MPI_Allreduce(MPI_IN_PLACE, servers.data(), serverSize,MPI_INT,MPI_SUM,intraComm) ;
+        ostringstream osstr ;
+        for(int i=0;i<serverSize;i++)  if (servers[i]==0) osstr<<i<<" , " ;
+        if (!osstr.str().empty())
+        {
+          ERROR("void CLegacyContextClient::sendEvent(CEventClient& event)",
+                 <<" Some servers will not receive the message for timeline = "<<timeLine<<endl
+                 <<"Servers are : "<<osstr.str()) ;
+        }
+
+
+      }
+
+      if (!event.isEmpty())
+      {
+        list<int> sizes = event.getSizes();
+
+         // We force the getBuffers call to be non-blocking on classical servers
+        list<CBufferOut*> buffList;
+        getBuffers(timeLine, ranks, sizes, buffList) ;
+
+        event.send(timeLine, sizes, buffList);
+       
+        //for (auto itRank = ranks.begin(); itRank != ranks.end(); itRank++) buffers[*itRank]->infoBuffer() ;
+
+        unlockBuffers(ranks) ;
+        checkBuffers(ranks);
+        
+      }
+      
+      if (isAttachedModeEnabled()) // couldBuffer is always true in attached mode
+      {
+        while (checkBuffers(ranks)) callGlobalEventLoop() ;
+      
+        CXios::getDaemonsManager()->scheduleContext(hashId_) ;
+        while (CXios::getDaemonsManager()->isScheduledContext(hashId_)) callGlobalEventLoop() ;
+      }
+      
+      timeLine++;
+    }
+
+
+    /*!
+     * Get buffers for each connection to the servers. This function blocks until there is enough room in the buffers unless
+     * it is explicitly requested to be non-blocking.
+     *
+     *
+     * \param [in] timeLine time line of the event which will be sent to servers
+     * \param [in] serverList list of rank of connected server
+     * \param [in] sizeList size of message corresponding to each connection
+     * \param [out] retBuffers list of buffers that can be used to store an event
+     * \param [in] nonBlocking whether this function should be non-blocking
+     * \return whether the already allocated buffers could be used
+    */
+    bool CLegacyContextClient::getBuffers(const size_t timeLine, const list<int>& serverList, const list<int>& sizeList, list<CBufferOut*>& retBuffers,
+                                    bool nonBlocking /*= false*/)
+    {
+      list<int>::const_iterator itServer, itSize;
+      list<CClientBuffer*> bufferList;
+      map<int,CClientBuffer*>::const_iterator it;
+      list<CClientBuffer*>::iterator itBuffer;
+      bool areBuffersFree;
+
+      for (itServer = serverList.begin(); itServer != serverList.end(); itServer++)
+      {
+        it = buffers.find(*itServer);
+        if (it == buffers.end())
+        {
+          newBuffer(*itServer);
+          it = buffers.find(*itServer);
+        }
+        bufferList.push_back(it->second);
+      }
+
+      double lastTimeBuffersNotFree=0. ;
+      double time ;
+      bool doUnlockBuffers ;
+      CTimer::get("Blocking time").resume();
+      do
+      {
+        areBuffersFree = true;
+        doUnlockBuffers=false ;
+        time=MPI_Wtime() ;
+        if (time-lastTimeBuffersNotFree > latency_)
+        {
+          for (itBuffer = bufferList.begin(), itSize = sizeList.begin(); itBuffer != bufferList.end(); itBuffer++, itSize++)
+          {
+            areBuffersFree &= (*itBuffer)->isBufferFree(*itSize);
+          }
+          if (!areBuffersFree)
+          {
+            lastTimeBuffersNotFree = time ;
+            doUnlockBuffers=true ;
+          }          
+        }
+        else areBuffersFree = false ;
+
+        if (!areBuffersFree)
+        {
+          if (doUnlockBuffers) for (itBuffer = bufferList.begin(); itBuffer != bufferList.end(); itBuffer++) (*itBuffer)->unlockBuffer();
+          checkBuffers();
+
+          callGlobalEventLoop() ;
+        }
+
+      } while (!areBuffersFree && !nonBlocking);
+      CTimer::get("Blocking time").suspend();
+
+      if (areBuffersFree)
+      {
+        for (itBuffer = bufferList.begin(), itSize = sizeList.begin(); itBuffer != bufferList.end(); itBuffer++, itSize++)
+          retBuffers.push_back((*itBuffer)->getBuffer(timeLine, *itSize));
+      }
+      return areBuffersFree;
+   }
+
+   void CLegacyContextClient::eventLoop(void)
+   {
+      if (!locked_) checkBuffers() ;
+   }
+
+   void CLegacyContextClient::callGlobalEventLoop(void)
+   {
+     locked_=true ;
+     context_->globalEventLoop() ;
+     locked_=false ;
+   }
+   /*!
+   Make a new buffer for a certain connection to server with specific rank
+   \param [in] rank rank of connected server
+   */
+   void CLegacyContextClient::newBuffer(int rank)
+   {
+      if (!mapBufferSize_.count(rank))
+      {
+        error(0) << "WARNING: Unexpected request for buffer to communicate with server " << rank << std::endl;
+        mapBufferSize_[rank] = CXios::minBufferSize;
+        maxEventSizes[rank] = CXios::minBufferSize;
+      }
+      
+      CClientBuffer* buffer = buffers[rank] = new CClientBuffer(interComm, rank, mapBufferSize_[rank], maxEventSizes[rank]);
+      if (isGrowableBuffer_) buffer->setGrowableBuffer(1.2) ;
+      else buffer->fixBuffer() ;
+      // Notify the server
+      CBufferOut* bufOut = buffer->getBuffer(0, 4*sizeof(MPI_Aint));
+      MPI_Aint sendBuff[4] ;
+      sendBuff[0]=hashId_;
+      sendBuff[1]=mapBufferSize_[rank];
+      sendBuff[2]=buffers[rank]->getWinAddress(0); 
+      sendBuff[3]=buffers[rank]->getWinAddress(1); 
+      info(100)<<"CLegacyContextClient::newBuffer : rank "<<rank<<" winAdress[0] "<<buffers[rank]->getWinAddress(0)<<" winAdress[1] "<<buffers[rank]->getWinAddress(1)<<endl;
+      bufOut->put(sendBuff, 4); 
+      buffer->checkBuffer(true);
+      
+       // create windows dynamically for one-sided
+      if (!isAttachedModeEnabled())
+      { 
+        CTimer::get("create Windows").resume() ;
+        MPI_Comm interComm ;
+        MPI_Intercomm_create(commSelf_, 0, interCommMerged_, clientSize+rank, 0, &interComm) ;
+        MPI_Intercomm_merge(interComm, false, &winComm_[rank]) ;
+        CXios::getMpiGarbageCollector().registerCommunicator(winComm_[rank]) ;
+        MPI_Comm_free(&interComm) ;
+        windows_[rank].resize(2) ;
+        
+        MPI_Win_create_dynamic(MPI_INFO_NULL, winComm_[rank], &windows_[rank][0]);
+        CXios::getMpiGarbageCollector().registerWindow(windows_[rank][0]) ;
+        
+        MPI_Win_create_dynamic(MPI_INFO_NULL, winComm_[rank], &windows_[rank][1]);   
+        CXios::getMpiGarbageCollector().registerWindow(windows_[rank][1]) ;
+
+        CTimer::get("create Windows").suspend() ;
+      }
+      else
+      {
+        winComm_[rank] = MPI_COMM_NULL ;
+        windows_[rank].resize(2) ;
+        windows_[rank][0] = MPI_WIN_NULL ;
+        windows_[rank][1] = MPI_WIN_NULL ;
+      }
+      buffer->attachWindows(windows_[rank]) ;
+      if (!isAttachedModeEnabled()) MPI_Barrier(winComm_[rank]) ;
+       
+   }
+
+   /*!
+   Verify state of buffers. Buffer is under pending state if there is no message on it
+   \return state of buffers, pending(true), ready(false)
+   */
+   bool CLegacyContextClient::checkBuffers(void)
+   {
+      map<int,CClientBuffer*>::iterator itBuff;
+      bool pending = false;
+      for (itBuff = buffers.begin(); itBuff != buffers.end(); itBuff++)
+        pending |= itBuff->second->checkBuffer(!pureOneSided);
+      return pending;
+   }
+
+   //! Release all buffers
+   void CLegacyContextClient::releaseBuffers()
+   {
+      map<int,CClientBuffer*>::iterator itBuff;
+      for (itBuff = buffers.begin(); itBuff != buffers.end(); itBuff++)
+      {
+         delete itBuff->second;
+      }
+      buffers.clear();
+
+// don't know when release windows
+
+      //if (!isAttachedModeEnabled())
+      //{  
+      //  for(auto& it : winComm_)
+      //  {
+      //    int rank = it.first ;
+      //    MPI_Win_free(&windows_[rank][0]);
+      //    MPI_Win_free(&windows_[rank][1]);
+      //    MPI_Comm_free(&winComm_[rank]) ;
+      //  }
+      //} 
+   }
+
+      
+  /*!
+   Lock the buffers for one sided communications
+   \param [in] ranks list rank of server to which client connects to
+   */
+   void CLegacyContextClient::lockBuffers(list<int>& ranks)
+   {
+      list<int>::iterator it;
+      for (it = ranks.begin(); it != ranks.end(); it++) buffers[*it]->lockBuffer();
+   }
+
+  /*!
+   Unlock the buffers for one sided communications
+   \param [in] ranks list rank of server to which client connects to
+   */
+   void CLegacyContextClient::unlockBuffers(list<int>& ranks)
+   {
+      list<int>::iterator it;
+      for (it = ranks.begin(); it != ranks.end(); it++) buffers[*it]->unlockBuffer();
+   }
+      
+   /*!
+   Verify state of buffers corresponding to a connection
+   \param [in] ranks list rank of server to which client connects to
+   \return state of buffers, pending(true), ready(false)
+   */
+   bool CLegacyContextClient::checkBuffers(list<int>& ranks)
+   {
+      list<int>::iterator it;
+      bool pending = false;
+      for (it = ranks.begin(); it != ranks.end(); it++) pending |= buffers[*it]->checkBuffer(!pureOneSided);
+      return pending;
+   }
+
+   /*!
+    * Set the buffer size for each connection. Warning: This function is collective.
+    *
+    * \param [in] mapSize maps the rank of the connected servers to the size of the correspoinding buffer
+    * \param [in] maxEventSize maps the rank of the connected servers to the size of the biggest event
+   */
+   void CLegacyContextClient::setBufferSize(const std::map<int,StdSize>& mapSize)
+   {
+     setFixedBuffer() ;
+     for(auto& it : mapSize)
+     {
+      size_t size=std::max(CXios::minBufferSize*1.0,std::min(it.second*CXios::bufferSizeFactor*1.01,CXios::maxBufferSize*1.0)) ;
+      mapBufferSize_[it.first]=size ;
+      if (buffers.count(it.first)>0) buffers[it.first]->fixBufferSize(size);
+     }
+   }
+
+   /*!
+   * Finalize context client and do some reports. Function is non-blocking.
+   */
+  void CLegacyContextClient::finalize(void)
+  {
+    map<int,CClientBuffer*>::iterator itBuff;
+    std::list<int>::iterator ItServerLeader; 
+    
+    bool stop = false;
+
+    int* nbServerConnectionLocal  = new int[serverSize] ;
+    int* nbServerConnectionGlobal  = new int[serverSize] ;
+    for(int i=0;i<serverSize;++i) nbServerConnectionLocal[i]=0 ;
+    for (itBuff = buffers.begin(); itBuff != buffers.end(); itBuff++)  nbServerConnectionLocal[itBuff->first]=1 ;
+    for (ItServerLeader = ranksServerLeader.begin(); ItServerLeader != ranksServerLeader.end(); ItServerLeader++)  nbServerConnectionLocal[*ItServerLeader]=1 ;
+    
+    MPI_Allreduce(nbServerConnectionLocal, nbServerConnectionGlobal, serverSize, MPI_INT, MPI_SUM, intraComm);
+    
+    CEventClient event(CContext::GetType(), CContext::EVENT_ID_CONTEXT_FINALIZE);
+    CMessage msg;
+
+    for (int i=0;i<serverSize;++i) if (nbServerConnectionLocal[i]==1) event.push(i, nbServerConnectionGlobal[i], msg) ;
+    sendEvent(event);
+
+    delete[] nbServerConnectionLocal ;
+    delete[] nbServerConnectionGlobal ;
+
+
+    CTimer::get("Blocking time").resume();
+    checkBuffers();
+    CTimer::get("Blocking time").suspend();
+
+    std::map<int,StdSize>::const_iterator itbMap = mapBufferSize_.begin(),
+                                          iteMap = mapBufferSize_.end(), itMap;
+
+    StdSize totalBuf = 0;
+    for (itMap = itbMap; itMap != iteMap; ++itMap)
+    {
+      report(10) << " Memory report : Context <" << context_->getId() << "> : client side : memory used for buffer of each connection to server" << endl
+                 << "  +) To server with rank " << itMap->first << " : " << itMap->second << " bytes " << endl;
+      totalBuf += itMap->second;
+    }
+    report(0) << " Memory report : Context <" << context_->getId() << "> : client side : total memory used for buffer " << totalBuf << " bytes" << endl;
+
+  }
+
+
+  /*!
+  */
+  bool CLegacyContextClient::havePendingRequests(void)
+  {
+    bool pending = false;
+    map<int,CClientBuffer*>::iterator itBuff;
+    for (itBuff = buffers.begin(); itBuff != buffers.end(); itBuff++)
+      pending |= itBuff->second->hasPendingRequest();
+    return pending;
+  }
+  
+  bool CLegacyContextClient::havePendingRequests(list<int>& ranks)
+  {
+      list<int>::iterator it;
+      bool pending = false;
+      for (it = ranks.begin(); it != ranks.end(); it++) pending |= buffers[*it]->hasPendingRequest();
+      return pending;
+  }
+
+  bool CLegacyContextClient::isNotifiedFinalized(void)
+  {
+    if (isAttachedModeEnabled()) return true ;
+
+    bool finalized = true;
+    map<int,CClientBuffer*>::iterator itBuff;
+    for (itBuff = buffers.begin(); itBuff != buffers.end(); itBuff++)
+      finalized &= itBuff->second->isNotifiedFinalized();
+    return finalized;
+  }
+
+}
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/legacy_context_client.hpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/legacy_context_client.hpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/legacy_context_client.hpp	(revision 2343)
@@ -0,0 +1,85 @@
+#ifndef __LEGACY_CONTEXT_CLIENT_HPP__
+#define __LEGACY_CONTEXT_CLIENT_HPP__
+
+#include "xios_spl.hpp"
+#include "buffer_out.hpp"
+#include "buffer_in.hpp"
+#include "buffer_client.hpp"
+#include "event_client.hpp"
+#include "event_server.hpp"
+#include "mpi.hpp"
+#include "registry.hpp"
+#include "context_client.hpp"
+
+namespace xios
+{
+  class CContext;
+  class CContextServer ;
+  /*!
+  \class CLegacyContextClient
+  A context can be both on client and on server side. In order to differenciate the role of
+  context on each side, e.x client sending events, server receiving and processing events, there is a need of
+  concrete "context" classes for both sides.
+  CLegacyContextClient processes and sends events from client to server where CContextServer receives these events
+  and processes them.
+  */
+  class CLegacyContextClient : public CContextClient
+  {
+    public:
+      // Contructor
+      CLegacyContextClient(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer = 0);
+
+      // Send event to server
+      void sendEvent(CEventClient& event);
+      void eventLoop(void) ;
+      void releaseBuffers(void);
+      bool havePendingRequests(void);
+
+      bool isNotifiedFinalized(void) ;
+      void finalize(void);
+
+      void setBufferSize(const std::map<int,StdSize>& mapSize);
+
+
+    private:
+
+      // Functions to set/get buffers
+      bool getBuffers(const size_t timeLine, const list<int>& serverList, const list<int>& sizeList, list<CBufferOut*>& retBuffers, bool nonBlocking = false);
+      void newBuffer(int rank);
+      bool checkBuffers(list<int>& ranks);
+      bool checkBuffers(void);
+      void callGlobalEventLoop() ;
+      bool havePendingRequests(list<int>& ranks) ;
+      void setGrowableBuffer(void) { isGrowableBuffer_=true;}
+      void setFixedBuffer(void) { isGrowableBuffer_=false;}
+      void lockBuffers(list<int>& ranks) ;
+      void unlockBuffers(list<int>& ranks) ;
+
+
+      size_t timeLine; //!< Timeline of each event
+
+      MPI_Comm interCommMerged_; //!< Communicator of the client group + server group (intraCommunicator) needed for one sided communication.
+      MPI_Comm commSelf_ ; //!< Communicator for proc alone from interCommMerged 
+
+      map<int,CClientBuffer*> buffers; //!< Buffers for connection to servers
+
+      bool pureOneSided ; //!< if true, client will communicated with servers only trough one sided communication. Otherwise the hybrid mode P2P /One sided is used.
+      
+      //! Mapping of server and buffer size for each connection to server
+      std::map<int,StdSize> mapBufferSize_;
+      //! Maximum event sizes estimated for each connection to server
+      std::map<int,StdSize> maxEventSizes;
+      //! Maximum number of events that can be buffered
+      StdSize maxBufferedEvents;
+
+      std::map<int, MPI_Comm> winComm_ ; //! Window communicators
+      std::map<int, std::vector<MPI_Win> >windows_ ; //! one sided mpi windows to expose client buffers to servers == windows[nbServers][2]
+      bool isGrowableBuffer_ = true ;
+
+      double latency_=0e-2 ;
+
+      bool locked_ = false ; //!< The context client is locked to avoid recursive checkBuffer
+  };
+}
+
+#endif // __LEGACY_CONTEXT_CLIENT_HPP__
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/legacy_context_server.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/legacy_context_server.cpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/legacy_context_server.cpp	(revision 2343)
@@ -0,0 +1,468 @@
+#include "legacy_context_server.hpp"
+#include "buffer_in.hpp"
+#include "type.hpp"
+#include "context.hpp"
+#include "object_template.hpp"
+#include "group_template.hpp"
+#include "attribute_template.hpp"
+#include "domain.hpp"
+#include "field.hpp"
+#include "file.hpp"
+#include "grid.hpp"
+#include "mpi.hpp"
+#include "tracer.hpp"
+#include "timer.hpp"
+#include "cxios.hpp"
+#include "event_scheduler.hpp"
+#include "server.hpp"
+#include "servers_ressource.hpp"
+#include "pool_ressource.hpp"
+#include "services.hpp"
+#include "contexts_manager.hpp"
+#include "timeline_events.hpp"
+
+#include <boost/functional/hash.hpp>
+#include <random>
+#include <chrono>
+
+
+namespace xios
+{
+  using namespace std ;
+
+  CLegacyContextServer::CLegacyContextServer(CContext* parent,MPI_Comm intraComm_,MPI_Comm interComm_) 
+    : CContextServer(parent, intraComm_, interComm_),
+      isProcessingEvent_(false)
+  {
+ 
+    MPI_Comm_dup(intraComm, &processEventBarrier_) ;
+ 
+
+    currentTimeLine=1;
+    scheduled=false;
+    finished=false;
+
+    if (!isAttachedModeEnabled()) MPI_Intercomm_merge(interComm_,true,&interCommMerged_) ;
+    MPI_Comm_split(intraComm_, intraCommRank, intraCommRank, &commSelf_) ; // for windows
+    
+    itLastTimeLine=lastTimeLine.begin() ;
+
+    pureOneSided=CXios::getin<bool>("pure_one_sided",false); // pure one sided communication (for test)
+    if (isAttachedModeEnabled()) pureOneSided=false ; // no one sided in attach mode
+      
+  }
+ 
+  void CLegacyContextServer::setPendingEvent(void)
+  {
+    pendingEvent=true;
+  }
+
+  bool CLegacyContextServer::hasPendingEvent(void)
+  {
+    return pendingEvent;
+  }
+
+  bool CLegacyContextServer::hasFinished(void)
+  {
+    return finished;
+  }
+
+  bool CLegacyContextServer::eventLoop(bool enableEventsProcessing /*= true*/)
+  {
+    CTimer::get("listen request").resume();
+    listen();
+    CTimer::get("listen request").suspend();
+    CTimer::get("check pending request").resume();
+    checkPendingRequest();
+    checkPendingProbe() ;
+    CTimer::get("check pending request").suspend();
+    CTimer::get("check event process").resume();
+    processEvents(enableEventsProcessing);
+    CTimer::get("check event process").suspend();
+    return finished;
+  }
+
+ void CLegacyContextServer::listen(void)
+  {
+    int rank;
+    int flag;
+    int count;
+    char * addr;
+    MPI_Status status;
+    MPI_Message message ;
+    map<int,CServerBuffer*>::iterator it;
+    bool okLoop;
+
+    traceOff();
+    MPI_Improbe(MPI_ANY_SOURCE, 20,interComm,&flag,&message, &status);
+    traceOn();
+    if (flag==true) listenPendingRequest(message, status) ;
+  }
+
+  bool CLegacyContextServer::listenPendingRequest( MPI_Message &message, MPI_Status& status)
+  {
+    int count;
+    char * addr;
+    map<int,CServerBuffer*>::iterator it;
+    int rank=status.MPI_SOURCE ;
+
+    it=buffers.find(rank);
+    if (it==buffers.end()) // Receive the buffer size and allocate the buffer
+    {
+      MPI_Aint recvBuff[4] ;
+      MPI_Mrecv(recvBuff, 4, MPI_AINT,  &message, &status);
+      remoteHashId_ = recvBuff[0] ;
+      StdSize buffSize = recvBuff[1];
+      vector<MPI_Aint> winAdress(2) ;
+      winAdress[0]=recvBuff[2] ; winAdress[1]=recvBuff[3] ;
+      mapBufferSize_.insert(std::make_pair(rank, buffSize));
+
+      // create windows dynamically for one-sided
+      if (!isAttachedModeEnabled())
+      { 
+        CTimer::get("create Windows").resume() ;
+        MPI_Comm interComm ;
+        MPI_Intercomm_create(commSelf_, 0, interCommMerged_, rank, 0 , &interComm) ;
+        MPI_Intercomm_merge(interComm, true, &winComm_[rank]) ;
+        CXios::getMpiGarbageCollector().registerCommunicator(winComm_[rank]) ;
+        MPI_Comm_free(&interComm) ;
+        windows_[rank].resize(2) ;
+        MPI_Win_create_dynamic(MPI_INFO_NULL, winComm_[rank], &windows_[rank][0]);
+        CXios::getMpiGarbageCollector().registerWindow(windows_[rank][0]) ;
+        MPI_Win_create_dynamic(MPI_INFO_NULL, winComm_[rank], &windows_[rank][1]);
+        CXios::getMpiGarbageCollector().registerWindow(windows_[rank][1]) ;
+        CTimer::get("create Windows").suspend() ;
+        MPI_Barrier(winComm_[rank]) ;
+      }
+      else
+      {
+        winComm_[rank] = MPI_COMM_NULL ;
+        windows_[rank].resize(2) ;
+        windows_[rank][0] = MPI_WIN_NULL ;
+        windows_[rank][1] = MPI_WIN_NULL ;
+      }   
+
+      it=(buffers.insert(pair<int,CServerBuffer*>(rank,new CServerBuffer(windows_[rank], winAdress, 0, buffSize)))).first;
+      lastTimeLine[rank]=0 ;
+      itLastTimeLine=lastTimeLine.begin() ;
+
+      return true;
+    }
+    else
+    {
+        std::pair<MPI_Message,MPI_Status> mypair(message,status) ;
+        pendingProbe[rank].push_back(mypair) ;
+        return false;
+    }
+  }
+
+  void CLegacyContextServer::checkPendingProbe(void)
+  {
+    
+    list<int> recvProbe ;
+    list<int>::iterator itRecv ;
+    map<int, list<std::pair<MPI_Message,MPI_Status> > >::iterator itProbe;
+
+    for(itProbe=pendingProbe.begin();itProbe!=pendingProbe.end();itProbe++)
+    {
+      int rank=itProbe->first ;
+      if (pendingRequest.count(rank)==0)
+      {
+        MPI_Message& message = itProbe->second.front().first ;
+        MPI_Status& status = itProbe->second.front().second ;
+        int count ;
+        MPI_Get_count(&status,MPI_CHAR,&count);
+        map<int,CServerBuffer*>::iterator it = buffers.find(rank);
+        if ( (it->second->isBufferFree(count) && !it->second->isResizing()) // accept new request if buffer is free
+          || (it->second->isResizing() && it->second->isBufferEmpty()) )    // or if resizing wait for buffer is empty
+        {
+          char * addr;
+          addr=(char*)it->second->getBuffer(count);
+          MPI_Imrecv(addr,count,MPI_CHAR, &message, &pendingRequest[rank]);
+          bufferRequest[rank]=addr;
+          recvProbe.push_back(rank) ;
+          itProbe->second.pop_front() ;
+        }
+      }
+    }
+
+    for(itRecv=recvProbe.begin(); itRecv!=recvProbe.end(); itRecv++) if (pendingProbe[*itRecv].empty()) pendingProbe.erase(*itRecv) ;
+  }
+
+
+  void CLegacyContextServer::checkPendingRequest(void)
+  {
+    map<int,MPI_Request>::iterator it;
+    list<int> recvRequest;
+    list<int>::iterator itRecv;
+    int rank;
+    int flag;
+    int count;
+    MPI_Status status;
+   
+    if (!pendingRequest.empty()) CTimer::get("receiving requests").resume();
+    else CTimer::get("receiving requests").suspend();
+
+    for(it=pendingRequest.begin();it!=pendingRequest.end();it++)
+    {
+      rank=it->first;
+      traceOff();
+      MPI_Test(& it->second, &flag, &status);
+      traceOn();
+      if (flag==true)
+      {
+        buffers[rank]->updateCurrentWindows() ;
+        recvRequest.push_back(rank);
+        MPI_Get_count(&status,MPI_CHAR,&count);
+        processRequest(rank,bufferRequest[rank],count);
+      }
+    }
+
+    for(itRecv=recvRequest.begin();itRecv!=recvRequest.end();itRecv++)
+    {
+      pendingRequest.erase(*itRecv);
+      bufferRequest.erase(*itRecv);
+    }
+  }
+
+  void CLegacyContextServer::getBufferFromClient(size_t timeLine)
+  {
+    CTimer::get("CLegacyContextServer::getBufferFromClient").resume() ;
+    if (!isAttachedModeEnabled()) // one sided desactivated in attached mode
+    {  
+      int rank ;
+      char *buffer ;
+      size_t count ; 
+
+      if (itLastTimeLine==lastTimeLine.end()) itLastTimeLine=lastTimeLine.begin() ;
+      for(;itLastTimeLine!=lastTimeLine.end();++itLastTimeLine)
+      {
+        rank=itLastTimeLine->first ;
+        if (itLastTimeLine->second < timeLine &&  pendingRequest.count(rank)==0 && buffers[rank]->isBufferEmpty())
+        {
+          if (buffers[rank]->getBufferFromClient(timeLine, buffer, count)) processRequest(rank, buffer, count);
+          if (count >= 0) ++itLastTimeLine ;
+          break ;
+        }
+      }
+    }
+    CTimer::get("CLegacyContextServer::getBufferFromClient").suspend() ;
+  }
+         
+       
+  void CLegacyContextServer::processRequest(int rank, char* buff,int count)
+  {
+
+    CBufferIn buffer(buff,count);
+    char* startBuffer,endBuffer;
+    int size, offset;
+    size_t timeLine=0;
+    map<size_t,CEventServer*>::iterator it;
+
+    
+    CTimer::get("Process request").resume();
+    while(count>0)
+    {
+      char* startBuffer=(char*)buffer.ptr();
+      CBufferIn newBuffer(startBuffer,buffer.remain());
+      newBuffer>>size>>timeLine;
+
+      if (timeLine==timelineEventNotifyChangeBufferSize)
+      {
+        buffers[rank]->notifyBufferResizing() ;
+        buffers[rank]->updateCurrentWindows() ;
+        buffers[rank]->popBuffer(count) ;
+        info(100)<<"Context id "<<context->getId()<<" : Receive NotifyChangeBufferSize from client rank "<<rank<<endl
+                 <<"isBufferEmpty ? "<<buffers[rank]->isBufferEmpty()<<"  remaining count : "<<buffers[rank]->getUsed()<<endl;
+      } 
+      else if (timeLine==timelineEventChangeBufferSize)
+      {
+        size_t newSize ;
+        vector<MPI_Aint> winAdress(2) ;
+        newBuffer>>newSize>>winAdress[0]>>winAdress[1] ;
+        buffers[rank]->freeBuffer(count) ;
+        delete buffers[rank] ;
+        buffers[rank] = new CServerBuffer(windows_[rank], winAdress, 0, 2*newSize) ;
+        info(100)<<"Context id "<<context->getId()<<" : Receive ChangeBufferSize from client rank "<<rank
+                 <<"  newSize : "<<newSize<<" Address : "<<winAdress[0]<<" & "<<winAdress[1]<<endl ;
+      }
+      else
+      {
+        info(100)<<"Context id "<<context->getId()<<" : Receive standard event from client rank "<<rank<<"  with timeLine : "<<timeLine<<endl ;
+        it=events.find(timeLine);
+       
+        if (it==events.end()) it=events.insert(pair<int,CEventServer*>(timeLine,new CEventServer(this))).first;
+        it->second->push(rank,buffers[rank],startBuffer,size);
+        if (timeLine>0) lastTimeLine[rank]=timeLine ;
+      }
+      buffer.advance(size);
+      count=buffer.remain();
+    }
+    
+    CTimer::get("Process request").suspend();
+  }
+
+  void CLegacyContextServer::processEvents(bool enableEventsProcessing)
+  {
+    map<size_t,CEventServer*>::iterator it;
+    CEventServer* event;
+    
+//    if (context->isProcessingEvent()) return ;
+    if (isProcessingEvent_) return ;
+    if (isAttachedModeEnabled())
+      if (!CXios::getDaemonsManager()->isScheduledContext(remoteHashId_)) return ;
+
+    it=events.find(currentTimeLine);
+    if (it!=events.end())
+    {
+      event=it->second;
+
+      if (event->isFull())
+      {
+        if (!scheduled && !isAttachedModeEnabled()) // Skip event scheduling for attached mode and reception on client side
+        {
+          eventScheduler_->registerEvent(currentTimeLine,hashId);
+          scheduled=true;
+        }
+        else if (isAttachedModeEnabled() || eventScheduler_->queryEvent(currentTimeLine,hashId) )
+        {
+          if (!enableEventsProcessing && isCollectiveEvent(*event)) return ;
+
+          if (!eventScheduled_) 
+          {
+            MPI_Ibarrier(processEventBarrier_,&processEventRequest_) ;
+            eventScheduled_=true ;
+            return ;
+          }
+          else 
+          {
+            MPI_Status status ;
+            int flag ;
+            MPI_Test(&processEventRequest_, &flag, &status) ;
+            if (!flag) return ;
+            eventScheduled_=false ;
+          }
+
+          if (!isAttachedModeEnabled()) eventScheduler_->popEvent() ;
+          //MPI_Barrier(intraComm) ;
+         // When using attached mode, synchronise the processes to avoid that differents event be scheduled by differents processes
+         // The best way to properly solve this problem will be to use the event scheduler also in attached mode
+         // for now just set up a MPI barrier
+//ym to be check later
+//         if (!eventScheduler_ && CXios::isServer) MPI_Barrier(intraComm) ;
+
+//         context->setProcessingEvent() ;
+         isProcessingEvent_=true ;
+         CTimer::get("Process events").resume();
+         info(100)<<"Context id "<<context->getId()<<" : Process Event "<<currentTimeLine<<" of class "<<event->classId<<" of type "<<event->type<<endl ;
+         dispatchEvent(*event);
+         CTimer::get("Process events").suspend();
+         isProcessingEvent_=false ;
+//         context->unsetProcessingEvent() ;
+         pendingEvent=false;
+         delete event;
+         events.erase(it);
+         currentTimeLine++;
+         scheduled = false;
+         if (isAttachedModeEnabled()) CXios::getDaemonsManager()->unscheduleContext() ;
+        }
+      }
+      else if (pendingRequest.empty()) getBufferFromClient(currentTimeLine) ;
+    }
+    else if (pendingRequest.empty()) getBufferFromClient(currentTimeLine) ; // if pure one sided check buffer even if no event recorded at current time line
+  }
+
+  CLegacyContextServer::~CLegacyContextServer()
+  {
+    map<int,CServerBuffer*>::iterator it;
+    for(it=buffers.begin();it!=buffers.end();++it) delete it->second;
+    buffers.clear() ;
+  }
+
+  void CLegacyContextServer::releaseBuffers()
+  {
+    //for(auto it=buffers.begin();it!=buffers.end();++it) delete it->second ;
+    //buffers.clear() ; 
+    freeWindows() ;
+  }
+
+  void CLegacyContextServer::freeWindows()
+  {
+    //if (!isAttachedModeEnabled())
+    //{
+    //  for(auto& it : winComm_)
+    //  {
+    //    int rank = it.first ;
+    //    MPI_Win_free(&windows_[rank][0]);
+    //    MPI_Win_free(&windows_[rank][1]);
+    //    MPI_Comm_free(&winComm_[rank]) ;
+    //  }
+    //}
+  }
+
+  void CLegacyContextServer::notifyClientsFinalize(void)
+  {
+    for(auto it=buffers.begin();it!=buffers.end();++it)
+    {
+      it->second->notifyClientFinalize() ;
+    }
+  }
+
+  void CLegacyContextServer::dispatchEvent(CEventServer& event)
+  {
+    string contextName;
+    string buff;
+    int MsgSize;
+    int rank;
+    list<CEventServer::SSubEvent>::iterator it;
+    StdString ctxId = context->getId();
+    CContext::setCurrent(ctxId);
+    StdSize totalBuf = 0;
+
+    if (event.classId==CContext::GetType() && event.type==CContext::EVENT_ID_CONTEXT_FINALIZE)
+    {
+      finished=true;
+      info(20)<<" CLegacyContextServer: Receive context <"<<context->getId()<<"> finalize."<<endl;
+      notifyClientsFinalize() ;
+      CTimer::get("receiving requests").suspend();
+      context->finalize();
+      
+      std::map<int, StdSize>::const_iterator itbMap = mapBufferSize_.begin(),
+                           iteMap = mapBufferSize_.end(), itMap;
+      for (itMap = itbMap; itMap != iteMap; ++itMap)
+      {
+        rank = itMap->first;
+        report(10)<< " Memory report : Context <"<<ctxId<<"> : server side : memory used for buffer of each connection to client" << endl
+            << "  +) With client of rank " << rank << " : " << itMap->second << " bytes " << endl;
+        totalBuf += itMap->second;
+      }
+      report(0)<< " Memory report : Context <"<<ctxId<<"> : server side : total memory used for buffer "<<totalBuf<<" bytes"<<endl;
+    }
+    else if (event.classId==CContext::GetType()) CContext::dispatchEvent(event);
+    else if (event.classId==CContextGroup::GetType()) CContextGroup::dispatchEvent(event);
+    else if (event.classId==CCalendarWrapper::GetType()) CCalendarWrapper::dispatchEvent(event);
+    else if (event.classId==CDomain::GetType()) CDomain::dispatchEvent(event);
+    else if (event.classId==CDomainGroup::GetType()) CDomainGroup::dispatchEvent(event);
+    else if (event.classId==CAxis::GetType()) CAxis::dispatchEvent(event);
+    else if (event.classId==CAxisGroup::GetType()) CAxisGroup::dispatchEvent(event);
+    else if (event.classId==CScalar::GetType()) CScalar::dispatchEvent(event);
+    else if (event.classId==CScalarGroup::GetType()) CScalarGroup::dispatchEvent(event);
+    else if (event.classId==CGrid::GetType()) CGrid::dispatchEvent(event);
+    else if (event.classId==CGridGroup::GetType()) CGridGroup::dispatchEvent(event);
+    else if (event.classId==CField::GetType()) CField::dispatchEvent(event);
+    else if (event.classId==CFieldGroup::GetType()) CFieldGroup::dispatchEvent(event);
+    else if (event.classId==CFile::GetType()) CFile::dispatchEvent(event);
+    else if (event.classId==CFileGroup::GetType()) CFileGroup::dispatchEvent(event);
+    else if (event.classId==CVariable::GetType()) CVariable::dispatchEvent(event);
+    else
+    {
+      ERROR("void CLegacyContextServer::dispatchEvent(CEventServer& event)",<<" Bad event class Id"<<endl);
+    }
+  }
+
+  bool CLegacyContextServer::isCollectiveEvent(CEventServer& event)
+  {
+    if (event.type>1000) return false ;
+    else return true ;
+  }
+}
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/legacy_context_server.hpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/legacy_context_server.hpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/legacy_context_server.hpp	(revision 2343)
@@ -0,0 +1,74 @@
+#ifndef __LEGACY_CONTEXT_SERVER_HPP__
+#define __LEGACY_CONTEXT_SERVER_HPP__
+#include "xios_spl.hpp"
+#include "event_server.hpp"
+#include "buffer_server.hpp"
+#include "mpi.hpp"
+#include "event_scheduler.hpp"
+#include "context_server.hpp"
+
+namespace xios
+{
+  class CContext ;
+  class CContextClient;
+
+  class CLegacyContextServer : public CContextServer
+  {
+    public:
+
+    CLegacyContextServer(CContext* parent,MPI_Comm intraComm,MPI_Comm interComm) ;
+    bool eventLoop(bool enableEventsProcessing = true);
+    void releaseBuffers(void) ;
+
+    private:
+
+    void listen(void) ;
+//    bool listenPendingRequest(MPI_Status& status) ;
+    bool listenPendingRequest(MPI_Message &message, MPI_Status& status) ;
+    void checkPendingProbe(void) ;
+    void checkPendingRequest(void) ;
+    void getBufferFromClient(size_t timeLine) ;
+    void processRequest(int rank, char* buff,int count) ;
+    void processEvents(bool enableEventsProcessing) ;
+    bool hasFinished(void);
+    void dispatchEvent(CEventServer& event) ;
+    bool isCollectiveEvent(CEventServer& event) ;
+    void setPendingEvent(void) ;
+    bool hasPendingEvent(void) ;
+    void notifyClientsFinalize(void) ;
+    void freeWindows(void) ; // !<< free Windows for one sided communication
+
+    MPI_Comm interCommMerged_; //!< Communicator of the client group + server group (intraCommunicator) needed for one sided communication.
+    MPI_Comm commSelf_ ; //!< Communicator for proc alone from interCommMerged 
+
+    map<int,CServerBuffer*> buffers ;
+    map<int,size_t> lastTimeLine ; //!< last event time line for a processed request
+    map<int,size_t>::iterator itLastTimeLine ; //!< iterator on lastTimeLine
+    map<int, list<std::pair<MPI_Message,MPI_Status> > > pendingProbe;
+    map<int,MPI_Request> pendingRequest ;
+    map<int,char*> bufferRequest ;
+
+    map<size_t,CEventServer*> events ;
+    size_t currentTimeLine ;
+      
+    bool finished ;
+    bool pendingEvent ;
+    bool scheduled  ;    /*!< event of current timeline is alreading scheduled ? */
+    bool pureOneSided ; //!< if true, client will communicated with servers only trough one sided communication. Otherwise the hybrid mode P2P /One sided is used.
+
+    ~CLegacyContextServer() ;
+  
+      std::map<int, StdSize> mapBufferSize_;
+      std::map<int,MPI_Comm> winComm_ ; //! Window communicators
+      std::map<int,std::vector<MPI_Win> >windows_ ; //! one sided mpi windows to expose client buffers to servers ; No memory will be attached on server side.
+      bool isProcessingEvent_ ;
+      size_t remoteHashId_; //!< the hash is of the calling context client
+      
+      MPI_Comm processEventBarrier_ ;
+      bool eventScheduled_=false;
+      MPI_Request processEventRequest_ ;
+  } ;
+
+}
+
+#endif
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_client_buffer.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_client_buffer.cpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_client_buffer.cpp	(revision 2343)
@@ -0,0 +1,283 @@
+#include "one_sided_client_buffer.hpp"
+#include "event_client.hpp"
+#include "timer.hpp"
+
+namespace xios
+{
+  
+  static CLogType logProtocol("log_protocol") ;
+
+  COneSidedClientBuffer::COneSidedClientBuffer(MPI_Comm& interComm, int serverRank, MPI_Comm& commSelf, MPI_Comm& interCommMerged, int intraServerRank) : interComm_(interComm), serverRank_(serverRank)
+  {
+    
+    MPI_Alloc_mem(controlSize_*sizeof(MPI_Aint), MPI_INFO_NULL, &control_) ;
+    control_[CONTROL_ADDR] = 0 ;
+    control_[CONTROL_FINALIZE] = 0 ;
+    sendNewBuffer() ;
+    createWindow(commSelf, interCommMerged, intraServerRank ) ;
+  }
+
+  void COneSidedClientBuffer::createWindow(MPI_Comm& commSelf, MPI_Comm& interCommMerged, int intraServerRank )
+  {
+    CTimer::get("create Windows").resume() ;
+    MPI_Comm interComm ;
+    MPI_Intercomm_create(commSelf, 0, interCommMerged, intraServerRank, 0, &interComm) ;
+    MPI_Intercomm_merge(interComm, false, &winComm_) ;
+    int rank ;
+    MPI_Comm_rank(winComm_,&rank) ;
+    info(logProtocol)<<"Windows rank="<<rank<<endl ;
+    CXios::getMpiGarbageCollector().registerCommunicator(winComm_) ;
+    MPI_Comm_free(&interComm) ;
+    
+    maxWindows_=MAX_WINDOWS ;    
+    windows_.resize(maxWindows_) ;
+    usedWindows_.resize(maxWindows_,false) ;
+    for(int i=0;i<maxWindows_;++i) 
+    {
+      MPI_Win_create_dynamic(MPI_INFO_NULL, winComm_, &windows_[i]);
+      CXios::getMpiGarbageCollector().registerWindow(windows_[i]) ;
+    }
+    currentWindow_=-1 ;
+    
+    MPI_Win_create_dynamic(MPI_INFO_NULL, winComm_, &winControl_);
+    CXios::getMpiGarbageCollector().registerWindow(winControl_) ;
+
+    
+
+    CTimer::get("create Windows").suspend() ;
+
+    MPI_Barrier(winComm_) ;
+    MPI_Win_attach(winControl_, control_, controlSize_*sizeof(MPI_Aint)) ;
+    MPI_Barrier(winComm_) ;
+ //   MPI_Win_lock(MPI_LOCK_EXCLUSIVE, 0, 0, winControl_) ;
+ //   MPI_Win_unlock(0,winControl_) ;
+
+  } 
+
+
+
+  void COneSidedClientBuffer::newBuffer(size_t size, bool fixed)
+  { 
+    currentWindow_=(currentWindow_+1)%maxWindows_ ;
+    if (usedWindows_[currentWindow_]) 
+    {
+      ERROR("void COneSidedClientBuffer::newBuffer(size_t size, bool fixed)",<<"Try to alloc buffer to a window already in use"<<endl ) ;
+    }
+    else usedWindows_[currentWindow_]=true ;
+    buffers_.push_back(new CBuffer(windows_[currentWindow_], size, fixed)); 
+    currentBuffer_=buffers_.back() ;
+    info(logProtocol)<<"   Nb attached memory blocs="<<buffers_.size()<<endl ;
+  }
+
+  bool COneSidedClientBuffer::isBufferFree(size_t size)
+  {
+    if (buffers_.size()>maxWindows_-1) return false ; 
+    CBuffer* buffer ;
+    if (buffers_.size()==0) return true ;
+    else if (!fixed) return true ;
+    else 
+    {
+      buffer = buffers_.back() ;
+      if (buffer->remain()>=size) return true ;
+      else
+      {
+        if (buffer->isFixed()) 
+        {
+          if ( size > buffer->getSize()) return true ;
+          else return false ;
+        }
+        else return true ;
+      }
+    }
+  }
+  
+  int COneSidedClientBuffer::writeBuffer(char* buffer, size_t size)
+  {
+    MPI_Aint addr ;
+    size_t start ;
+    size_t count ;
+    int nbBlocs=0 ;
+
+    if (isBufferFree(size))
+    {
+      while (size > 0)
+      {
+        if (buffers_.empty())
+        {
+          if (fixed_) newBuffer(fixedSize_,fixed_) ;
+          else
+          { 
+            if (currentBufferSize_==0) currentBufferSize_=size ;
+            newBuffer(currentBufferSize_, fixed_) ;
+          }
+        }
+        CBuffer* currentBuffer = buffers_.back() ;
+
+        MPI_Win_lock(MPI_LOCK_SHARED, 0, 0, windows_[currentWindow_]) ;
+        currentBuffer->write(&buffer, size, addr, start, count) ;
+        if (count > 0) 
+        {
+          blocs_.push_back({addr,currentBuffer_, start, count, currentWindow_}) ;
+          nbBlocs++ ; 
+        }
+
+        currentBuffer->write(&buffer, size, addr, start, count) ;
+        MPI_Win_unlock(0,windows_[currentWindow_]) ;
+
+        if (count > 0) 
+        {
+          blocs_.push_back({addr,currentBuffer_, start, count, currentWindow_}) ;
+          nbBlocs++ ; 
+        }
+
+        if (size>0) 
+        {
+          if (fixed_) 
+          {
+            currentBufferSize_ = fixedSize_ ;
+            newBuffer(currentBufferSize_,fixed_) ;
+          }
+          else
+          {
+            currentBufferSize_ = max((size_t)(currentBufferSize_*growingFactor_), size) ;
+            newBuffer(currentBufferSize_,fixed_) ;
+          }
+        } 
+      }      
+      // send message here ?
+      return nbBlocs ;
+    }
+    else return 0 ;
+  }
+
+  void COneSidedClientBuffer::freeBuffer(MPI_Aint addr)
+  {
+//    if (addr != lastFreedBloc_)
+    if (addr != 0)
+    {
+      while(freeBloc(addr)) ;
+//      lastFreedBloc_ = addr ;
+    }
+    
+    if (isFinalized_ && !buffers_.empty() && buffers_.front()->getCount()==0) 
+    {
+      delete buffers_.front() ;
+      buffers_.pop_front() ;
+    }
+  }
+  
+  bool COneSidedClientBuffer::freeBloc(MPI_Aint addr)
+  {
+    SBloc& bloc = blocs_.front() ;
+    bloc.buffer->free(bloc.start, bloc.count) ;
+    if (bloc.buffer->getCount()==0) 
+      if (buffers_.size()>1) 
+      {  
+        usedWindows_[bloc.window]=false ;
+        delete buffers_.front() ;
+        buffers_.pop_front() ;
+      }
+    
+    if (addr != bloc.addr) 
+    {
+      blocs_.pop_front() ;
+      return true ;
+    }
+    else 
+    {
+      blocs_.pop_front() ;
+      return false ;
+    }
+
+  }
+
+  bool COneSidedClientBuffer::writeEvent(size_t timeline, CEventClient& event)
+  {
+    size_t size = event.getSize() ;
+    if (isBufferFree(size))
+    {
+      CBufferOut buffer(size) ;
+      event.send(timeline, size, &buffer) ;
+      size_t bufferSizeBefore = currentBufferSize_ ; 
+      int nbBlocs = writeBuffer((char*)buffer.start(),buffer.count()) ;
+      if (currentBufferSize_!=bufferSizeBefore) sendResizeBufferEvent(timeline,currentBufferSize_) ;
+      sendTimelineEvent(timeline, event.getNbSender(), nbBlocs) ;
+      return true ;
+    }
+    else return false ;
+  }
+
+  void COneSidedClientBuffer::eventLoop(void)
+  {
+    // check to free requests
+    int flag ;
+    bool out = true;
+    SRequest request ; 
+    while (!requests_.empty() && out) 
+    {
+      request = requests_.front() ;
+      MPI_Test(&request.mpiRequest, &flag, MPI_STATUS_IGNORE) ;
+      if (flag==true)
+      {
+        delete request.buffer ;
+        requests_.pop_front() ;
+      }
+      else out=false; 
+    }
+    
+    // check to free blocs
+    MPI_Aint addr ;
+    MPI_Aint finalize ;
+    MPI_Win_lock(MPI_LOCK_SHARED, 0, 0, winControl_) ;
+    addr = control_[CONTROL_ADDR] ;
+    control_[CONTROL_ADDR] = 0 ;
+    finalize = control_[CONTROL_FINALIZE] ;
+    MPI_Win_unlock(0, winControl_) ;
+    freeBuffer(addr) ;
+    if (finalize==1) isFinalized_=true ;
+
+
+  }
+
+  void COneSidedClientBuffer::sendTimelineEvent(size_t timeline, int nbSenders, int nbBlocs)
+  {
+    ostringstream outStr ;
+    SRequest request ;
+    request.buffer = new CBufferOut(sizeof(timeline)+sizeof(nbSenders)+sizeof(nbBlocs)+(sizeof(MPI_Aint)+sizeof(int)+sizeof(int))*nbBlocs) ; 
+    *(request.buffer)<<timeline<<nbSenders<<nbBlocs ;
+    if (info.isActive(logProtocol))  outStr<<"New timeline event sent to server rank "<<serverRank_<<" : timeLine="<<timeline<<"  nbSenders="<<nbSenders<<"  nbBlocs="<<nbBlocs<<endl ;
+    auto it = blocs_.end() ;
+    for(int i=0 ; i<nbBlocs; ++i,--it) ;
+    for(int i=0 ; i<nbBlocs; ++i,++it) 
+    {
+      *(request.buffer) << it->addr << it->count << it->window;
+    
+      if (info.isActive(logProtocol))
+      {
+        size_t checksum=0 ;
+        for(size_t j=0;j<it->count;j++) checksum+=((unsigned char*)(it->addr))[j] ;
+        outStr<<"Bloc "<<i<<"  addr="<<it->addr<<"  count="<<it->count<<"  checksum="<<checksum<<"  ;  " ;
+      }
+    }
+    MPI_Isend(request.buffer->start(),request.buffer->count(), MPI_CHAR, serverRank_, 20, interComm_, &request.mpiRequest ) ;
+    info(logProtocol)<<outStr.str()<<endl ;
+    requests_.push_back(request) ;
+  }
+
+  void COneSidedClientBuffer::sendResizeBufferEvent(size_t timeline, size_t size)
+  {
+    SRequest request ;
+    request.buffer = new CBufferOut(sizeof(EVENT_BUFFER_RESIZE)+sizeof(timeline)+sizeof(size)) ; 
+    *(request.buffer)<<EVENT_BUFFER_RESIZE<<timeline<<size ;
+    MPI_Isend(request.buffer->start(),request.buffer->count(), MPI_CHAR, serverRank_, 20, interComm_, &request.mpiRequest ) ;
+    requests_.push_back(request) ;
+  }
+
+  void COneSidedClientBuffer::sendNewBuffer(void)
+  {
+    MPI_Aint controlAddr ;
+    MPI_Get_address(control_, &controlAddr) ;
+    MPI_Send(&controlAddr, 1, MPI_AINT, serverRank_, 20, interComm_) ;
+  }
+
+}
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_client_buffer.hpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_client_buffer.hpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_client_buffer.hpp	(revision 2343)
@@ -0,0 +1,202 @@
+#ifndef __ONE_SIDED_CLIENT_BUFFER_HPP__
+#define __ONE_SIDED_CLIENT_BUFFER_HPP__
+
+#include "xios_spl.hpp"
+#include "buffer_out.hpp"
+#include "mpi.hpp"
+#include "cxios.hpp"
+#include "event_client.hpp"
+#include "one_sided_cs_buffer_base.hpp"
+
+namespace xios
+{
+  extern CLogType logProtocol ;
+
+  class COneSidedClientBuffer : public COneSidedCSBufferBase
+  {
+    class CBuffer
+    {
+      char* buffer_ ;
+      size_t start_ ;
+      size_t end_ ;
+      size_t count_ ;
+      size_t size_ ;
+      bool fixed_ ;
+      MPI_Win window_ ;
+
+      public:
+        CBuffer(MPI_Win window, size_t size, bool fixed) : start_(size), end_(0), count_(0), size_(size), fixed_(fixed), window_(window) 
+        { 
+          size_t trueSize = (size/8 + 1)*8 + 8 ;  // seems to have some problem with OpenMPi/UCX when trying to tranfer 1 byte
+                                                  // at the end of the buffer. Alignment problem ? Or simple bug ? Seems that allocate
+                                                  // greater buffer solves the problem 
+          MPI_Alloc_mem(trueSize, MPI_INFO_NULL, &buffer_) ;
+          info(logProtocol)<<"Attach memory to windows : addr="<<(MPI_Aint)buffer_<<"   count="<<size<<endl ;
+
+          MPI_Win_attach(window_, buffer_, trueSize) ;
+          
+        }
+        ~CBuffer() 
+        { 
+          if (count_>0) ERROR("COneSidedClientBuffer::~CBuffer()",<<"Try to delete buffer that is not empty"<<std::endl) ;
+          MPI_Win_detach(window_, buffer_) ;
+          MPI_Free_mem(buffer_) ;
+          info(logProtocol)<<"Detach memory from windows : addr="<<(MPI_Aint)buffer_<<"   count="<<size_<<endl ;
+        }
+       
+        void write(char** buffer, size_t& size, MPI_Aint& addr, size_t& start, size_t& count)
+        {
+          addr = 0 ;
+          count = 0 ;
+          if (end_ < start_)
+          {
+            if (start_-end_ >= size)
+            {
+              count=size ;
+              size = 0 ;
+              start=end_ ;
+              MPI_Get_address(&buffer_[start], &addr) ;
+              end_  += count ; 
+              count_+= count ;
+              memcpy(&buffer_[start], *buffer, count) ;
+              *buffer+=count ;
+            } 
+            else
+            {
+              count = start_-end_ ;
+              size -= count ;
+              start=end_ ;
+              MPI_Get_address(&buffer_[start], &addr) ;
+              end_ = start_ ;
+              count_+=count ;
+              memcpy(&buffer_[start], *buffer, count) ;
+              *buffer+=count ;
+            }
+          }
+          else if ( end_> start_ )
+          {
+            if (size_-end_ >= size)
+            {
+              count = size ;
+              size = 0;
+              start=end_ ;
+              MPI_Get_address(&buffer_[start], &addr) ;
+              end_   += count ;
+              count_ += count ;
+              memcpy(&buffer_[start], *buffer, count) ;
+              *buffer+=count ;
+            }
+            else
+            {
+              count = size_ - end_ ;
+              size -= count ;
+              start=end_ ;
+              MPI_Get_address(&buffer_[start], &addr) ;
+              end_ = 0 ;
+              count_+= count ;
+              memcpy(&buffer_[start], *buffer, count) ;
+              *buffer+=count ;
+            }
+          }
+          else if (end_==start_)
+          {
+            count = 0 ;
+          }
+
+          // check
+
+          if (count!=0)
+          {
+            MPI_Aint startBufferAddr,endBufferAddr ;
+            MPI_Get_address(&buffer_[0], &startBufferAddr) ;
+            MPI_Get_address(&buffer_[size_-1], &endBufferAddr) ;
+
+            if (addr<startBufferAddr || MPI_Aint_add(addr,count-1)>endBufferAddr)
+            {
+              ERROR("COneSidedClientBuffer::CBuffer::write(char** buffer, size_t& size, MPI_Aint& addr, size_t& start, size_t& count)",<<" out of bounds"<<std::endl) ;
+            }
+
+          }
+        }
+
+        void free(size_t start, size_t count)
+        {
+          start_ = start+count-1 ;
+          count_ -= count ;
+        }
+
+        size_t remain(void) { return size_-count_; }
+        size_t getSize(void) { return size_ ;}
+        size_t getCount(void) {return count_ ;}
+        size_t isFixed(void) {return fixed_;}
+    } ;
+  
+    public:
+      COneSidedClientBuffer(MPI_Comm& interComm, int serverRank, MPI_Comm& commSelf, MPI_Comm& interCommMerged, int intraServerRank) ;
+      void newBuffer(size_t size, bool fixed) ;
+      bool isBufferFree(size_t size) ;
+      int writeBuffer(char* buff, size_t size) ;
+      void freeBuffer(MPI_Aint addr) ;
+      bool freeBloc(MPI_Aint addr) ;
+      bool writeEvent(size_t timeLine, CEventClient& event) ;
+      bool isEmpty(void) { return blocs_.empty() ;}
+      bool isNotifiedFinalized(void) { eventLoop() ; return buffers_.empty() && isFinalized_ ;}
+      void setFixed(size_t size) { fixed_=true ; fixedSize_=size ;}
+      void setGrowable(double growingFactor) { fixed_= false ; growingFactor_=growingFactor;}
+      void setGrowingFactor(double growingFactor) {growingFactor_=growingFactor;}
+      void eventLoop(void) ;
+      void sendTimelineEvent(size_t timeline, int nbSenders, int nbBlocs) ;
+      void sendResizeBufferEvent(size_t timeline, size_t currentBufferSize_) ;
+      void sendNewBuffer(void) ;
+      void createWindow(MPI_Comm& commSelf, MPI_Comm& interCommMerged, int intraServerRank ) ;
+
+    private :
+      
+      struct SBloc
+      {
+        MPI_Aint addr ;
+        CBuffer* buffer ;
+        size_t start ;
+        int    count ;
+        int    window ;
+      } ;
+
+      struct SRequest
+      {
+        CBufferOut* buffer ;
+        MPI_Request mpiRequest ;
+      } ;
+      
+      MPI_Aint* control_ ;
+
+      MPI_Comm interComm_; 
+      MPI_Comm winComm_ ;
+
+      MPI_Win window_ ;
+      vector<MPI_Win> windows_ ;
+      vector<bool> usedWindows_ ;
+      int currentWindow_ ;
+      int maxWindows_ ;
+
+      MPI_Win winControl_ ;
+      int serverRank_ ;
+
+      std::list<CBuffer*> buffers_ ;
+      std::list<SBloc> blocs_ ;
+      std::list<SBloc>::iterator lastBlocEvent_ ;
+      CBuffer* currentBuffer_=nullptr ;
+      std::list<SRequest> requests_ ;
+
+      bool fixed_=false;
+      size_t fixedSize_ = 0 ;
+      size_t currentBufferSize_=0 ;
+      double growingFactor_ = 2. ; 
+      MPI_Aint lastFreedBloc_=0 ;
+      bool isFinalized_ = false ;
+
+  } ;
+
+}
+
+
+#endif
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_context_client.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_context_client.cpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_context_client.cpp	(revision 2343)
@@ -0,0 +1,268 @@
+#include "xios_spl.hpp"
+#include "one_sided_context_client.hpp"
+#include "context_server.hpp"
+#include "event_client.hpp"
+#include "buffer_out.hpp"
+#include "type.hpp"
+#include "event_client.hpp"
+#include "context.hpp"
+#include "mpi.hpp"
+#include "timer.hpp"
+#include "cxios.hpp"
+#include "server.hpp"
+#include "services.hpp"
+#include <boost/functional/hash.hpp>
+#include <random>
+#include <chrono>
+
+namespace xios
+{
+    /*!
+    \param [in] parent Pointer to context on client side
+    \param [in] intraComm_ communicator of group client
+    \param [in] interComm_ communicator of group server
+    \cxtSer [in] cxtSer Pointer to context of server side. (It is only used in case of attached mode).
+    */
+    COneSidedContextClient::COneSidedContextClient(CContext* parent, MPI_Comm intraComm_, MPI_Comm interComm_, CContext* cxtSer)
+     : CContextClient(parent, intraComm_, interComm_, cxtSer),
+       mapBufferSize_(), maxBufferedEvents(4)
+    {
+      
+      pureOneSided=CXios::getin<bool>("pure_one_sided",false); // pure one sided communication (for test)
+      if (isAttachedModeEnabled()) pureOneSided=false ; // no one sided in attach mode
+
+      if (!isAttachedModeEnabled()) MPI_Intercomm_merge(interComm_,false, &interCommMerged_) ;
+      
+      MPI_Comm_split(intraComm_,clientRank,clientRank, &commSelf_) ; // for windows
+
+      timeLine = 1;
+    }
+
+
+    /*!
+    In case of attached mode, the current context must be reset to context for client
+    \param [in] event Event sent to server
+    */
+    void COneSidedContextClient::sendEvent(CEventClient& event)
+    {
+      list<int> ranks = event.getRanks();
+ 
+//      ostringstream str ;
+//      for(auto& rank : ranks) str<<rank<<" ; " ;
+//      info(100)<<"Event "<<timeLine<<" of context "<<context_->getId()<<"  for ranks : "<<str.str()<<endl ;
+
+      if (CXios::checkEventSync)
+      {
+        int typeId, classId, typeId_in, classId_in;
+        long long timeLine_out;
+        long long timeLine_in( timeLine );
+        typeId_in=event.getTypeId() ;
+        classId_in=event.getClassId() ;
+//        MPI_Allreduce(&timeLine,&timeLine_out, 1, MPI_UINT64_T, MPI_SUM, intraComm) ; // MPI_UINT64_T standardized by MPI 3
+        MPI_Allreduce(&timeLine_in,&timeLine_out, 1, MPI_LONG_LONG_INT, MPI_SUM, intraComm) ; 
+        MPI_Allreduce(&typeId_in,&typeId, 1, MPI_INT, MPI_SUM, intraComm) ;
+        MPI_Allreduce(&classId_in,&classId, 1, MPI_INT, MPI_SUM, intraComm) ;
+        if (typeId/clientSize!=event.getTypeId() || classId/clientSize!=event.getClassId() || timeLine_out/clientSize!=timeLine)
+        {
+           ERROR("void COneSidedContextClient::sendEvent(CEventClient& event)",
+               << "Event are not coherent between client for timeline = "<<timeLine);
+        }
+        
+        vector<int> servers(serverSize,0) ;
+        auto ranks=event.getRanks() ;
+        for(auto& rank : ranks) servers[rank]=1 ;
+        MPI_Allreduce(MPI_IN_PLACE, servers.data(), serverSize,MPI_INT,MPI_SUM,intraComm) ;
+        ostringstream osstr ;
+        for(int i=0;i<serverSize;i++)  if (servers[i]==0) osstr<<i<<" , " ;
+        if (!osstr.str().empty())
+        {
+          ERROR("void COneSidedContextClient::sendEvent(CEventClient& event)",
+                 <<" Some servers will not receive the message for timeline = "<<timeLine<<endl
+                 <<"Servers are : "<<osstr.str()) ;
+        }
+
+
+      }
+      
+      event.setFirst() ;
+      while(!event.isEmpty())
+      {
+        int rank=event.getRank() ;
+        auto itBuffer=buffers.find(rank) ;
+        if (itBuffer==buffers.end()) 
+        {  
+          newBuffer(rank) ;
+          itBuffer=buffers.find(rank) ;
+        }
+        itBuffer->second->eventLoop() ;
+        bool succed = itBuffer->second->writeEvent(timeLine, event)  ;
+        if (succed) event.remove() ;
+        else event.next() ;
+        if (event.isFirst()) callGlobalEventLoop() ;
+      }
+      
+      if (isAttachedModeEnabled()) // couldBuffer is always true in attached mode
+      {
+        while (checkBuffers(ranks)) callGlobalEventLoop() ;
+      
+        CXios::getDaemonsManager()->scheduleContext(hashId_) ;
+        while (CXios::getDaemonsManager()->isScheduledContext(hashId_)) callGlobalEventLoop() ;
+      }
+      
+      timeLine++;
+    }
+
+
+   void COneSidedContextClient::eventLoop(void)
+   {
+      if (!locked_) checkBuffers() ;
+   }
+
+   void COneSidedContextClient::callGlobalEventLoop(void)
+   {
+     locked_=true ;
+     context_->globalEventLoop() ;
+     locked_=false ;
+   }
+   /*!
+   Make a new buffer for a certain connection to server with specific rank
+   \param [in] rank rank of connected server
+   */
+   void COneSidedContextClient::newBuffer(int rank)
+   {
+      if (!mapBufferSize_.count(rank))
+      {
+        error(0) << "WARNING: Unexpected request for buffer to communicate with server " << rank << std::endl;
+        mapBufferSize_[rank] = CXios::minBufferSize;
+        maxEventSizes[rank] = CXios::minBufferSize;
+      }
+
+      COneSidedClientBuffer* buffer = buffers[rank] = new COneSidedClientBuffer(interComm, rank, commSelf_, interCommMerged_, clientSize+rank );
+      if (isGrowableBuffer_) { buffer->setGrowable(growingFactor_) ; }
+      else buffer->setFixed(mapBufferSize_[rank]) ;
+  
+   }
+
+   /*!
+   Verify state of buffers. Buffer is under pending state if there is no message on it
+   \return state of buffers, pending(true), ready(false)
+   */
+   bool COneSidedContextClient::checkBuffers(void)
+   {
+      bool pending = false;
+      for (auto itBuff : buffers)
+      {
+        itBuff.second->eventLoop() ;
+        pending |= itBuff.second->isEmpty();
+      }
+      return pending;
+   }
+
+   //! Release all buffers
+   void COneSidedContextClient::releaseBuffers()
+   {
+      for (auto& itBuff : buffers) delete itBuff.second;
+      buffers.clear();
+   }
+
+
+   /*!
+   Verify state of buffers corresponding to a connection
+   \param [in] ranks list rank of server to which client connects to
+   \return state of buffers, pending(true), ready(false)
+   */
+   bool COneSidedContextClient::checkBuffers(list<int>& ranks)
+   {
+      bool pending = false;
+      for (auto& rank : ranks) 
+      {
+        buffers[rank]->eventLoop() ;
+        pending |= buffers[rank]->isEmpty() ;
+      }
+      return pending;
+   }
+
+   /*!
+    * Set the buffer size for each connection. Warning: This function is collective.
+    *
+    * \param [in] mapSize maps the rank of the connected servers to the size of the correspoinding buffer
+    * \param [in] maxEventSize maps the rank of the connected servers to the size of the biggest event
+   */
+   void COneSidedContextClient::setBufferSize(const std::map<int,StdSize>& mapSize)
+   {
+     setFixedBuffer() ;
+     for(auto& it : mapSize)
+     {
+      size_t size=std::max(CXios::minBufferSize*1.0,std::min(it.second*CXios::bufferSizeFactor*1.01,CXios::maxBufferSize*1.0)) * 8 ; // double
+      mapBufferSize_[it.first]=size ;
+      if (buffers.count(it.first)>0) buffers[it.first]->setFixed(size);
+     }
+   }
+
+
+   /*!
+   * Finalize context client and do some reports. Function is non-blocking.
+   */
+  void COneSidedContextClient::finalize(void)
+  {
+    bool stop = false;
+
+    int* nbServerConnectionLocal  = new int[serverSize] ;
+    int* nbServerConnectionGlobal  = new int[serverSize] ;
+    for(int i=0;i<serverSize;++i) nbServerConnectionLocal[i]=0 ;
+    for (auto itBuff = buffers.begin(); itBuff != buffers.end(); itBuff++)  nbServerConnectionLocal[itBuff->first]=1 ;
+    for (auto ItServerLeader = ranksServerLeader.begin(); ItServerLeader != ranksServerLeader.end(); ItServerLeader++)  nbServerConnectionLocal[*ItServerLeader]=1 ;
+    
+    MPI_Allreduce(nbServerConnectionLocal, nbServerConnectionGlobal, serverSize, MPI_INT, MPI_SUM, intraComm);
+    
+    CEventClient event(CContext::GetType(), CContext::EVENT_ID_CONTEXT_FINALIZE);
+    CMessage msg;
+
+    for (int i=0;i<serverSize;++i) if (nbServerConnectionLocal[i]==1) event.push(i, nbServerConnectionGlobal[i], msg) ;
+    sendEvent(event);
+
+    delete[] nbServerConnectionLocal ;
+    delete[] nbServerConnectionGlobal ;
+
+
+    CTimer::get("Blocking time").resume();
+    checkBuffers();
+    CTimer::get("Blocking time").suspend();
+
+    std::map<int,StdSize>::const_iterator itbMap = mapBufferSize_.begin(),
+                                          iteMap = mapBufferSize_.end(), itMap;
+
+    StdSize totalBuf = 0;
+    for (itMap = itbMap; itMap != iteMap; ++itMap)
+    {
+      report(10) << " Memory report : Context <" << context_->getId() << "> : client side : memory used for buffer of each connection to server" << endl
+                 << "  +) To server with rank " << itMap->first << " : " << itMap->second << " bytes " << endl;
+      totalBuf += itMap->second;
+    }
+    report(0) << " Memory report : Context <" << context_->getId() << "> : client side : total memory used for buffer " << totalBuf << " bytes" << endl;
+
+  }
+
+
+  /*!
+  */
+  bool COneSidedContextClient::havePendingRequests(void)
+  {
+    return checkBuffers();
+  }
+  
+  bool COneSidedContextClient::havePendingRequests(list<int>& ranks)
+  {
+    return checkBuffers(ranks) ;
+  }
+
+  bool COneSidedContextClient::isNotifiedFinalized(void)
+  {
+    if (isAttachedModeEnabled()) return true ;
+
+    bool finalized = true;
+    for (auto& it : buffers ) finalized &= it.second->isNotifiedFinalized();
+    return finalized;
+  }
+
+}
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_context_client.hpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_context_client.hpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_context_client.hpp	(revision 2343)
@@ -0,0 +1,85 @@
+#ifndef __ONE_SIDED_CONTEXT_CLIENT_HPP__
+#define __ONE_SIDED_CONTEXT_CLIENT_HPP__
+
+#include "xios_spl.hpp"
+#include "buffer_out.hpp"
+#include "buffer_in.hpp"
+#include "one_sided_client_buffer.hpp"
+#include "event_client.hpp"
+#include "event_server.hpp"
+#include "mpi.hpp"
+#include "registry.hpp"
+#include "context_client.hpp"
+
+namespace xios
+{
+  class CContext;
+  class CContextServer ;
+  /*!
+  \class CContextClient
+  A context can be both on client and on server side. In order to differenciate the role of
+  context on each side, e.x client sending events, server receiving and processing events, there is a need of
+  concrete "context" classes for both sides.
+  CContextClient processes and sends events from client to server where CContextServer receives these events
+  and processes them.
+  */
+  class COneSidedContextClient : public CContextClient
+  {
+    public:
+      // Contructor
+      COneSidedContextClient(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer = 0);
+
+      // Send event to server
+      void sendEvent(CEventClient& event);
+      bool havePendingRequests(void);
+      void releaseBuffers(void);
+      bool isNotifiedFinalized(void) ;
+      void finalize(void);
+      void setBufferSize(const std::map<int,StdSize>& mapSize);
+    
+    private:
+
+      // Functions to set/get buffers
+      bool getBuffers(const size_t timeLine, const list<int>& serverList, const list<int>& sizeList, list<CBufferOut*>& retBuffers, bool nonBlocking = false);
+      void newBuffer(int rank);
+      bool checkBuffers(list<int>& ranks);
+      bool checkBuffers(void);
+      void eventLoop(void) ;
+      void callGlobalEventLoop() ;
+      bool havePendingRequests(list<int>& ranks) ;
+
+
+
+      void setGrowableBuffer(void) { isGrowableBuffer_=true;}
+      void setFixedBuffer(void) { isGrowableBuffer_=false;}
+
+      size_t timeLine; //!< Timeline of each event
+
+      MPI_Comm interCommMerged_; //!< Communicator of the client group + server group (intraCommunicator) needed for one sided communication.
+      MPI_Comm commSelf_ ; //!< Communicator for proc alone from interCommMerged 
+      map<int,COneSidedClientBuffer*> buffers; //!< Buffers for connection to servers
+
+      bool pureOneSided ; //!< if true, client will communicated with servers only trough one sided communication. Otherwise the hybrid mode P2P /One sided is used.
+
+    private:
+      
+      //! Mapping of server and buffer size for each connection to server
+      std::map<int,StdSize> mapBufferSize_;
+      //! Maximum event sizes estimated for each connection to server
+      std::map<int,StdSize> maxEventSizes;
+      //! Maximum number of events that can be buffered
+      StdSize maxBufferedEvents;
+
+      std::map<int, MPI_Comm> winComm_ ; //! Window communicators
+      std::map<int, MPI_Win >window_ ; //! one sided mpi windows to expose client buffers to servers == windows[nbServers][2]
+
+      bool isGrowableBuffer_ = true ;
+      double growingFactor_ = 1.25 ;
+
+      double latency_=0e-2 ;
+
+      bool locked_ = false ; //!< The context client is locked to avoid recursive checkBuffer
+  };
+}
+
+#endif // __ONE_SIDED_CONTEXT_CLIENT_HPP__
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_context_server.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_context_server.cpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_context_server.cpp	(revision 2343)
@@ -0,0 +1,299 @@
+#include "one_sided_context_server.hpp"
+#include "buffer_in.hpp"
+#include "type.hpp"
+#include "context.hpp"
+#include "object_template.hpp"
+#include "group_template.hpp"
+#include "attribute_template.hpp"
+#include "domain.hpp"
+#include "field.hpp"
+#include "file.hpp"
+#include "grid.hpp"
+#include "mpi.hpp"
+#include "tracer.hpp"
+#include "timer.hpp"
+#include "cxios.hpp"
+#include "event_scheduler.hpp"
+#include "server.hpp"
+#include "servers_ressource.hpp"
+#include "pool_ressource.hpp"
+#include "services.hpp"
+#include "contexts_manager.hpp"
+#include "timeline_events.hpp"
+
+#include <boost/functional/hash.hpp>
+#include <random>
+#include <chrono>
+
+
+namespace xios
+{
+  using namespace std ;
+
+  COneSidedContextServer::COneSidedContextServer(CContext* parent,MPI_Comm intraComm_,MPI_Comm interComm_)
+                         : CContextServer(parent, intraComm_, interComm_), 
+                           isProcessingEvent_(false)
+  {
+   
+    MPI_Comm_dup(intraComm, &processEventBarrier_) ;
+ 
+    currentTimeLine=1;
+    scheduled=false;
+    finished=false;
+
+    if (!isAttachedModeEnabled()) MPI_Intercomm_merge(interComm_,true,&interCommMerged_) ;
+    MPI_Comm_split(intraComm_, intraCommRank, intraCommRank, &commSelf_) ; // for windows
+    
+    itLastTimeLine=lastTimeLine.begin() ;
+
+    pureOneSided=CXios::getin<bool>("pure_one_sided",false); // pure one sided communication (for test)
+    if (isAttachedModeEnabled()) pureOneSided=false ; // no one sided in attach mode
+      
+  }
+
+  void COneSidedContextServer::setPendingEvent(void)
+  {
+    pendingEvent=true;
+  }
+
+  bool COneSidedContextServer::hasPendingEvent(void)
+  {
+    return pendingEvent;
+  }
+
+  bool COneSidedContextServer::hasFinished(void)
+  {
+    return finished;
+  }
+
+  bool COneSidedContextServer::eventLoop(bool enableEventsProcessing /*= true*/)
+  {
+    CTimer::get("listen request").resume();
+    listen();
+    CTimer::get("listen request").suspend();
+
+    CTimer::get("listen pending request").resume();
+    listenPendingRequest() ;
+    CTimer::get("listen pending request").suspend();
+
+    CTimer::get("check server Buffers").resume();
+    checkBuffers() ;
+    CTimer::get("check server Buffers").suspend();
+
+    CTimer::get("check event process").resume();
+    processEvents(enableEventsProcessing);
+    CTimer::get("check event process").suspend();
+    return finished;
+
+  }
+
+ void COneSidedContextServer::listen(void)
+  {
+    int rank;
+    int flag;
+    MPI_Status status;
+    
+    traceOff();
+    MPI_Iprobe(MPI_ANY_SOURCE, 20,interComm, &flag, &status);
+    traceOn();
+    if (flag==true)
+    {
+      requests_.push_back(CRequest(interComm, status)) ;
+      if (requests_.back().test()) 
+      {
+        processRequest(requests_.back()) ;
+        requests_.pop_back() ;
+      }
+    }
+  }
+
+  void COneSidedContextServer::listenPendingRequest(void)
+  {
+    auto it = requests_.begin() ;
+    while (it != requests_.end())
+    {
+      if (it->test())
+      {
+        processRequest(*it) ;
+        auto it2=it ;
+        ++it ;
+        requests_.erase(it2) ;
+      }
+      else ++it ;
+    }
+  }
+
+  void COneSidedContextServer::processRequest(CRequest& request)
+  {
+    int rank = request.getRank() ;
+    auto it=buffers_.find(rank);
+    if (it==buffers_.end())
+    {
+      buffers_[rank] = new COneSidedServerBuffer(rank, commSelf_, interCommMerged_, pendingEvents_, completedEvents_, request.getBuffer()) ;
+    }
+    else it->second->receivedRequest(request.getBuffer()) ;
+  }
+
+  void COneSidedContextServer::checkBuffers(void)
+  {
+    if (!pendingEvents_.empty())
+    {
+      SPendingEvent& nextEvent = pendingEvents_.begin()->second ;
+      for(auto& buffer : nextEvent.buffers ) buffer->eventLoop() ;
+      if (nextEvent.nbSenders==0) pendingEvents_.erase(pendingEvents_.begin()) ;
+    }
+  }
+
+
+  void COneSidedContextServer::processEvents(bool enableEventsProcessing)
+  {
+  
+    if (isProcessingEvent_) return ;
+    if (isAttachedModeEnabled())
+      if (!CXios::getDaemonsManager()->isScheduledContext(remoteHashId_)) return ;
+
+    auto it=completedEvents_.find(currentTimeLine);
+
+    if (it!=completedEvents_.end())
+    {
+      if (it->second.nbSenders == it->second.currentNbSenders)
+      {
+        if (!scheduled && !isAttachedModeEnabled()) // Skip event scheduling for attached mode and reception on client side
+        {
+          eventScheduler_->registerEvent(currentTimeLine,hashId);
+          scheduled=true;
+        }
+        else if (isAttachedModeEnabled() || eventScheduler_->queryEvent(currentTimeLine,hashId) )
+        {
+          //if (!enableEventsProcessing && isCollectiveEvent(event)) return ;
+
+          if (!eventScheduled_) 
+          {
+            MPI_Ibarrier(processEventBarrier_,&processEventRequest_) ;
+            eventScheduled_=true ;
+            return ;
+          }
+          else 
+          {
+            MPI_Status status ;
+            int flag ;
+            MPI_Test(&processEventRequest_, &flag, &status) ;
+            if (!flag) return ;
+            eventScheduled_=false ;
+          }
+
+          if (!isAttachedModeEnabled()) eventScheduler_->popEvent() ;
+
+          isProcessingEvent_=true ;
+          CEventServer event(this) ;
+          for(auto& buffer : it->second.buffers) buffer->fillEventServer(currentTimeLine, event) ;
+
+          CTimer::get("Process events").resume();
+          info(100)<<"Context id "<<context->getId()<<" : Process Event "<<currentTimeLine<<" of class "<<event.classId<<" of type "<<event.type<<endl ;
+          dispatchEvent(event);
+          CTimer::get("Process events").suspend();
+          isProcessingEvent_=false ;
+//         context->unsetProcessingEvent() ;
+          pendingEvent=false;
+          completedEvents_.erase(it);
+          currentTimeLine++;
+          scheduled = false;
+          if (isAttachedModeEnabled()) CXios::getDaemonsManager()->unscheduleContext() ;
+        }
+      }
+    }
+  }
+
+  COneSidedContextServer::~COneSidedContextServer()
+  {
+    for(auto& buffer : buffers_) delete buffer.second;
+    buffers_.clear() ;
+  }
+
+  void COneSidedContextServer::releaseBuffers()
+  {
+    //for(auto it=buffers.begin();it!=buffers.end();++it) delete it->second ;
+    //buffers.clear() ; 
+    freeWindows() ;
+  }
+
+  void COneSidedContextServer::freeWindows()
+  {
+    //if (!isAttachedModeEnabled())
+    //{
+    //  for(auto& it : winComm_)
+    //  {
+    //    int rank = it.first ;
+    //    MPI_Win_free(&windows_[rank][0]);
+    //    MPI_Win_free(&windows_[rank][1]);
+    //    MPI_Comm_free(&winComm_[rank]) ;
+    //  }
+    //}
+  }
+
+  void COneSidedContextServer::notifyClientsFinalize(void)
+  {
+    for(auto it=buffers_.begin();it!=buffers_.end();++it)
+    {
+      it->second->notifyClientFinalize() ;
+    }
+  }
+
+  void COneSidedContextServer::dispatchEvent(CEventServer& event)
+  {
+    string contextName;
+    string buff;
+    int MsgSize;
+    int rank;
+    list<CEventServer::SSubEvent>::iterator it;
+    StdString ctxId = context->getId();
+    CContext::setCurrent(ctxId);
+    StdSize totalBuf = 0;
+
+    if (event.classId==CContext::GetType() && event.type==CContext::EVENT_ID_CONTEXT_FINALIZE)
+    {
+      finished=true;
+      info(20)<<" COneSidedContextServer: Receive context <"<<context->getId()<<"> finalize."<<endl;
+      notifyClientsFinalize() ;
+      CTimer::get("receiving requests").suspend();
+      context->finalize();
+      
+      std::map<int, StdSize>::const_iterator itbMap = mapBufferSize_.begin(),
+                           iteMap = mapBufferSize_.end(), itMap;
+      for (itMap = itbMap; itMap != iteMap; ++itMap)
+      {
+        rank = itMap->first;
+        report(10)<< " Memory report : Context <"<<ctxId<<"> : server side : memory used for buffer of each connection to client" << endl
+            << "  +) With client of rank " << rank << " : " << itMap->second << " bytes " << endl;
+        totalBuf += itMap->second;
+      }
+      report(0)<< " Memory report : Context <"<<ctxId<<"> : server side : total memory used for buffer "<<totalBuf<<" bytes"<<endl;
+    }
+    else if (event.classId==CContext::GetType()) CContext::dispatchEvent(event);
+    else if (event.classId==CContextGroup::GetType()) CContextGroup::dispatchEvent(event);
+    else if (event.classId==CCalendarWrapper::GetType()) CCalendarWrapper::dispatchEvent(event);
+    else if (event.classId==CDomain::GetType()) CDomain::dispatchEvent(event);
+    else if (event.classId==CDomainGroup::GetType()) CDomainGroup::dispatchEvent(event);
+    else if (event.classId==CAxis::GetType()) CAxis::dispatchEvent(event);
+    else if (event.classId==CAxisGroup::GetType()) CAxisGroup::dispatchEvent(event);
+    else if (event.classId==CScalar::GetType()) CScalar::dispatchEvent(event);
+    else if (event.classId==CScalarGroup::GetType()) CScalarGroup::dispatchEvent(event);
+    else if (event.classId==CGrid::GetType()) CGrid::dispatchEvent(event);
+    else if (event.classId==CGridGroup::GetType()) CGridGroup::dispatchEvent(event);
+    else if (event.classId==CField::GetType()) CField::dispatchEvent(event);
+    else if (event.classId==CFieldGroup::GetType()) CFieldGroup::dispatchEvent(event);
+    else if (event.classId==CFile::GetType()) CFile::dispatchEvent(event);
+    else if (event.classId==CFileGroup::GetType()) CFileGroup::dispatchEvent(event);
+    else if (event.classId==CVariable::GetType()) CVariable::dispatchEvent(event);
+    else
+    {
+      ERROR("void COneSidedContextServer::dispatchEvent(CEventServer& event)",<<" Bad event class Id"<<endl);
+    }
+  }
+
+  bool COneSidedContextServer::isCollectiveEvent(CEventServer& event)
+  {
+    if (event.type>1000) return false ;
+    else return true ;
+  }
+}
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_context_server.hpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_context_server.hpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_context_server.hpp	(revision 2343)
@@ -0,0 +1,117 @@
+#ifndef __ONE_SIDED_CONTEXT_SERVER_HPP__
+#define __ONE_SIDED_CONTEXT_SERVER_HPP__
+#include "xios_spl.hpp"
+#include "event_server.hpp"
+#include "buffer_server.hpp"
+#include "one_sided_server_buffer.hpp"
+#include "one_sided_server_base.hpp"
+#include "mpi.hpp"
+#include "event_scheduler.hpp"
+#include "context_server.hpp"
+
+namespace xios
+{
+  class CContext ;
+  class CContextClient;
+
+  class COneSidedContextServer : public CContextServer, public COneSidedServerBase
+  {
+    
+    public:
+
+      COneSidedContextServer(CContext* parent,MPI_Comm intraComm,MPI_Comm interComm) ;
+      ~COneSidedContextServer() ;
+      bool eventLoop(bool enableEventsProcessing = true);
+      void releaseBuffers(void) ;
+
+
+    private:
+
+      class CRequest
+      {
+        public : 
+          CRequest(MPI_Comm& interComm, MPI_Status& status)
+          {
+            rank_=status.MPI_SOURCE ;
+            MPI_Get_count(&status,MPI_CHAR,&count_);
+            buffer_.resize(count_) ;
+            MPI_Irecv(buffer_.data(), count_, MPI_CHAR, rank_, 20, interComm, &request_) ;
+          }
+          
+          ~CRequest() { }
+
+          bool test(void)
+          {
+            int flag ;
+            MPI_Status status ;
+            MPI_Test(&request_, &flag, &status) ;
+            if (flag==true) return true ;
+            else return false ;
+          }
+          int getCount(void) {return count_ ;}
+          int getRank(void) {return rank_ ;}
+          vector<char>& getBuffer(void) { return buffer_;}
+
+        private:
+          int rank_ ;
+          int count_ ;
+          vector<char> buffer_ ;
+          MPI_Request request_ ;
+      };
+    
+   
+    void listen(void) ;
+    void listenPendingRequest(void) ;
+    void processRequest(CRequest& request) ;
+    void checkBuffers(void) ;
+    void processEvents(bool enableEventsProcessing) ;
+    
+    bool hasFinished(void);
+    void dispatchEvent(CEventServer& event) ;
+    bool isCollectiveEvent(CEventServer& event) ;
+    void setPendingEvent(void) ;
+    bool hasPendingEvent(void) ;
+
+    void notifyClientsFinalize(void) ;
+    void freeWindows(void) ; // !<< free Windows for one sided communication
+    
+    MPI_Comm interCommMerged_; //!< Communicator of the client group + server group (intraCommunicator) needed for one sided communication.
+    MPI_Comm commSelf_ ; //!< Communicator for proc alone from interCommMerged 
+
+    map<int,COneSidedServerBuffer*> buffers_ ;
+    map<int,size_t> lastTimeLine ; //!< last event time line for a processed request
+    map<int,size_t>::iterator itLastTimeLine ; //!< iterator on lastTimeLine
+    map<int, list<std::pair<MPI_Message,MPI_Status> > > pendingProbe;
+    map<int,MPI_Request> pendingRequest ;
+    map<int,char*> bufferRequest ;
+
+    map<size_t,CEventServer*> events ;
+    size_t currentTimeLine ;
+      
+    bool finished ;
+    bool pendingEvent ;
+    bool scheduled  ;    /*!< event of current timeline is alreading scheduled ? */
+    bool pureOneSided ; //!< if true, client will communicated with servers only trough one sided communication. Otherwise the hybrid mode P2P /One sided is used.
+
+    private:
+  
+      std::map<int, StdSize> mapBufferSize_;
+      std::map<int,MPI_Comm> winComm_ ; //! Window communicators
+      std::map<int,std::vector<MPI_Win> >windows_ ; //! one sided mpi windows to expose client buffers to servers ; No memory will be attached on server side.
+      bool isProcessingEvent_ ;
+      size_t remoteHashId_; //!< the hash is of the calling context client
+      
+      MPI_Comm processEventBarrier_ ;
+      bool eventScheduled_=false;
+      MPI_Request processEventRequest_ ;
+
+      std::list<CRequest> requests_ ;
+
+      std::map<size_t, SPendingEvent> pendingEvents_   ;
+      std::map<size_t, SPendingEvent> completedEvents_ ;
+
+  } ;
+
+}
+
+#endif
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_cs_buffer_base.hpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_cs_buffer_base.hpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_cs_buffer_base.hpp	(revision 2343)
@@ -0,0 +1,30 @@
+#ifndef __ONE_SIDED_CS_BUFFER_BASE_HPP__
+#define __ONE_SIDED_CS_BUFFER_BASE_HPP__
+
+#include "xios_spl.hpp"
+#include "buffer_out.hpp"
+#include "mpi.hpp"
+#include "cxios.hpp"
+#include "event_client.hpp"
+#include <limits>
+
+namespace xios
+{
+  class COneSidedCSBufferBase 
+  {
+    protected :
+
+      const int controlSize_ = 2 ;
+      const int CONTROL_ADDR = 0 ;
+      const int CONTROL_FINALIZE = 1  ;
+
+      const size_t EVENT_BUFFER_RESIZE = std::numeric_limits<size_t>::max()-1 ;
+      const int MAX_WINDOWS=6 ;
+
+
+  } ;
+
+}
+
+
+#endif
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_server_base.hpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_server_base.hpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_server_base.hpp	(revision 2343)
@@ -0,0 +1,26 @@
+#ifndef __ONE_SIDED_SERVER_BASE_HPP__
+#define __ONE_SIDED_SERVER_BASE_HPP__
+#include "xios_spl.hpp"
+
+namespace xios
+{
+
+  class COneSidedServerBuffer ;
+  
+  class COneSidedServerBase
+  {
+    public:
+      struct SPendingEvent
+      {
+        int nbSenders ;
+        int currentNbSenders ;
+        std::list<COneSidedServerBuffer*> buffers ;
+      } ;
+  } ;
+
+}
+
+
+
+
+#endif
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_server_buffer.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_server_buffer.cpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_server_buffer.cpp	(revision 2343)
@@ -0,0 +1,387 @@
+#include "one_sided_server_buffer.hpp"
+#include "xios_spl.hpp"
+#include "mpi.hpp"
+#include "timer.hpp"
+#include "buffer_in.hpp"
+
+
+
+namespace xios
+{
+  static CLogType logProtocol("log_protocol") ;
+
+  COneSidedServerBuffer::COneSidedServerBuffer(int clientRank, const MPI_Comm& commSelf, const MPI_Comm& interCommMerged, map<size_t, SPendingEvent>& pendingEvents, 
+                                               map<size_t, SPendingEvent>& completedEvents, vector<char>& buffer) 
+                        : clientRank_(clientRank), pendingFullEvents_(pendingEvents), completedFullEvents_(completedEvents)
+  {
+    MPI_Alloc_mem(controlSize_*sizeof(MPI_Aint), MPI_INFO_NULL, &control_) ;
+    CBufferIn bufferIn(buffer.data(),buffer.size()) ;
+    bufferIn >> controlAddr_;
+    createWindow(commSelf, interCommMerged) ;
+  }
+
+  void COneSidedServerBuffer::createWindow(const MPI_Comm& commSelf, const MPI_Comm& interCommMerged)
+  {
+    CTimer::get("create Windows").resume() ;
+    MPI_Comm interComm ;
+    MPI_Intercomm_create(commSelf, 0, interCommMerged, clientRank_, 0 , &interComm) ;
+    MPI_Intercomm_merge(interComm, true, &winComm_) ;
+    CXios::getMpiGarbageCollector().registerCommunicator(winComm_) ;
+    MPI_Comm_free(&interComm) ;
+    
+    maxWindows_=MAX_WINDOWS ;
+    windows_.resize(maxWindows_) ;
+   
+    for(int i=0;i<maxWindows_;++i) 
+    {
+      MPI_Win_create_dynamic(MPI_INFO_NULL, winComm_, &windows_[i]);
+      CXios::getMpiGarbageCollector().registerWindow(windows_[i]) ;
+    }
+    MPI_Win_create_dynamic(MPI_INFO_NULL, winComm_, &winControl_);
+    CXios::getMpiGarbageCollector().registerWindow(winControl_) ;
+    CTimer::get("create Windows").suspend() ;
+    MPI_Barrier(winComm_) ;
+    MPI_Barrier(winComm_) ;
+
+  }
+
+  void COneSidedServerBuffer::receivedRequest(vector<char>& buffer)
+  {
+    size_t timeline ;
+    int nbSenders ;
+    CBufferIn bufferIn(buffer.data(),buffer.size()) ;
+    bufferIn >> timeline ;
+    if (timeline==EVENT_BUFFER_RESIZE)
+    {
+      size_t AssociatedTimeline ;
+      size_t newSize ;
+      bufferIn >>AssociatedTimeline>>newSize ;
+      bufferResize_.push_back({AssociatedTimeline,newSize}) ;
+    }
+    else // receive standard event
+    {
+
+      bufferIn>> nbSenders ;
+      nbSenders_[timeline] = nbSenders ;
+      auto pendingFullEvent=pendingFullEvents_.find(timeline) ;
+      if (pendingFullEvent==pendingFullEvents_.end()) 
+      {
+        SPendingEvent pendingEvent = {nbSenders,1,{this}} ;
+        pendingFullEvents_[timeline]=pendingEvent ;
+      }
+      else 
+      {  
+        pendingFullEvent->second.currentNbSenders++ ;
+        pendingFullEvent->second.buffers.push_back(this) ;
+      }
+    
+      int nbBlocs ; 
+      int count ;
+      int window ;
+      bufferIn >> nbBlocs ;
+      MPI_Aint bloc ;
+      auto& blocs = pendingBlocs_[timeline] ;
+      for(int i=0;i<nbBlocs;++i) 
+      {
+        bufferIn >> bloc >> count >> window;
+        blocs.push_back({bloc, count, window}) ;
+      }
+    }
+  }
+
+  void COneSidedServerBuffer::eventLoop(void)
+  {
+    int flag ;
+    if (!pendingRmaRequests_.empty()) testPendingRequests() ;
+    if (pendingRmaRequests_.empty()) transferEvents() ;
+
+    if (!isLocked_)
+    {
+      if (lastBlocToFree_!=0)
+      {
+        info(logProtocol)<<"Send bloc to free : "<<lastBlocToFree_<<endl ;
+        MPI_Win_lock(MPI_LOCK_EXCLUSIVE, windowRank_, 0, winControl_) ;
+        MPI_Aint target=MPI_Aint_add(controlAddr_, CONTROL_ADDR*sizeof(MPI_Aint)) ;
+        MPI_Put(&lastBlocToFree_, 1, MPI_AINT, windowRank_, target, 1, MPI_AINT, winControl_) ;
+        MPI_Win_unlock(windowRank_,winControl_) ; 
+        lastBlocToFree_ = 0 ;        
+      }
+    }
+
+    if (buffers_.size()>1) 
+     if (buffers_.front()->getCount()==0) buffers_.pop_front() ; // if buffer is empty free buffer
+  }
+
+  void COneSidedServerBuffer::notifyClientFinalize(void)
+  {
+    eventLoop() ; // to free the last bloc
+    MPI_Aint finalize=1 ;
+    MPI_Win_lock(MPI_LOCK_EXCLUSIVE, windowRank_, 0, winControl_) ;
+    MPI_Aint target=MPI_Aint_add(controlAddr_, CONTROL_FINALIZE*sizeof(MPI_Aint)) ;
+    MPI_Put(&finalize, 1, MPI_AINT, windowRank_, target, 1, MPI_AINT, winControl_) ;
+    MPI_Win_unlock(windowRank_,winControl_) ; 
+  }
+  void COneSidedServerBuffer::testPendingRequests(void)
+  {
+    if (!pendingRmaRequests_.empty())
+    {
+      int flag ;
+      MPI_Testall(pendingRmaRequests_.size(), pendingRmaRequests_.data(), &flag, pendingRmaStatus_.data()) ;
+      if (flag==true) 
+      {
+        if (!isLocked_) ERROR("void COneSidedServerBuffer::testPendingRequests(void)",<<"windows is not Locked");
+        for(auto& win : windowsLocked_) 
+        {
+          info(logProtocol)<<"unlock window "<<win<<endl ;
+          MPI_Win_unlock(windowRank_,windows_[win]) ; 
+        }
+        windowsLocked_.clear() ;
+          
+        isLocked_=false ;
+        pendingRmaRequests_.clear() ;
+        pendingRmaStatus_.clear() ;
+        completedEvents_.insert(onTransferEvents_.begin(),onTransferEvents_.end()) ;
+        
+        for(auto & event : onTransferEvents_) 
+        {
+          size_t timeline = event.first ;
+
+          auto pendingFullEvent=pendingFullEvents_.find(timeline) ;
+          pendingFullEvent->second.nbSenders-- ;
+          pendingFullEvent->second.currentNbSenders-- ;
+          
+
+          auto completedFullEvent=completedFullEvents_.find(timeline) ;
+          if (completedFullEvent==completedFullEvents_.end()) 
+          {
+            SPendingEvent pendingEvent = {nbSenders_[timeline],1,{this}} ;
+            completedFullEvents_[timeline]=pendingEvent ;
+          }
+          else 
+          {
+            completedFullEvent->second.currentNbSenders++ ;
+            completedFullEvent->second.buffers.push_back(this) ;
+          }
+          nbSenders_.erase(timeline) ;
+        }  
+        onTransferEvents_.clear() ;
+      }
+    }
+
+  }
+  
+  size_t COneSidedServerBuffer::remainSize(void)
+  {
+    if (!fixed_) return std::numeric_limits<size_t>::max() ;
+    else
+    {
+      if (currentBuffer_ == nullptr) return fixedSize_ ;
+      else return currentBuffer_->remain() ;
+    }
+  }
+
+  void COneSidedServerBuffer::transferEvents(void)
+  {
+    if (pendingRmaRequests_.empty() && !pendingBlocs_.empty())
+    {
+      size_t remain=remainSize() ;
+      size_t transferedSize=0 ;
+
+      size_t timeline =  pendingBlocs_.begin()->first ;
+      auto& blocs = pendingBlocs_.begin()->second ;
+      
+      if (!bufferResize_.empty()) 
+      {
+        if (bufferResize_.front().first==timeline)
+        {
+          currentBufferSize_=bufferResize_.front().second ;
+          info(logProtocol)<<"Received new buffer size="<<currentBufferSize_<<"  at timeline="<<timeline<<endl ;
+          bufferResize_.pop_front() ;
+          newBuffer(currentBufferSize_,fixed_) ;
+        }
+      }
+
+      size_t eventSize=0 ;
+      for(auto& bloc : blocs) eventSize+=get<1>(bloc) ;
+      
+      if (eventSize > remain) 
+      {
+        if ( eventSize <= currentBufferSize_) return ; // wait for free storage ;
+        else 
+        {
+          if (currentBuffer_==nullptr) remain = eventSize ;
+          else remain = currentBuffer_->remain() + fixedSize_ ;
+        }
+      }
+      
+      if (isLocked_) ERROR("void COneSidedServerBuffer::transferEvents(void)",<<"windows is Locked");
+      for(auto& bloc : blocs) 
+      {
+        int win=get<2>(bloc) ;
+        if (windowsLocked_.count(win)==0) 
+        {
+          MPI_Win_lock(MPI_LOCK_SHARED, windowRank_, 0, windows_[win]) ;
+          windowsLocked_.insert(win) ;
+        }
+      }
+      isLocked_=true ;
+      do
+      {
+        transferEvent() ; // ok enough storage for this bloc
+        
+        transferedSize += eventSize ;
+        pendingBlocs_.erase(pendingBlocs_.begin()) ;
+        
+//        break ; // transfering just one event temporary => to remove
+        
+        if (pendingBlocs_.empty()) break ; // no more blocs to tranfer => exit loop
+
+        timeline =  pendingBlocs_.begin()->first ;
+        auto& blocs=pendingBlocs_.begin()->second ;
+        
+        if (!bufferResize_.empty()) 
+        {
+          if (bufferResize_.front().first==timeline)
+          {
+            currentBufferSize_=bufferResize_.front().second ;
+            info(logProtocol)<<"Received new buffer size="<<currentBufferSize_<<"  at timeline="<<timeline<<endl ;
+            bufferResize_.pop_front() ;
+            newBuffer(currentBufferSize_,fixed_) ;
+          }
+        }
+
+        for(auto& bloc : blocs) eventSize+=get<1>(bloc) ;
+        if (transferedSize+eventSize<=remain)
+        {
+          for(auto& bloc : blocs) 
+          {
+            int win=get<2>(bloc) ;
+            if (windowsLocked_.count(win)==0) 
+            {
+              MPI_Win_lock(MPI_LOCK_SHARED, windowRank_, 0, windows_[win]) ;
+              windowsLocked_.insert(win) ;
+            }
+          }
+        }
+      }
+      while(transferedSize+eventSize<=remain) ;
+      
+    }
+  }
+  
+  void COneSidedServerBuffer::transferEvent(void)
+  {
+    MPI_Aint addr;
+    MPI_Aint offset ;
+
+    size_t size;
+    size_t start;
+    size_t count;
+    int window ;
+
+    auto& blocs=pendingBlocs_.begin()->second ;
+    size_t timeline = pendingBlocs_.begin() -> first ;
+  
+
+    for(auto& bloc : blocs)
+    {
+      addr = std::get<0>(bloc) ;
+      size = std::get<1>(bloc) ;
+      window = std::get<2>(bloc) ;
+
+      offset=0 ;
+
+      do
+      {
+        if (currentBuffer_!=nullptr)
+        {
+          currentBuffer_->reserve(size, start, count) ;
+      
+          if ( count > 0)
+          {
+            transferRmaRequest(timeline, addr, offset, currentBuffer_, start, count, window) ;
+            offset=MPI_Aint_add(offset, count) ;
+          }
+          currentBuffer_->reserve(size, start, count) ;
+      
+          if ( count > 0)
+          {
+            transferRmaRequest(timeline, addr, offset, currentBuffer_, start, count, window) ;
+            offset=MPI_Aint_add(offset, count) ;
+          }
+        }
+
+        if (size>0) 
+        {
+          if (fixed_) newBuffer(fixedSize_,fixed_) ;
+          else
+          {
+            currentBufferSize_ = std::max((size_t)(currentBufferSize_*growingFactor_), size) ;
+            newBuffer(currentBufferSize_,fixed_) ;
+          }
+        }
+      } while (size > 0 ) ;
+    }
+
+    pendingRmaStatus_.resize(pendingRmaRequests_.size()) ;
+  }
+
+  void COneSidedServerBuffer::transferRmaRequest(size_t timeline, MPI_Aint addr, MPI_Aint offset, CBuffer* buffer, size_t start, int count, int window)
+  {
+    MPI_Request request ;
+    MPI_Aint offsetAddr=MPI_Aint_add(addr, offset) ;
+    info(logProtocol)<<"receive Bloc from client "<<clientRank_<<" : timeline="<<timeline<<"  addr="<<addr<<"  count="<<count<<" buffer="<<buffer<<"  start="<<start<<endl ;
+    info(logProtocol)<<"check dest buffers ; start_buffer="<<static_cast<void*>(buffer->getBuffer())<<"  end_buffer="<<static_cast<void*>(buffer->getBuffer()+buffer->getSize()-1)
+             <<"  start="<<static_cast<void*>(buffer->getBuffer()+start)<<"   end="<<static_cast<void*>(buffer->getBuffer()+start+count-1)<<endl ;
+    MPI_Rget(buffer->getBuffer()+start, count, MPI_CHAR, windowRank_, offsetAddr, count, MPI_CHAR, windows_[window], &request) ;
+    pendingRmaRequests_.push_back(request) ;
+    onTransferEvents_[timeline].push_back({buffer,start,count,addr}) ;
+  }
+
+  void COneSidedServerBuffer::fillEventServer(size_t timeline, CEventServer& event)
+  {
+    auto &completedEvent=completedEvents_[timeline] ;
+    size_t size=0 ;
+    for(auto& bloc : completedEvent) size+=bloc.count ;
+    char* buffer = new char[size] ;
+    size=0 ;
+    
+    ostringstream outStr ;
+    outStr<<"Received Event from client "<<clientRank_<<"  timeline="<<timeline<<"  nbBlocs="<<completedEvent.size()<<endl ;
+    int i=0 ;
+    MPI_Aint addr ;
+    for(auto& bloc : completedEvent) 
+    {
+      memcpy(&buffer[size], bloc.buffer->getBuffer()+bloc.start, bloc.count) ;
+      
+      if (info.isActive(logProtocol))
+      {
+        size_t checksum=0 ;
+        for(size_t j=0;j<bloc.count;j++) checksum += (unsigned char) buffer[size+j] ;
+        outStr<<"bloc "<<i<<"  count="<<bloc.count<<" checksum="<<checksum<<"  ;  " ;
+        i++ ;
+      }
+
+      size+=bloc.count ;
+      bloc.buffer->free(bloc.start, bloc.count) ; // free bloc
+      addr=bloc.addr ;
+      if (bloc.buffer->getCount()==0) if (buffers_.size() > 1) buffers_.pop_front() ; // if buffer is empty free buffer
+    }
+    event.push(clientRank_, nullptr, buffer, size) ;
+    if (info.isActive(logProtocol)) outStr<<" ==> nbSenders="<<event.getNbSender() ;
+    info(logProtocol)<<outStr.str()<<endl ;
+    
+    lastBlocToFree_=addr ;
+    /*
+    if (!isLocked_) MPI_Win_lock(MPI_LOCK_SHARED, windowRank_, 0, window_) ;
+    MPI_Aint target=MPI_Aint_add(controlAddr_, CONTROL_ADDR) ;
+    MPI_Put(&addr, 1, MPI_AINT, windowRank_, target, 1, MPI_AINT, window_) ;
+    if (!isLocked_) MPI_Win_unlock(windowRank_,window_) ;
+   */
+    completedEvents_.erase(timeline) ;
+    eventLoop() ;
+  }
+
+  
+
+}
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_server_buffer.hpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_server_buffer.hpp	(revision 2343)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/transport/one_sided_server_buffer.hpp	(revision 2343)
@@ -0,0 +1,170 @@
+#ifndef __ONE_SIDED_SERVER_BUFFER_HPP__
+#define __ONE_SIDED_SERVER_BUFFER_HPP__
+
+#include "xios_spl.hpp"
+#include "buffer_out.hpp"
+#include "mpi.hpp"
+#include "cxios.hpp"
+#include "event_server.hpp"
+#include "one_sided_cs_buffer_base.hpp"
+#include "one_sided_server_base.hpp"
+
+namespace xios
+{
+  extern CLogType logProtocol ;
+
+  class COneSidedServerBuffer : public COneSidedCSBufferBase, public COneSidedServerBase
+  {
+    private :
+
+      class CBuffer
+      {
+        char* buffer_ ;
+        size_t start_ ;
+        size_t end_ ;
+        size_t count_ ;
+        size_t size_ ;
+        bool fixed_ ;
+
+        public:
+          CBuffer(size_t size, bool fixed) : start_(size), end_(0), count_(0), size_(size), fixed_(fixed) 
+          { 
+            MPI_Alloc_mem(size, MPI_INFO_NULL, &buffer_) ;
+            info(logProtocol)<<"New buffer of size="<<size<<endl ;
+          }
+          ~CBuffer() 
+          { 
+            if (count_>0) ERROR("COneSidedServerBuffer::~CBuffer()",<<"Try to delete buffer that is not empty"<<std::endl) ;
+            MPI_Free_mem(&buffer_) ;
+          }
+       
+          void reserve(size_t& size, size_t& start, size_t& count)
+          {
+            count = 0 ;
+            if (end_ < start_)
+            {
+              if (start_-end_ >= size)
+              {
+                count=size ;
+                size = 0 ;
+                start=end_ ;
+                end_  += count ; 
+                count_+= count ;
+              } 
+              else
+              {
+                count = start_-end_ ;
+                size -= count ;
+                start=end_ ;
+                end_ = start_ ;
+                count_+=count ;
+              }
+            }
+            else if ( end_> start_ )
+            {
+              if (size_-end_ >= size)
+              {
+                count = size ;
+                size = 0;
+                start=end_ ;
+                end_   += count ;
+                count_ += count ;
+              }
+              else
+              {
+                count = size_ - end_ ;
+                size -= count ;
+                start=end_ ;
+                end_ = 0 ;
+                count_+= count ;
+              }
+            }
+            else if (end_==start_)
+            {
+              count = 0 ;
+            }
+          }
+
+          void free(size_t start, size_t count)
+          {
+            start_ = start+count-1 ;
+            count_ -= count ;
+          }
+
+          size_t remain(void) { return size_-count_; }
+          size_t getSize(void) { return size_ ;}
+          size_t getCount(void) {return count_ ;}
+          size_t isFixed(void) {return fixed_;}
+          char* getBuffer(void) {return buffer_ ;}
+      } ;
+     
+    public:
+    
+      COneSidedServerBuffer(int clientRank, const MPI_Comm& commSelf, const MPI_Comm& interCommMerged, map<size_t, SPendingEvent>& pendingEvents, 
+                             map<size_t, SPendingEvent>& completedEvents, vector<char>& buffer)  ;
+      
+      void receivedRequest(vector<char>& buffer) ;
+      void eventLoop(void) ;
+      void fillEventServer(size_t timeline, CEventServer& event) ;
+      void notifyClientFinalize(void);
+
+    private:
+      struct SBloc
+      {
+        CBuffer* buffer ;
+        size_t start ;
+        int count ;
+        MPI_Aint addr ;
+      } ;
+
+      void createWindow(const MPI_Comm& commSelf, const MPI_Comm& interCommMerged) ;
+      void newBuffer(size_t size, bool fixed) { buffers_.push_back(new CBuffer(size, fixed)); currentBuffer_=buffers_.back() ;}
+      void testPendingRequests(void) ;
+      void transferEvents(void) ;
+      void transferEvent(void) ;
+      void transferRmaRequest(size_t timeline, MPI_Aint addr, MPI_Aint offset, CBuffer* buffer, size_t start, int count, int window) ;
+      size_t remainSize(void) ;
+
+
+
+      bool fixed_=false;
+      size_t fixedSize_ = 0 ;
+      size_t currentBufferSize_=0 ;
+      double growingFactor_ = 2. ;
+      
+      std::list<CBuffer*> buffers_ ;
+      CBuffer* currentBuffer_=nullptr ;
+
+      map<size_t, SPendingEvent>& pendingFullEvents_ ;
+      map<size_t, SPendingEvent>& completedFullEvents_ ;
+
+      map<size_t, int> nbSenders_ ;
+      map<size_t, list<tuple<MPI_Aint,int,int>>> pendingBlocs_;
+     
+      vector<MPI_Request> pendingRmaRequests_ ;
+      vector<MPI_Status> pendingRmaStatus_ ;
+
+      map<size_t, list<SBloc>> onTransferEvents_ ; // map<size_t timeline, list<pair<char* bloc, int count>>>
+      map<size_t, list<SBloc>> completedEvents_ ; // map<size_t timeline, list<pair<char* bloc, int count>>>
+      list<std::pair<size_t,size_t>> bufferResize_ ; // list<size_t AssociatedTimeline, size_t newSize> 
+
+      int clientRank_ ;
+      MPI_Aint * control_ ;
+      MPI_Aint controlAddr_ ;
+
+      MPI_Comm winComm_ ;
+      vector<MPI_Win> windows_ ;
+      int maxWindows_ ;
+      set<int> windowsLocked_ ;
+
+      MPI_Win winControl_ ;
+      bool isLocked_=false ;
+      const int windowRank_=0 ;
+      MPI_Aint lastBlocToFree_=0 ;
+
+  } ;
+
+}
+
+
+#endif
