source: XIOS/dev/dev_ym/XIOS_SERVICES/src/manager/server_context.cpp @ 1761

Last change on this file since 1761 was 1761, checked in by ymipsl, 5 years ago

implementing first guess for service functionnalities.

YM

  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 7.9 KB
Line 
1#include "server_context.hpp"
2#include "contexts_manager.hpp"
3#include "cxios.hpp"
4#include "mpi.hpp"
5#include "context.hpp"
6#include "register_context_info.hpp"
7#include "services.hpp"
8
9
10namespace xios
11{
12  using namespace std ;
13
14  map<string, tuple<bool,MPI_Comm,MPI_Comm> > CServerContext::overlapedComm_ ;
15
16  CServerContext::CServerContext(CService* parentService, MPI_Comm contextComm, const std::string& poolId, const std::string& serviceId, 
17                                 const int& partitionId, const std::string& contextId) : finalizeSignal_(false), parentService_(parentService)
18  {
19   int localRank, globalRank, commSize ;
20
21    MPI_Comm_dup(contextComm, &contextComm_) ;
22    xiosComm_=CXios::getXiosComm() ;
23 
24    MPI_Comm_rank(xiosComm_,&globalRank) ;
25    MPI_Comm_rank(contextComm_,&localRank) ;
26 
27    winNotify_ = new CWindowManager(contextComm_, maxBufferSize_) ;
28   
29    int type;
30    if (localRank==localLeader_) 
31    {
32      globalLeader_=globalRank ;
33      MPI_Comm_rank(contextComm_,&commSize) ;
34     
35      CXios::getServicesManager()->getServiceType(poolId,serviceId, 0, type) ;
36      SRegisterContextInfo contextInfo = {poolId, serviceId, partitionId, type, contextId, commSize, globalLeader_} ;
37      name_ = CXios::getContextsManager()->getServerContextName(poolId, serviceId, partitionId, type, contextId) ;
38      CXios::getContextsManager()->registerContext(name_, contextInfo) ;
39    }
40    MPI_Bcast(&type, 1, MPI_INT, localLeader_,contextComm_) ;
41    name_ = CXios::getContextsManager()->getServerContextName(poolId, serviceId, partitionId, type, contextId) ;
42    context_=CContext::create(name_);
43
44    context_->init(this, contextComm, type) ;
45
46    info(10)<<"Context "<< CXios::getContextsManager()->getServerContextName(poolId, serviceId, partitionId, type, contextId)<<" created, on local rank "<<localRank
47                        <<" and global rank "<<globalRank<<endl  ;
48  }
49
50 
51  bool CServerContext::createIntercomm(const string& poolId, const string& serviceId, const int& partitionId, const string& contextId, 
52                                       const MPI_Comm& intraComm, MPI_Comm& interCommClient, MPI_Comm& interCommServer, bool wait)
53  {
54    int intraCommRank ;
55    MPI_Comm_rank(intraComm, &intraCommRank) ;
56    int contextLeader ;
57
58    bool ok ;
59    int type ;
60    MPI_Comm newInterCommClient, newInterCommServer ;
61    MPI_Comm_dup(contextComm_,&newInterCommClient) ;
62    MPI_Comm_dup(contextComm_,&newInterCommServer) ;
63    overlapedComm_[name_]=tuple<bool, MPI_Comm, MPI_Comm>(false, newInterCommClient, newInterCommServer) ;
64    MPI_Barrier(contextComm_) ;
65
66    if (intraCommRank==0)
67    {
68      ok=CXios::getContextsManager()->createServerContextIntercomm(poolId, serviceId, partitionId, contextId, name_, wait) ;
69      if (ok) 
70      {
71        CXios::getServicesManager()->getServiceType(poolId,serviceId, 0, type) ;
72        string name=CXios::getContextsManager()->getServerContextName(poolId, serviceId, partitionId, type, contextId) ;
73        CXios::getContextsManager()->getContextLeader(name, contextLeader) ;
74      }
75    }
76   
77    auto eventScheduler=parentService_->getEventScheduler() ;
78    std::hash<string> hashString ;
79    size_t hashId = hashString(name_) ;
80    size_t currentTimeLine=0 ;
81    eventScheduler->registerEvent(currentTimeLine,hashId); 
82
83    while (!eventScheduler->queryEvent(currentTimeLine,hashId))
84    {
85       CXios::getDaemonsManager()->eventLoop() ;
86    } 
87   
88    MPI_Bcast(&ok, 1, MPI_INT, 0, intraComm) ;
89
90    if (ok) 
91    {
92      int overlap  ;
93      if (get<0>(overlapedComm_[name_])) overlap=1 ;
94      else overlap=0 ;
95
96      int nOverlap ; 
97      MPI_Allreduce(&overlap, &nOverlap, 1, MPI_INT, MPI_SUM, contextComm_) ;
98      int commSize ;
99      MPI_Comm_size(contextComm_,&commSize ) ;
100      if (nOverlap==commSize)
101      {
102        cout<<"CServerContext::createIntercomm : total overlap ==> context in attached mode"<<endl ;
103        interCommClient=newInterCommClient ;
104        interCommServer=newInterCommServer ;
105      }
106      else if (nOverlap==0)
107      { 
108        cout<<"CServerContext::createIntercomm : No overlap ==> context in server mode"<<endl ;
109        MPI_Intercomm_create(intraComm, 0, xiosComm_, contextLeader, 3141, &interCommClient) ;
110        MPI_Comm_dup(interCommClient, &interCommServer) ;
111        MPI_Comm_free(&newInterCommClient) ;
112        MPI_Comm_free(&newInterCommServer) ;
113      }
114      else
115      {
116        cout<<"CServerContext::createIntercomm : partial overlap ==> not managed"<<endl ;
117      }
118    }
119    overlapedComm_.erase(name_) ;
120    return ok ;
121  }
122
123
124  void CServerContext::createIntercomm(int remoteLeader, const string& sourceContext)
125  {
126     int commSize ;
127     MPI_Comm_size(contextComm_,&commSize) ;
128     for(int rank=0; rank<commSize; rank++)
129     {
130       notifyType_=NOTIFY_CREATE_INTERCOMM ;
131       notifyCreateIntercomm_ = make_tuple(remoteLeader, sourceContext) ;
132       sendNotification(rank) ;
133     }
134  }
135 
136  void CServerContext::sendNotification(int rank)
137  {
138    winNotify_->lockWindow(rank,0) ;
139    winNotify_->pushToWindow(rank, this, &CServerContext::notificationsDumpOut) ;
140    winNotify_->unlockWindow(rank,0) ;
141  }
142
143 
144  void CServerContext::notificationsDumpOut(CBufferOut& buffer)
145  {
146   
147    buffer.realloc(maxBufferSize_) ;
148   
149    if (notifyType_==NOTIFY_CREATE_INTERCOMM)
150    {
151      auto& arg=notifyCreateIntercomm_ ;
152      buffer << notifyType_ << std::get<0>(arg)<<std::get<1>(arg) ;
153    }
154  }
155
156  void CServerContext::notificationsDumpIn(CBufferIn& buffer)
157  {
158    if (buffer.bufferSize() == 0) notifyType_= NOTIFY_NOTHING ;
159    else
160    {
161      buffer>>notifyType_;
162      if (notifyType_==NOTIFY_CREATE_INTERCOMM)
163      {
164        auto& arg=notifyCreateIntercomm_ ;
165        buffer >> std::get<0>(arg)>> std::get<1>(arg) ;
166      }
167    }
168  }
169
170  void CServerContext::checkNotifications(void)
171  {
172    int commRank ;
173    MPI_Comm_rank(contextComm_, &commRank) ;
174    winNotify_->lockWindow(commRank,0) ;
175    winNotify_->popFromWindow(commRank, this, &CServerContext::notificationsDumpIn) ;
176    winNotify_->unlockWindow(commRank,0) ;
177    if (notifyType_==NOTIFY_CREATE_INTERCOMM) createIntercomm() ;
178  }
179
180  bool CServerContext::eventLoop(void)
181  {
182    bool finished=false ;
183    checkNotifications() ;
184    if (context_!=nullptr) 
185    {
186      if (context_->eventLoop())
187      {
188        context_=nullptr ;
189        // destroy context ??? --> later
190      }
191    }
192
193    if (context_==nullptr && finalizeSignal_) finished=true ;
194    return finished ;
195  }
196
197  void CServerContext::createIntercomm(void)
198  {
199     MPI_Comm interCommServer, interCommClient ;
200     int remoteLeader=get<0>(notifyCreateIntercomm_) ;
201     string sourceContext=get<1>(notifyCreateIntercomm_) ;
202
203     auto it=overlapedComm_.find(sourceContext) ;
204     int overlap=0 ;
205     if (it!=overlapedComm_.end())
206     {
207       get<0>(it->second)=true ;
208       overlap=1 ;
209     }
210     int nOverlap ; 
211     MPI_Allreduce(&overlap, &nOverlap, 1, MPI_INT, MPI_SUM, contextComm_) ;
212     int commSize ;
213     MPI_Comm_size(contextComm_,&commSize ) ;
214
215    if (nOverlap==commSize)
216    {
217      cout<<"CServerContext::createIntercomm : total overlap ==> context in attached mode"<<endl ;
218      interCommClient=get<2>(it->second) ;
219      interCommServer=get<1>(it->second) ;
220      context_ -> createClientInterComm(interCommClient, interCommServer ) ;
221      clientsInterComm_.push_back(interCommClient) ;
222      clientsInterComm_.push_back(interCommServer) ;
223    }
224    else if (nOverlap==0)
225    { 
226      cout<<"CServerContext::createIntercomm : No overlap ==> context in server mode"<<endl ;
227      MPI_Intercomm_create(contextComm_, 0, xiosComm_, remoteLeader, 3141, &interCommServer) ;
228      MPI_Comm_dup(interCommServer,&interCommClient) ;
229      context_ -> createClientInterComm(interCommClient,interCommServer) ;
230      clientsInterComm_.push_back(interCommClient) ;
231      clientsInterComm_.push_back(interCommServer) ;
232    }
233    else
234    {
235      cout<<"CServerContext::createIntercomm : partial overlap ==> not managed"<<endl ;
236    }
237   
238  }
239
240  void CServerContext::finalizeSignal(void)
241  {
242    finalizeSignal_=true ;
243  }
244   
245
246}
Note: See TracBrowser for help on using the repository browser.