Index: XIOS3/trunk/src/transport/context_client.cpp
===================================================================
--- XIOS3/trunk/src/transport/context_client.cpp	(revision 2555)
+++ XIOS3/trunk/src/transport/context_client.cpp	(revision 2556)
@@ -17,4 +17,5 @@
 #include <chrono>
 #include "one_sided_context_client.hpp"
+#include "p2p_context_client.hpp"
 #include "legacy_context_client.hpp"
 #include "online_context_client.hpp"
@@ -59,4 +60,5 @@
       string defaultProtocol = CXios::getin<string>("transport_protocol", "default") ;
       if (defaultProtocol=="one_sided") return getNew<CContextClient::oneSided>(parent, intraComm, interComm) ;
+      else if  (defaultProtocol=="p2p") return getNew<CContextClient::p2p>(parent, intraComm, interComm) ;
       else if  (defaultProtocol=="legacy") return getNew<CContextClient::legacy>(parent, intraComm, interComm) ;
       else if  (defaultProtocol=="online") return getNew<CContextClient::online>(parent, intraComm, interComm) ;
@@ -70,4 +72,10 @@
     { 
       return new COneSidedContextClient(parent, intraComm, interComm, parentServer); 
+    }
+
+    template<>
+    CContextClient* CContextClient::getNew<CContextClient::p2p>(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer)
+    { 
+      return new CP2pContextClient(parent, intraComm, interComm, parentServer); 
     }
 
Index: XIOS3/trunk/src/transport/context_client.hpp
===================================================================
--- XIOS3/trunk/src/transport/context_client.hpp	(revision 2555)
+++ XIOS3/trunk/src/transport/context_client.hpp	(revision 2556)
@@ -28,5 +28,5 @@
   {
     public:
-      enum ETransport { generic, legacy, oneSided, online}  ;
+      enum ETransport { generic, legacy, oneSided, p2p, online}  ;
       
       template<ETransport transport=generic> 
@@ -102,4 +102,7 @@
 
   template<>
+  CContextClient* CContextClient::getNew<CContextClient::p2p>(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) ;
 
Index: XIOS3/trunk/src/transport/context_server.cpp
===================================================================
--- XIOS3/trunk/src/transport/context_server.cpp	(revision 2555)
+++ XIOS3/trunk/src/transport/context_server.cpp	(revision 2556)
@@ -22,4 +22,5 @@
 #include "timeline_events.hpp"
 #include "one_sided_context_server.hpp"
+#include "p2p_context_server.hpp"
 #include "legacy_context_server.hpp"
 
@@ -67,4 +68,5 @@
     string defaultProtocol = CXios::getin<string>("transport_protocol", "default") ;
     if (defaultProtocol=="one_sided") return new COneSidedContextServer(parent, intraComm, interComm) ;
+    else if  (defaultProtocol=="p2p") return new CP2pContextServer(parent, intraComm, interComm) ;
     else if  (defaultProtocol=="legacy") return new CLegacyContextServer(parent, intraComm, interComm) ;
     else if  (defaultProtocol=="default") return new CLegacyContextServer(parent, intraComm, interComm) ;
@@ -80,4 +82,10 @@
 
   template<>
+  CContextServer* CContextServer::getNew<CContextServer::p2p>(CContext* parent,MPI_Comm intraComm,MPI_Comm interComm) 
+  { 
+    return new CP2pContextServer(parent, intraComm, interComm) ; 
+  }
+
+  template<>
   CContextServer* CContextServer::getNew<CContextServer::legacy>(CContext* parent,MPI_Comm intraComm,MPI_Comm interComm) 
   { 
Index: XIOS3/trunk/src/transport/context_server.hpp
===================================================================
--- XIOS3/trunk/src/transport/context_server.hpp	(revision 2555)
+++ XIOS3/trunk/src/transport/context_server.hpp	(revision 2556)
@@ -16,5 +16,5 @@
     public:
     
-    enum ETransport { generic, legacy, oneSided}  ;
+    enum ETransport { generic, legacy, p2p, oneSided}  ;
       
     template<ETransport transport=generic> 
@@ -55,4 +55,7 @@
 
   template<>
+  CContextServer* CContextServer::getNew<CContextServer::p2p>(CContext* parent,MPI_Comm intraComm,MPI_Comm interComm) ;
+
+  template<>
   CContextServer* CContextServer::getNew<CContextServer::legacy>(CContext* parent,MPI_Comm intraComm,MPI_Comm interComm) ;
 
Index: XIOS3/trunk/src/transport/p2p_client_buffer.cpp
===================================================================
--- XIOS3/trunk/src/transport/p2p_client_buffer.cpp	(revision 2556)
+++ XIOS3/trunk/src/transport/p2p_client_buffer.cpp	(revision 2556)
@@ -0,0 +1,315 @@
+#include "p2p_client_buffer.hpp"
+#include "event_client.hpp"
+#include "timer.hpp"
+
+namespace xios
+{
+  
+  extern CLogType logProtocol;
+
+  CP2pClientBuffer::CP2pClientBuffer(MPI_Comm& interComm, int serverRank, MPI_Comm& commSelf, MPI_Comm& interCommMerged, int intraServerRank) : interComm_(interComm), serverRank_(serverRank), interCommMerged_(interCommMerged), intraServerRank_(intraServerRank)
+  {
+    
+    //MPI_Alloc_mem(controlSize_*sizeof(MPI_Aint), MPI_INFO_NULL, &control_) ;
+    //control_[CONTROL_ADDR] = 0 ;
+    //control_[CONTROL_FINALIZE] = 0 ;
+    //sendNewBuffer() ;
+    createWindow(commSelf, interCommMerged, intraServerRank ) ;
+    char dummy ;
+    MPI_Irecv(&dummy, 0, MPI_CHAR, intraServerRank, 22, interCommMerged, &finalizeRequest_) ;
+  }
+
+  void CP2pClientBuffer::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_) ;
+
+    //MPI_Barrier(winComm_) ;
+    //MPI_Win_attach(winControl_, control_, controlSize_*sizeof(MPI_Aint)) ;
+    //MPI_Barrier(winComm_) ;
+    CTimer::get("create Windows").suspend() ;
+ 
+ //   MPI_Win_lock(MPI_LOCK_EXCLUSIVE, 0, 0, winControl_) ;
+ //   MPI_Win_unlock(0,winControl_) ;
+
+  } 
+
+
+
+  void CP2pClientBuffer::newBuffer(size_t size, bool fixed)
+  { 
+    currentWindow_=(currentWindow_+1)%maxWindows_ ;
+    if (usedWindows_[currentWindow_]) 
+    {
+      ERROR("void CP2pClientBuffer::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 CP2pClientBuffer::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 CP2pClientBuffer::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, static_cast<int>(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, static_cast<int>(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 CP2pClientBuffer::freeBuffer(MPI_Aint addr)
+  {
+    if (addr != 0)
+    {
+      while(freeBloc(addr)) ;
+    }
+    
+    if (isFinalized_ && !buffers_.empty() && buffers_.front()->getCount()==0) 
+    {
+      delete buffers_.front() ;
+      buffers_.pop_front() ;
+    }
+  }
+  
+  bool CP2pClientBuffer::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 CP2pClientBuffer::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 CP2pClientBuffer::eventLoop(void)
+  {
+    // check to free requests
+    int flag ;
+    bool out = true;
+    SRequest request ; 
+    while (!requests_.empty() && out) 
+    {
+      request = requests_.front() ;
+      if (info.isActive(logProtocol)) CTimer::get("sendTimelineEvent : MPI_Test").resume() ;
+      MPI_Test(&request.mpiRequest, &flag, MPI_STATUS_IGNORE) ;
+      if (info.isActive(logProtocol)) CTimer::get("sendTimelineEvent : MPI_Test").suspend() ;
+      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_) ;
+    MPI_Aint addr=0 ;
+    auto it=sentBlocRequest_.begin() ;
+    for( ; it!=sentBlocRequest_.end() ; ++it)
+    {
+      int flag=true ;
+      MPI_Status status ; 
+      MPI_Test(&it->mpiRequest, &flag, &status) ;
+      if (flag==false) 
+      {
+        ++it ;
+        break ;
+      }
+      else addr = it->addr;
+    }
+    if (addr!=0) sentBlocRequest_.erase(sentBlocRequest_.begin(), it) ;
+    freeBuffer(addr) ;
+
+    // if (finalize==1) isFinalized_=true ;
+    listenFinalize() ;
+  }
+
+  void CP2pClientBuffer::listenFinalize(void)
+  {
+    if (!isFinalized_)
+    {
+      int flag ;
+      MPI_Status status ;
+      MPI_Test(&finalizeRequest_,&flag, &status) ;
+      if (flag) isFinalized_=true;
+    }
+  }
+
+  void CP2pClientBuffer::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<<"  ;  " ;
+      }
+
+      sentBlocRequest_.emplace_back() ;
+      sentBlocRequest_.back().addr = it->addr ; 
+      MPI_Issend((void*)(it->addr), it->count, MPI_CHAR, intraServerRank_, 21, interCommMerged_, &sentBlocRequest_.back().mpiRequest) ;
+    }
+    if (info.isActive(logProtocol)) CTimer::get("sendTimelineEvent : MPI_Isend").resume() ;
+    MPI_Isend(request.buffer->start(),request.buffer->count(), MPI_CHAR, intraServerRank_, 20, interCommMerged_, &request.mpiRequest ) ;
+    if (info.isActive(logProtocol)) CTimer::get("sendTimelineEvent : MPI_Isend").suspend() ;
+    info(logProtocol)<<outStr.str()<<endl ;
+    requests_.push_back(request) ;
+  }
+
+  void CP2pClientBuffer::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, intraServerRank_, 20, interCommMerged_, &request.mpiRequest ) ;
+    requests_.push_back(request) ;
+  }
+
+  void CP2pClientBuffer::sendNewBuffer(void)
+  {
+//    MPI_Aint controlAddr ;
+//    MPI_Get_address(control_, &controlAddr) ;
+//    MPI_Send(&controlAddr, 1, MPI_AINT, intraServerRank_, 20, interCommMerged_) ;
+  }
+
+}
Index: XIOS3/trunk/src/transport/p2p_client_buffer.hpp
===================================================================
--- XIOS3/trunk/src/transport/p2p_client_buffer.hpp	(revision 2556)
+++ XIOS3/trunk/src/transport/p2p_client_buffer.hpp	(revision 2556)
@@ -0,0 +1,216 @@
+#ifndef __P2P_CLIENT_BUFFER_HPP__
+#define __P2P_CLIENT_BUFFER_HPP__
+
+#include "xios_spl.hpp"
+#include "buffer_out.hpp"
+#include "mpi.hpp"
+#include "cxios.hpp"
+#include "event_client.hpp"
+#include "p2p_cs_buffer_base.hpp"
+
+namespace xios
+{
+  extern CLogType logProtocol ;
+
+  class CP2pClientBuffer : public CP2pCSBufferBase
+  {
+    class CBuffer
+    {
+      char* buffer_ ;
+      size_t start_ ;
+      size_t end_ ;
+      size_t count_ ;
+      size_t size_ ;
+      bool fixed_ ;
+      char* window_ ;
+
+      public:
+        CBuffer(char* 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("CP2pClientBuffer::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:
+      CP2pClientBuffer(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 ) ;
+      void listenFinalize(void) ;
+
+    private :
+      
+      struct SBloc
+      {
+        MPI_Aint addr ;
+        CBuffer* buffer ;
+        size_t start ;
+        int    count ;
+        int    window ;
+      } ;
+
+      struct SRequest
+      {
+        CBufferOut* buffer ;
+        MPI_Request mpiRequest ;
+      } ;
+
+      struct SBlocRequest
+      {
+        MPI_Aint addr ;
+        MPI_Request mpiRequest ;
+      } ;
+      
+      MPI_Aint* control_ ;
+
+      MPI_Comm interComm_; 
+      MPI_Comm winComm_ ;
+
+      //MPI_Win window_ ;
+      //vector<MPI_Win> windows_ ;
+      vector<char*> windows_ ;
+      vector<bool> usedWindows_ ;
+      int currentWindow_ ;
+      int maxWindows_ ;
+
+      //MPI_Win winControl_ ;
+      int serverRank_ ;
+
+      MPI_Comm interCommMerged_;  
+      int intraServerRank_ ; 
+
+      std::list<CBuffer*> buffers_ ;
+      std::list<SBloc> blocs_ ;
+      std::list<SBloc>::iterator lastBlocEvent_ ;
+      CBuffer* currentBuffer_=nullptr ;
+      std::list<SRequest> requests_ ;
+
+      std::list<SBlocRequest> sentBlocRequest_ ;
+      MPI_Request finalizeRequest_ ;
+
+      bool fixed_=false;
+      size_t fixedSize_ = 0 ;
+      size_t currentBufferSize_= 0  ;
+      double growingFactor_ = 2. ; 
+      MPI_Aint lastFreedBloc_=0 ;
+      bool isFinalized_ = false ;
+
+  } ;
+
+}
+
+
+#endif
Index: XIOS3/trunk/src/transport/p2p_context_client.cpp
===================================================================
--- XIOS3/trunk/src/transport/p2p_context_client.cpp	(revision 2556)
+++ XIOS3/trunk/src/transport/p2p_context_client.cpp	(revision 2556)
@@ -0,0 +1,291 @@
+#include "xios_spl.hpp"
+#include "p2p_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 --> obsolete ).
+    */
+    CP2pContextClient::CP2pContextClient(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)
+
+      MPI_Intercomm_merge(interComm_,false, &interCommMerged_) ;
+      
+      MPI_Comm_split(intraComm_,clientRank,clientRank, &commSelf_) ; // for windows
+      eventScheduler_ = parent->getEventScheduler() ;  
+      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 CP2pContextClient::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() ;
+        double time=CTimer::getTime() ;
+        bool succed = itBuffer->second->writeEvent(timeLine, event)  ;
+        if (succed) 
+        {
+          time=CTimer::getTime()-time ;
+          if (!CTimer::get("Blocking time").isSuspended()) CTimer::get("Blocking time").minus(time) ;
+        }
+
+        if (succed) event.remove() ;
+        else event.next() ;
+        if (event.isFirst())
+        {
+          if (CTimer::get("Blocking time").isSuspended()) CTimer::get("Blocking time").resume() ;
+          yield() ;
+        } 
+      }
+      if (!CTimer::get("Blocking time").isSuspended()) CTimer::get("Blocking time").suspend() ;
+
+
+      synchronize() ;
+      
+      timeLine++;
+    }
+
+
+   void CP2pContextClient::eventLoop(void)
+   {
+      if (!locked_) checkBuffers() ;
+   }
+
+   void CP2pContextClient::callGlobalEventLoop(void)
+   {
+     locked_=true ;
+     context_->globalEventLoop() ;
+     locked_=false ;
+   }
+
+   void CP2pContextClient::yield(void)
+   {
+     locked_=true ;
+     context_->yield() ;
+     locked_=false ;
+   }
+
+   void CP2pContextClient::synchronize(void)
+   {
+     if (context_->getServiceType()!=CServicesManager::CLIENT)
+     {
+       locked_=true ;
+       context_->synchronize() ;
+       locked_=false ;
+     }    
+   }
+
+   /*!
+   Make a new buffer for a certain connection to server with specific rank
+   \param [in] rank rank of connected server
+   */
+   void CP2pContextClient::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;
+      }
+
+      CP2pClientBuffer* buffer = buffers[rank] = new CP2pClientBuffer(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 CP2pContextClient::checkBuffers(void)
+   {
+      bool pending = false;
+      for (auto itBuff : buffers)
+      {
+        itBuff.second->eventLoop() ;
+        pending |= !(itBuff.second->isEmpty());
+      }
+      return pending;
+   }
+
+   //! Release all buffers
+   void CP2pContextClient::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 CP2pContextClient::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 CP2pContextClient::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 CP2pContextClient::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 CP2pContextClient::havePendingRequests(void)
+  {
+    return checkBuffers();
+  }
+  
+  bool CP2pContextClient::havePendingRequests(list<int>& ranks)
+  {
+    return checkBuffers(ranks) ;
+  }
+
+  bool CP2pContextClient::isNotifiedFinalized(void)
+  {
+
+    bool finalized = true;
+    for (auto& it : buffers ) finalized &= it.second->isNotifiedFinalized();
+    return finalized;
+  }
+
+}
Index: XIOS3/trunk/src/transport/p2p_context_client.hpp
===================================================================
--- XIOS3/trunk/src/transport/p2p_context_client.hpp	(revision 2556)
+++ XIOS3/trunk/src/transport/p2p_context_client.hpp	(revision 2556)
@@ -0,0 +1,89 @@
+#ifndef __P2P_CONTEXT_CLIENT_HPP__
+#define __P2P_CONTEXT_CLIENT_HPP__
+
+#include "xios_spl.hpp"
+#include "buffer_out.hpp"
+#include "buffer_in.hpp"
+#include "p2p_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 CP2pContextClient : public CContextClient
+  {
+    public:
+      // Contructor
+      CP2pContextClient(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer = 0);
+
+      ETransport getType(void) {return oneSided ;}
+      // 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() ;
+      void yield() ;
+      void synchronize() ;
+      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,CP2pClientBuffer*> 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
+      shared_ptr<CEventScheduler> eventScheduler_ ;
+  };
+}
+
+#endif // __ONE_SIDED_CONTEXT_CLIENT_HPP__
Index: XIOS3/trunk/src/transport/p2p_context_server.cpp
===================================================================
--- XIOS3/trunk/src/transport/p2p_context_server.cpp	(revision 2556)
+++ XIOS3/trunk/src/transport/p2p_context_server.cpp	(revision 2556)
@@ -0,0 +1,311 @@
+#include "p2p_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 ;
+
+  CP2pContextServer::CP2pContextServer(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;
+
+    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)
+      
+  }
+
+  void CP2pContextServer::setPendingEvent(void)
+  {
+    pendingEvent=true;
+  }
+
+  bool CP2pContextServer::hasPendingEvent(void)
+  {
+    return pendingEvent;
+  }
+
+  bool CP2pContextServer::hasFinished(void)
+  {
+    return finished;
+  }
+
+  bool CP2pContextServer::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 CP2pContextServer::listen(void)
+  {
+    int rank;
+    int flag;
+    MPI_Status status;
+    flag=true ;
+
+    while(flag)
+    {
+      traceOff();
+      MPI_Iprobe(MPI_ANY_SOURCE, 20,interCommMerged_, &flag, &status);
+      traceOn();
+      if (flag==true)
+      {
+        requests_.push_back(new CRequest(interCommMerged_, status)) ;
+        if (requests_.back()->test()) 
+        {
+          processRequest(*(requests_.back())) ;
+          delete requests_.back();
+          requests_.pop_back() ;
+        }
+      }
+    }
+  }
+
+  void CP2pContextServer::listenPendingRequest(void)
+  {
+    auto it = requests_.begin() ;
+    while (it != requests_.end())
+    {
+      if ((*it)->test())
+      {
+        processRequest(*(*it)) ;
+        delete (*it);
+        auto it2=it ;
+        ++it ;
+        requests_.erase(it2) ;
+      }
+      else ++it ;
+    }
+  }
+
+  void CP2pContextServer::processRequest(CRequest& request)
+  {
+    int rank = request.getRank() ;
+    auto it=buffers_.find(rank);
+    if (it==buffers_.end())
+    {
+      buffers_[rank] = new CP2pServerBuffer(rank, commSelf_, interCommMerged_, pendingEvents_, completedEvents_, request.getBuffer()) ;
+    }
+    else it->second->receivedRequest(request.getBuffer()) ;
+  }
+
+  void CP2pContextServer::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()) ;
+*/
+      for(auto it=pendingEvents_.begin() ;  it!=pendingEvents_.end() ;)
+      {
+        SPendingEvent& nextEvent = it->second ;
+        for(auto& buffer : nextEvent.buffers ) buffer->eventLoop() ;
+        if (nextEvent.nbSenders==0) it=pendingEvents_.erase(it) ;
+        else ++it ;
+      }
+    }
+  }
+
+
+  void CP2pContextServer::processEvents(bool enableEventsProcessing)
+  {
+  
+    if (isProcessingEvent_) return ;
+
+    auto it=completedEvents_.find(currentTimeLine);
+
+    if (it!=completedEvents_.end())
+    {
+      if (it->second.nbSenders == it->second.currentNbSenders)
+      {
+        if (!scheduled) 
+        {
+          eventScheduler_->registerEvent(currentTimeLine,hashId);
+          scheduled=true;
+        }
+        else if (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 ;
+          }
+
+          eventScheduler_->popEvent() ;
+
+          isProcessingEvent_=true ;
+          CEventServer event(this) ;
+          for(auto& buffer : it->second.buffers) buffer->fillEventServer(currentTimeLine, event) ;
+//          MPI_Barrier(intraComm) ;
+          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;
+        }
+      }
+    }
+  }
+
+  CP2pContextServer::~CP2pContextServer()
+  {
+    for(auto& buffer : buffers_) delete buffer.second;
+    buffers_.clear() ;
+  }
+
+  void CP2pContextServer::releaseBuffers()
+  {
+    //for(auto it=buffers.begin();it!=buffers.end();++it) delete it->second ;
+    //buffers.clear() ; 
+    freeWindows() ;
+  }
+
+  void CP2pContextServer::freeWindows()
+  {
+    //  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 CP2pContextServer::notifyClientsFinalize(void)
+  {
+    for(auto it=buffers_.begin();it!=buffers_.end();++it)
+    {
+      it->second->notifyClientFinalize() ;
+    }
+  }
+
+  void CP2pContextServer::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)<<" CP2pContextServer: 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()) 
+    {
+      if (event.type==CField::EVENT_ID_UPDATE_DATA) CField::dispatchEvent(event);
+      else 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 CP2pContextServer::dispatchEvent(CEventServer& event)",<<" Bad event class Id"<<endl);
+    }
+  }
+
+  bool CP2pContextServer::isCollectiveEvent(CEventServer& event)
+  {
+    if (event.type>1000) return false ;
+    else return true ;
+  }
+}
Index: XIOS3/trunk/src/transport/p2p_context_server.hpp
===================================================================
--- XIOS3/trunk/src/transport/p2p_context_server.hpp	(revision 2556)
+++ XIOS3/trunk/src/transport/p2p_context_server.hpp	(revision 2556)
@@ -0,0 +1,117 @@
+#ifndef __P2P_CONTEXT_SERVER_HPP__
+#define __P2P_CONTEXT_SERVER_HPP__
+#include "xios_spl.hpp"
+#include "event_server.hpp"
+#include "buffer_server.hpp"
+#include "p2p_server_buffer.hpp"
+#include "p2p_server_base.hpp"
+#include "mpi.hpp"
+#include "event_scheduler.hpp"
+#include "context_server.hpp"
+
+namespace xios
+{
+  class CContext ;
+  class CContextClient;
+
+  class CP2pContextServer : public CContextServer, public CP2pServerBase
+  {
+    
+    public:
+
+      CP2pContextServer(CContext* parent,MPI_Comm intraComm,MPI_Comm interComm) ;
+      ~CP2pContextServer() ;
+      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,CP2pServerBuffer*> 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: XIOS3/trunk/src/transport/p2p_cs_buffer_base.hpp
===================================================================
--- XIOS3/trunk/src/transport/p2p_cs_buffer_base.hpp	(revision 2556)
+++ XIOS3/trunk/src/transport/p2p_cs_buffer_base.hpp	(revision 2556)
@@ -0,0 +1,30 @@
+#ifndef __P2P_CS_BUFFER_BASE_HPP__
+#define __P2P_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 CP2pCSBufferBase 
+  {
+    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: XIOS3/trunk/src/transport/p2p_server_base.hpp
===================================================================
--- XIOS3/trunk/src/transport/p2p_server_base.hpp	(revision 2556)
+++ XIOS3/trunk/src/transport/p2p_server_base.hpp	(revision 2556)
@@ -0,0 +1,26 @@
+#ifndef __P2P_SERVER_BASE_HPP__
+#define __P2P_SERVER_BASE_HPP__
+#include "xios_spl.hpp"
+
+namespace xios
+{
+
+  class CP2pServerBuffer ;
+  
+  class CP2pServerBase
+  {
+    public:
+      struct SPendingEvent
+      {
+        int nbSenders ;
+        int currentNbSenders ;
+        std::list<CP2pServerBuffer*> buffers ;
+      } ;
+  } ;
+
+}
+
+
+
+
+#endif
Index: XIOS3/trunk/src/transport/p2p_server_buffer.cpp
===================================================================
--- XIOS3/trunk/src/transport/p2p_server_buffer.cpp	(revision 2556)
+++ XIOS3/trunk/src/transport/p2p_server_buffer.cpp	(revision 2556)
@@ -0,0 +1,428 @@
+#include "p2p_server_buffer.hpp"
+#include "xios_spl.hpp"
+#include "mpi.hpp"
+#include "timer.hpp"
+#include "buffer_in.hpp"
+
+
+
+namespace xios
+{
+  extern CLogType logProtocol ;
+
+  CP2pServerBuffer::CP2pServerBuffer(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), interCommMerged_(interCommMerged), 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 CP2pServerBuffer::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 CP2pServerBuffer::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
+    {
+      info(logProtocol)<<"received request from rank : "<<clientRank_<<"  with timeline : "<<timeline
+                                                        <<"   at time : "<<CTimer::get("XIOS server").getTime()<<endl ;
+      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 CP2pServerBuffer::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 ;
+        if (info.isActive(logProtocol)) CTimer::get("Send bloc to free").resume() ;
+        //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_) ; 
+        if (info.isActive(logProtocol)) CTimer::get("Send bloc to free").suspend() ;
+        lastBlocToFree_ = 0 ;        
+      }
+    }
+
+    if (buffers_.size()>1) 
+     if (buffers_.front()->getCount()==0) buffers_.pop_front() ; // if buffer is empty free buffer
+  }
+
+  void CP2pServerBuffer::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_) ; 
+    int dummy ;
+    MPI_Send(&dummy, 0, MPI_CHAR, clientRank_, 22, interCommMerged_) ;
+  }
+  
+  void CP2pServerBuffer::testPendingRequests(void)
+  {
+    if (!pendingRmaRequests_.empty())
+    {
+      int flag ;    
+
+      if (info.isActive(logProtocol)) CTimer::get("transfer MPI_Testall").resume() ;
+      MPI_Testall(pendingRmaRequests_.size(), pendingRmaRequests_.data(), &flag, pendingRmaStatus_.data()) ;
+      if (info.isActive(logProtocol)) CTimer::get("transfer MPI_Testall").suspend() ;
+      
+      if (flag==true) 
+      {
+        //if (!isLocked_) ERROR("void COneSidedServerBuffer::testPendingRequests(void)",<<"windows is not Locked");
+        //for(auto& win : windowsLocked_) 
+        //{
+        //  info(logProtocol)<<"unlock window "<<win<<endl ;
+        //  if (info.isActive(logProtocol)) CTimer::get("transfer unlock").resume() ;
+        //  MPI_Win_unlock(windowRank_,windows_[win]) ; 
+        //  if (info.isActive(logProtocol)) CTimer::get("transfer unlock").suspend() ;
+        //}
+        //windowsLocked_.clear() ;
+        
+
+        if (info.isActive(logProtocol)) CTimer::get("transfer MPI_Rget from "+std::to_string(clientRank_)).suspend() ;
+        if (info.isActive(logProtocol)) CTimer::get("lastTransfer from "+std::to_string(clientRank_)).suspend() ;
+        
+        size_t transferedSize = 0 ;
+        for(auto& count : pendingRmaCount_) transferedSize+=count ;
+
+        if (info.isActive(logProtocol))
+        {
+          double time = CTimer::get("lastTransfer from "+std::to_string(clientRank_)).getCumulatedTime() ;
+          info(logProtocol)<<"Tranfer message from rank : "<<clientRank_<<"  nbBlocs : "<< pendingRmaStatus_.size()
+                           << "  total count = "<<transferedSize<<"  duration : "<<time<<" s"
+                           << "  Bandwith : "<< transferedSize/time<< "byte/s"<<endl ;
+          CTimer::get("lastTransfer from "+std::to_string(clientRank_)).reset() ;
+         }
+
+        //isLocked_=false ;
+        pendingRmaRequests_.clear() ;
+        pendingRmaStatus_.clear() ;
+        pendingRmaCount_.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 CP2pServerBuffer::remainSize(void)
+  {
+    if (!fixed_) return std::numeric_limits<size_t>::max() ;
+    else
+    {
+      if (currentBuffer_ == nullptr) return fixedSize_ ;
+      else return currentBuffer_->remain() ;
+    }
+  }
+
+  void CP2pServerBuffer::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 * bufferServerFactor_ ;
+          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");
+      
+      if (info.isActive(logProtocol)) CTimer::get("transfer MPI_Rget from "+std::to_string(clientRank_)).resume() ;
+      if (info.isActive(logProtocol)) CTimer::get("lastTransfer from "+std::to_string(clientRank_)).resume() ;
+      //for(auto& bloc : blocs) 
+      //{
+      //  int win=get<2>(bloc) ;
+      //  if (windowsLocked_.count(win)==0) 
+      //  {
+      //    info(logProtocol)<<"lock window "<<win<<endl ;
+      //    if (info.isActive(logProtocol)) CTimer::get("transfer lock").resume() ;
+      //    MPI_Win_lock(MPI_LOCK_SHARED, windowRank_, 0, windows_[win]) ;
+      //    if (info.isActive(logProtocol)) CTimer::get("transfer lock").suspend() ;
+      //    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 * bufferServerFactor_ ;
+            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) 
+          //  {
+          //    info(logProtocol)<<"lock window "<<win<<endl ;
+          //    if (info.isActive(logProtocol)) CTimer::get("transfer lock").resume() ;
+          //    MPI_Win_lock(MPI_LOCK_SHARED, windowRank_, 0, windows_[win]) ;
+          //    if (info.isActive(logProtocol)) CTimer::get("transfer lock").suspend() ;
+          //    windowsLocked_.insert(win) ;
+          //  }
+          //}
+        }
+      }
+      while(transferedSize+eventSize<=remain) ;
+      
+    }
+  }
+  
+  void CP2pServerBuffer::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(std::max(fixedSize_, size),fixed_) ;
+          else
+          {
+            currentBufferSize_ = std::max((size_t)(currentBufferSize_*growingFactor_), size) ;
+            newBuffer(currentBufferSize_,fixed_) ;
+          }
+        }
+      } while (size > 0 ) ;
+    }
+
+    pendingRmaStatus_.resize(pendingRmaRequests_.size()) ;
+  }
+
+  void CP2pServerBuffer::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) ;
+    if (info.isActive(logProtocol))
+    {
+      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 ;
+    }
+    if (info.isActive(logProtocol)) CTimer::get("MPI_Rget").resume() ;
+    //MPI_Rget(buffer->getBuffer()+start, count, MPI_CHAR, windowRank_, offsetAddr, count, MPI_CHAR, windows_[window], &request) ;
+    MPI_Irecv(buffer->getBuffer()+start, count, MPI_CHAR, clientRank_, 21, interCommMerged_, &request) ;
+    if (info.isActive(logProtocol)) CTimer::get("MPI_Rget").suspend() ;
+    pendingRmaRequests_.push_back(request) ;
+    pendingRmaCount_.push_back(count) ;
+    onTransferEvents_[timeline].push_back({buffer,start,count,addr}) ;
+  }
+
+  void CP2pServerBuffer::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 ;
+    if (info.isActive(logProtocol)) 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 ;
+
+    completedEvents_.erase(timeline) ;
+    eventLoop() ;
+  }
+
+  
+
+}
Index: XIOS3/trunk/src/transport/p2p_server_buffer.hpp
===================================================================
--- XIOS3/trunk/src/transport/p2p_server_buffer.hpp	(revision 2556)
+++ XIOS3/trunk/src/transport/p2p_server_buffer.hpp	(revision 2556)
@@ -0,0 +1,175 @@
+#ifndef __P2P_SERVER_BUFFER_HPP__
+#define __P2P_SERVER_BUFFER_HPP__
+
+#include "xios_spl.hpp"
+#include "buffer_out.hpp"
+#include "mpi.hpp"
+#include "cxios.hpp"
+#include "event_server.hpp"
+#include "p2p_cs_buffer_base.hpp"
+#include "p2p_server_base.hpp"
+
+namespace xios
+{
+  extern CLogType logProtocol ;
+
+  class CP2pServerBuffer : public CP2pCSBufferBase, public CP2pServerBase
+  {
+    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 ;
+                count = 0 ; 
+              }
+            }
+            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 ;
+                count = 0 ;
+              }
+            }
+            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:
+    
+      CP2pServerBuffer(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. ;
+      double bufferServerFactor_=10. ;
+      
+      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_ ;
+      vector<int> pendingRmaCount_ ;
+
+      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 interCommMerged_ ;
+      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
