source: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/context.cpp @ 2124

Last change on this file since 2124 was 2124, checked in by ymipsl, 3 years ago

Fix bad suffix context in generated object id
YM

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
File size: 85.9 KB
Line 
1#include "context.hpp"
2#include "attribute_template.hpp"
3#include "object_template.hpp"
4#include "group_template.hpp"
5
6#include "calendar_type.hpp"
7#include "duration.hpp"
8
9#include "context_client.hpp"
10#include "context_server.hpp"
11#include "nc4_data_output.hpp"
12#include "node_type.hpp"
13#include "message.hpp"
14#include "type.hpp"
15#include "xios_spl.hpp"
16#include "timer.hpp"
17#include "memtrack.hpp"
18#include <limits>
19#include <fstream>
20#include "server.hpp"
21#include "distribute_file_server2.hpp"
22#include "services_manager.hpp"
23#include "contexts_manager.hpp"
24#include "cxios.hpp"
25#include "client.hpp"
26#include "coupler_in.hpp"
27#include "coupler_out.hpp"
28#include "servers_ressource.hpp"
29#include "pool_ressource.hpp"
30#include "services.hpp"
31#include "contexts_manager.hpp"
32#include <chrono>
33#include <random>
34
35namespace xios
36{
37
38  std::shared_ptr<CContextGroup> CContext::root;
39
40   /// ////////////////////// Définitions ////////////////////// ///
41
42   CContext::CContext(void)
43      : CObjectTemplate<CContext>(), CContextAttributes()
44      , calendar(), hasClient(false), hasServer(false)
45      , isPostProcessed(false), finalized(false)
46      , client(nullptr), server(nullptr)
47      , allProcessed(false), countChildContextFinalized_(0), isProcessingEvent_(false)
48
49   { /* Ne rien faire de plus */ }
50
51   CContext::CContext(const StdString & id)
52      : CObjectTemplate<CContext>(id), CContextAttributes()
53      , calendar(), hasClient(false), hasServer(false)
54      , isPostProcessed(false), finalized(false)
55      , client(nullptr), server(nullptr)
56      , allProcessed(false), countChildContextFinalized_(0), isProcessingEvent_(false)
57   { /* Ne rien faire de plus */ }
58
59   CContext::~CContext(void)
60   {
61     delete client;
62     delete server;
63     for (std::vector<CContextClient*>::iterator it = clientPrimServer.begin(); it != clientPrimServer.end(); it++)  delete *it;
64     for (std::vector<CContextServer*>::iterator it = serverPrimServer.begin(); it != serverPrimServer.end(); it++)  delete *it;
65
66   }
67
68   //----------------------------------------------------------------
69   //! Get name of context
70   StdString CContext::GetName(void)   { return (StdString("context")); }
71   StdString CContext::GetDefName(void){ return (CContext::GetName()); }
72   ENodeType CContext::GetType(void)   { return (eContext); }
73
74   //----------------------------------------------------------------
75
76  void CContext::initEventScheduler(void)
77  {
78    SRegisterContextInfo contextInfo ;
79    CXios::getContextsManager()->getContextInfo(this->getId(), contextInfo, getIntraComm()) ;
80
81    eventScheduler_=CXios::getPoolRessource()->getService(contextInfo.serviceId,contextInfo.partitionId)->getEventScheduler() ;
82 
83    // generate unique hash for server
84    auto time=chrono::system_clock::now().time_since_epoch().count() ;
85    std::default_random_engine rd(time); // not reproducible from a run to another
86    std::uniform_int_distribution<size_t> dist;
87    hashId_=dist(rd) ;
88    MPI_Bcast(&hashId_,1,MPI_SIZE_T,0,getIntraComm()) ; // Bcast to all server of the context
89  }
90   /*!
91   \brief Get context group (context root)
92   \return Context root
93   */
94   CContextGroup* CContext::getRoot(void)
95   TRY
96   {
97      if (root.get()==NULL) root=std::shared_ptr<CContextGroup>(new CContextGroup(xml::CXMLNode::GetRootName()));
98      return root.get();
99   }
100   CATCH
101
102   //----------------------------------------------------------------
103
104   /*!
105   \brief Get calendar of a context
106   \return Calendar
107   */
108   std::shared_ptr<CCalendar> CContext::getCalendar(void) const
109   TRY
110   {
111      return (this->calendar);
112   }
113   CATCH
114
115   //----------------------------------------------------------------
116
117   /*!
118   \brief Set a context with a calendar
119   \param[in] newCalendar new calendar
120   */
121   void CContext::setCalendar(std::shared_ptr<CCalendar> newCalendar)
122   TRY
123   {
124      this->calendar = newCalendar;
125   }
126   CATCH_DUMP_ATTR
127
128   //----------------------------------------------------------------
129   /*!
130   \brief Parse xml file and write information into context object
131   \param [in] node xmld node corresponding in xml file
132   */
133   void CContext::parse(xml::CXMLNode & node)
134   TRY
135   {
136      CContext::SuperClass::parse(node);
137
138      // PARSING POUR GESTION DES ENFANTS
139      xml::THashAttributes attributes = node.getAttributes();
140
141      if (attributes.end() != attributes.find("src"))
142      {
143         StdIFStream ifs ( attributes["src"].c_str() , StdIFStream::in );
144         if ( (ifs.rdstate() & std::ifstream::failbit ) != 0 )
145            ERROR("void CContext::parse(xml::CXMLNode & node)",
146                  <<endl<< "Can not open <"<<attributes["src"].c_str()<<"> file" );
147         if (!ifs.good())
148            ERROR("CContext::parse(xml::CXMLNode & node)",
149                  << "[ filename = " << attributes["src"] << " ] Bad xml stream !");
150         xml::CXMLParser::ParseInclude(ifs, attributes["src"], *this);
151      }
152
153      if (node.getElementName().compare(CContext::GetName()))
154         DEBUG("Le noeud is wrong defined but will be considered as a context !");
155
156      if (!(node.goToChildElement()))
157      {
158         DEBUG("Le context ne contient pas d'enfant !");
159      }
160      else
161      {
162         do { // Parcours des contextes pour traitement.
163
164            StdString name = node.getElementName();
165            attributes.clear();
166            attributes = node.getAttributes();
167
168            if (attributes.end() != attributes.find("id"))
169            {
170              DEBUG(<< "Definition node has an id,"
171                    << "it will not be taking account !");
172            }
173
174#define DECLARE_NODE(Name_, name_)    \
175   if (name.compare(C##Name_##Definition::GetDefName()) == 0) \
176   { C##Name_##Definition::create(C##Name_##Definition::GetDefName()) -> parse(node); continue; }
177#define DECLARE_NODE_PAR(Name_, name_)
178#include "node_type.conf"
179
180            DEBUG(<< "The element \'"     << name
181                  << "\' in the context \'" << CContext::getCurrent()->getId()
182                  << "\' is not a definition !");
183
184         } while (node.goToNextElement());
185
186         node.goToParentElement(); // Retour au parent
187      }
188   }
189   CATCH_DUMP_ATTR
190
191   //----------------------------------------------------------------
192   //! Show tree structure of context
193   void CContext::ShowTree(StdOStream & out)
194   TRY
195   {
196      StdString currentContextId = CContext::getCurrent() -> getId();
197      std::vector<CContext*> def_vector =
198         CContext::getRoot()->getChildList();
199      std::vector<CContext*>::iterator
200         it = def_vector.begin(), end = def_vector.end();
201
202      out << "<? xml version=\"1.0\" ?>" << std::endl;
203      out << "<"  << xml::CXMLNode::GetRootName() << " >" << std::endl;
204
205      for (; it != end; it++)
206      {
207         CContext* context = *it;
208         CContext::setCurrent(context->getId());
209         out << *context << std::endl;
210      }
211
212      out << "</" << xml::CXMLNode::GetRootName() << " >" << std::endl;
213      CContext::setCurrent(currentContextId);
214   }
215   CATCH
216
217   //----------------------------------------------------------------
218
219   //! Convert context object into string (to print)
220   StdString CContext::toString(void) const
221   TRY
222   {
223      StdOStringStream oss;
224      oss << "<" << CContext::GetName()
225          << " id=\"" << this->getId() << "\" "
226          << SuperClassAttribute::toString() << ">" << std::endl;
227      if (!this->hasChild())
228      {
229         //oss << "<!-- No definition -->" << std::endl; // fait planter l'incrémentation
230      }
231      else
232      {
233
234#define DECLARE_NODE(Name_, name_)    \
235   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
236   oss << * C##Name_##Definition::get(C##Name_##Definition::GetDefName()) << std::endl;
237#define DECLARE_NODE_PAR(Name_, name_)
238#include "node_type.conf"
239
240      }
241      oss << "</" << CContext::GetName() << " >";
242      return (oss.str());
243   }
244   CATCH
245
246   //----------------------------------------------------------------
247
248   /*!
249   \brief Find all inheritace among objects in a context.
250   \param [in] apply (true) write attributes of parent into ones of child if they are empty
251                     (false) write attributes of parent into a new container of child
252   \param [in] parent unused
253   */
254   void CContext::solveDescInheritance(bool apply, const CAttributeMap * const UNUSED(parent))
255   TRY
256   {
257#define DECLARE_NODE(Name_, name_)    \
258   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
259     C##Name_##Definition::get(C##Name_##Definition::GetDefName())->solveDescInheritance(apply);
260#define DECLARE_NODE_PAR(Name_, name_)
261#include "node_type.conf"
262   }
263   CATCH_DUMP_ATTR
264
265   //----------------------------------------------------------------
266
267   //! Verify if all root definition in the context have child.
268   bool CContext::hasChild(void) const
269   TRY
270   {
271      return (
272#define DECLARE_NODE(Name_, name_)    \
273   C##Name_##Definition::has(C##Name_##Definition::GetDefName())   ||
274#define DECLARE_NODE_PAR(Name_, name_)
275#include "node_type.conf"
276      false);
277}
278   CATCH
279
280   //----------------------------------------------------------------
281
282   void CContext::CleanTree(void)
283   TRY
284   {
285#define DECLARE_NODE(Name_, name_) C##Name_##Definition::ClearAllAttributes();
286#define DECLARE_NODE_PAR(Name_, name_)
287#include "node_type.conf"
288   }
289   CATCH
290
291   ///---------------------------------------------------------------
292
293
294   void CContext::setClientServerBuffer(vector<CField*>& fields, bool bufferForWriting)
295   TRY
296   {
297      // Estimated minimum event size for small events (20 is an arbitrary constant just for safety)
298     const size_t minEventSize = CEventClient::headerSize + 20 * sizeof(int);
299      // Ensure there is at least some room for 20 of such events in the buffers
300     size_t minBufferSize = std::max(CXios::minBufferSize, 20 * minEventSize);
301
302#define DECLARE_NODE(Name_, name_)    \
303     if (minBufferSize < sizeof(C##Name_##Definition)) minBufferSize = sizeof(C##Name_##Definition);
304#define DECLARE_NODE_PAR(Name_, name_)
305#include "node_type.conf"
306#undef DECLARE_NODE
307#undef DECLARE_NODE_PAR
308
309
310     map<CContextClient*,map<int,size_t>> dataSize ;
311     map<CContextClient*,map<int,size_t>> maxEventSize ;
312     map<CContextClient*,map<int,size_t>> attributesSize ; 
313
314     for(auto field : fields)
315     {
316       field->setContextClientDataBufferSize(dataSize, maxEventSize, bufferForWriting) ;
317       field->setContextClientAttributesBufferSize(attributesSize, maxEventSize, bufferForWriting) ;
318     }
319     
320
321     for(auto& it : attributesSize)
322     {
323       auto contextClient = it.first ;
324       auto& contextDataSize =  dataSize[contextClient] ;
325       auto& contextAttributesSize =  attributesSize[contextClient] ;
326       auto& contextMaxEventSize =  maxEventSize[contextClient] ;
327   
328       for (auto& it : contextAttributesSize)
329       {
330         auto serverRank=it.first ;
331         auto& buffer = contextAttributesSize[serverRank] ;
332         if (contextDataSize[serverRank] > buffer) buffer=contextDataSize[serverRank] ;
333         buffer *= CXios::bufferSizeFactor;
334         if (buffer < minBufferSize) buffer = minBufferSize;
335         if (buffer > CXios::maxBufferSize ) buffer = CXios::maxBufferSize;
336       }
337
338       // Leaders will have to send some control events so ensure there is some room for those in the buffers
339       if (contextClient->isServerLeader())
340         for(auto& rank : contextClient->getRanksServerLeader())
341           if (!contextAttributesSize.count(rank))
342           {
343             contextAttributesSize[rank] = minBufferSize;
344             contextMaxEventSize[rank] = minEventSize;
345           }
346     
347       contextClient->setBufferSize(contextAttributesSize, contextMaxEventSize);   
348     }
349   }
350   CATCH_DUMP_ATTR
351
352
353    /*!
354    Sets client buffers.
355    \param [in] contextClient
356    \param [in] bufferForWriting True if buffers are used for sending data for writing
357    This flag is only true for client and server-1 for communication with server-2
358  */
359  // ym obsolete to be removed
360   void CContext::setClientServerBuffer(CContextClient* contextClient, bool bufferForWriting)
361   TRY
362   {
363      // Estimated minimum event size for small events (20 is an arbitrary constant just for safety)
364     const size_t minEventSize = CEventClient::headerSize + 20 * sizeof(int);
365
366      // Ensure there is at least some room for 20 of such events in the buffers
367      size_t minBufferSize = std::max(CXios::minBufferSize, 20 * minEventSize);
368
369#define DECLARE_NODE(Name_, name_)    \
370     if (minBufferSize < sizeof(C##Name_##Definition)) minBufferSize = sizeof(C##Name_##Definition);
371#define DECLARE_NODE_PAR(Name_, name_)
372#include "node_type.conf"
373#undef DECLARE_NODE
374#undef DECLARE_NODE_PAR
375
376     // Compute the buffer sizes needed to send the attributes and data corresponding to fields
377     std::map<int, StdSize> maxEventSize;
378     std::map<int, StdSize> bufferSize = getAttributesBufferSize(maxEventSize, contextClient, bufferForWriting);
379     std::map<int, StdSize> dataBufferSize = getDataBufferSize(maxEventSize, contextClient, bufferForWriting);
380
381     std::map<int, StdSize>::iterator it, ite = dataBufferSize.end();
382     for (it = dataBufferSize.begin(); it != ite; ++it)
383       if (it->second > bufferSize[it->first]) bufferSize[it->first] = it->second;
384
385     // Apply the buffer size factor, check that we are above the minimum buffer size and below the maximum size
386     ite = bufferSize.end();
387     for (it = bufferSize.begin(); it != ite; ++it)
388     {
389       it->second *= CXios::bufferSizeFactor;
390       if (it->second < minBufferSize) it->second = minBufferSize;
391       if (it->second > CXios::maxBufferSize) it->second = CXios::maxBufferSize;
392     }
393
394     // Leaders will have to send some control events so ensure there is some room for those in the buffers
395     if (contextClient->isServerLeader())
396     {
397       const std::list<int>& ranks = contextClient->getRanksServerLeader();
398       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
399       {
400         if (!bufferSize.count(*itRank))
401         {
402           bufferSize[*itRank] = minBufferSize;
403           maxEventSize[*itRank] = minEventSize;
404         }
405       }
406     }
407     contextClient->setBufferSize(bufferSize, maxEventSize);
408   }
409   CATCH_DUMP_ATTR
410
411 /*!
412    * Compute the required buffer size to send the fields data.
413    * \param maxEventSize [in/out] the size of the bigger event for each connected server
414    * \param [in] contextClient
415    * \param [in] bufferForWriting True if buffers are used for sending data for writing
416      This flag is only true for client and server-1 for communication with server-2
417    */
418   std::map<int, StdSize> CContext::getDataBufferSize(std::map<int, StdSize>& maxEventSize,
419                                                      CContextClient* contextClient, bool bufferForWriting /*= "false"*/)
420   TRY
421   {
422     std::map<int, StdSize> dataSize;
423
424     // Find all reference domain and axis of all active fields
425     std::vector<CFile*>& fileList = bufferForWriting ? this->enabledWriteModeFiles : this->enabledReadModeFiles;
426     size_t numEnabledFiles = fileList.size();
427     for (size_t i = 0; i < numEnabledFiles; ++i)
428     {
429       CFile* file = fileList[i];
430       if (file->getContextClient() == contextClient)
431       {
432         std::vector<CField*> enabledFields = file->getEnabledFields();
433         size_t numEnabledFields = enabledFields.size();
434         for (size_t j = 0; j < numEnabledFields; ++j)
435         {
436           // const std::vector<std::map<int, StdSize> > mapSize = enabledFields[j]->getGridDataBufferSize(contextClient);
437           const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataBufferSize(contextClient,bufferForWriting);
438           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
439           for (; it != itE; ++it)
440           {
441             // If dataSize[it->first] does not exist, it will be zero-initialized
442             // so we can use it safely without checking for its existance
443           if (CXios::isOptPerformance)
444               dataSize[it->first] += it->second;
445             else if (dataSize[it->first] < it->second)
446               dataSize[it->first] = it->second;
447
448           if (maxEventSize[it->first] < it->second)
449               maxEventSize[it->first] = it->second;
450           }
451         }
452       }
453     }
454     return dataSize;
455   }
456   CATCH_DUMP_ATTR
457
458/*!
459    * Compute the required buffer size to send the attributes (mostly those grid related).
460    * \param maxEventSize [in/out] the size of the bigger event for each connected server
461    * \param [in] contextClient
462    * \param [in] bufferForWriting True if buffers are used for sending data for writing
463      This flag is only true for client and server-1 for communication with server-2
464    */
465   std::map<int, StdSize> CContext::getAttributesBufferSize(std::map<int, StdSize>& maxEventSize,
466                                                           CContextClient* contextClient, bool bufferForWriting /*= "false"*/)
467   TRY
468   {
469   // As calendar attributes are sent even if there are no active files or fields, maps are initialized according the size of calendar attributes
470     std::map<int, StdSize> attributesSize = CCalendarWrapper::get(CCalendarWrapper::GetDefName())->getMinimumBufferSizeForAttributes(contextClient);
471     maxEventSize = CCalendarWrapper::get(CCalendarWrapper::GetDefName())->getMinimumBufferSizeForAttributes(contextClient);
472
473     std::vector<CFile*>& fileList = this->enabledFiles;
474     size_t numEnabledFiles = fileList.size();
475     for (size_t i = 0; i < numEnabledFiles; ++i)
476     {
477//         CFile* file = this->enabledWriteModeFiles[i];
478        CFile* file = fileList[i];
479        std::vector<CField*> enabledFields = file->getEnabledFields();
480        size_t numEnabledFields = enabledFields.size();
481        for (size_t j = 0; j < numEnabledFields; ++j)
482        {
483          const std::map<int, StdSize> mapSize = enabledFields[j]->getGridAttributesBufferSize(contextClient, bufferForWriting);
484          std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
485          for (; it != itE; ++it)
486          {
487         // If attributesSize[it->first] does not exist, it will be zero-initialized
488         // so we can use it safely without checking for its existence
489             if (attributesSize[it->first] < it->second)
490         attributesSize[it->first] = it->second;
491
492         if (maxEventSize[it->first] < it->second)
493         maxEventSize[it->first] = it->second;
494          }
495        }
496     }
497     return attributesSize;
498   }
499   CATCH_DUMP_ATTR
500
501
502
503   //! Verify whether a context is initialized
504   bool CContext::isInitialized(void)
505   TRY
506   {
507     return hasClient;
508   }
509   CATCH_DUMP_ATTR
510
511
512   void CContext::init(CServerContext* parentServerContext, MPI_Comm intraComm, int serviceType)
513   TRY
514   {
515     parentServerContext_ = parentServerContext ;
516     if (serviceType==CServicesManager::CLIENT) 
517       initClient(intraComm, serviceType) ;
518     else
519       initServer(intraComm, serviceType) ;
520     initEventScheduler() ;
521    }
522    CATCH_DUMP_ATTR
523
524
525
526//! Initialize client side
527   void CContext::initClient(MPI_Comm intraComm, int serviceType)
528   TRY
529   {
530      intraComm_=intraComm ;
531      MPI_Comm_rank(intraComm_, &intraCommRank_) ;
532      MPI_Comm_size(intraComm_, &intraCommSize_) ;
533
534      serviceType_ = CServicesManager::CLIENT ;
535      if (serviceType_==CServicesManager::CLIENT)
536      {
537        hasClient=true ;
538        hasServer=false ;
539      }
540      contextId_ = getId() ;
541     
542      attached_mode=true ;
543      if (!CXios::isUsingServer()) attached_mode=false ;
544
545
546      string contextRegistryId=getId() ;
547      registryIn=new CRegistry(intraComm);
548      registryIn->setPath(contextRegistryId) ;
549     
550      int commRank ;
551      MPI_Comm_rank(intraComm_,&commRank) ;
552      if (commRank==0) registryIn->fromFile("xios_registry.bin") ;
553      registryIn->bcastRegistry() ;
554      registryOut=new CRegistry(intraComm_) ;
555      registryOut->setPath(contextRegistryId) ;
556     
557   }
558   CATCH_DUMP_ATTR
559
560   
561   void CContext::initServer(MPI_Comm intraComm, int serviceType)
562   TRY
563   {
564     hasServer=true;
565     intraComm_=intraComm ;
566     MPI_Comm_rank(intraComm_, &intraCommRank_) ;
567     MPI_Comm_size(intraComm_, &intraCommSize_) ;
568
569     serviceType_=serviceType ;
570
571     if (serviceType_==CServicesManager::GATHERER)
572     {
573       hasClient=true ;
574       hasServer=true ;
575     }
576     else if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER)
577     {
578       hasClient=false ;
579       hasServer=true ;
580     }
581
582     CXios::getContextsManager()->getContextId(getId(), contextId_, intraComm) ;
583     
584     registryIn=new CRegistry(intraComm);
585     registryIn->setPath(contextId_) ;
586     
587     int commRank ;
588     MPI_Comm_rank(intraComm_,&commRank) ;
589     if (commRank==0) registryIn->fromFile("xios_registry.bin") ;
590   
591     registryIn->bcastRegistry() ;
592     registryOut=new CRegistry(intraComm) ;
593     registryOut->setPath(contextId_) ;
594
595   }
596   CATCH_DUMP_ATTR
597
598
599  void CContext::createClientInterComm(MPI_Comm interCommClient, MPI_Comm interCommServer) // for servers
600  TRY
601  {
602    MPI_Comm intraCommClient ;
603    MPI_Comm_dup(intraComm_, &intraCommClient);
604    comms.push_back(intraCommClient);
605    // attached_mode=parentServerContext_->isAttachedMode() ; //ym probably inherited from source context
606    server = new CContextServer(this,intraComm_, interCommServer); // check if we need to dupl. intraComm_ ?
607    client = new CContextClient(this,intraCommClient,interCommClient);
608    client->setAssociatedServer(server) ; 
609    server->setAssociatedClient(client) ; 
610
611  }
612  CATCH_DUMP_ATTR
613
614  void CContext::createServerInterComm(void) 
615  TRY
616  {
617   
618    MPI_Comm interCommClient, interCommServer ;
619
620    if (serviceType_ == CServicesManager::CLIENT)
621    {
622
623      int commRank ;
624      MPI_Comm_rank(intraComm_,&commRank) ;
625      if (commRank==0)
626      {
627        if (attached_mode) CXios::getContextsManager()->createServerContext(CClient::getPoolRessource()->getId(), CXios::defaultServerId, 0, getContextId()) ;
628        else if (CXios::usingServer2) CXios::getContextsManager()->createServerContext(CXios::defaultPoolId, CXios::defaultGathererId, 0, getContextId()) ;
629        else  CXios::getContextsManager()->createServerContext(CXios::defaultPoolId, CXios::defaultServerId, 0, getContextId()) ;
630      }
631
632      MPI_Comm interComm ;
633     
634      if (attached_mode)
635      {
636        parentServerContext_->createIntercomm(CClient::getPoolRessource()->getId(), CXios::defaultServerId, 0, getContextId(), intraComm_, 
637                                              interCommClient, interCommServer) ;
638        int type ; 
639        if (commRank==0) CXios::getServicesManager()->getServiceType(CClient::getPoolRessource()->getId(), CXios::defaultServerId, 0, type) ;
640        MPI_Bcast(&type,1,MPI_INT,0,intraComm_) ;
641        setCurrent(getId()) ; // getCurrent/setCurrent may be supress, it can cause a lot of trouble
642      }
643      else if (CXios::usingServer2)
644      { 
645//      CXios::getContextsManager()->createServerContextIntercomm(CXios::defaultPoolId, CXios::defaultGathererId, 0, getContextId(), intraComm_, interComm) ;
646        parentServerContext_->createIntercomm(CXios::defaultPoolId, CXios::defaultGathererId, 0, getContextId(), intraComm_,
647                                              interCommClient, interCommServer) ;
648        int type ; 
649        if (commRank==0) CXios::getServicesManager()->getServiceType(CXios::defaultPoolId, CXios::defaultGathererId, 0, type) ;
650        MPI_Bcast(&type,1,MPI_INT,0,intraComm_) ;
651      }
652      else
653      {
654        //CXios::getContextsManager()->createServerContextIntercomm(CXios::defaultPoolId, CXios::defaultServerId, 0, getContextId(), intraComm_, interComm) ;
655        parentServerContext_->createIntercomm(CXios::defaultPoolId, CXios::defaultServerId, 0, getContextId(), intraComm_,
656                                              interCommClient, interCommServer) ;
657        int type ; 
658        if (commRank==0) CXios::getServicesManager()->getServiceType(CXios::defaultPoolId, CXios::defaultServerId, 0, type) ;
659        MPI_Bcast(&type,1,MPI_INT,0,intraComm_) ;
660      }
661
662        // intraComm client is not duplicated. In all the code we use client->intraComm for MPI
663        // in future better to replace it by intracommuncator associated to the context
664   
665      MPI_Comm intraCommClient, intraCommServer ;
666      intraCommClient=intraComm_ ;
667      MPI_Comm_dup(intraComm_, &intraCommServer) ;
668      client = new CContextClient(this, intraCommClient, interCommClient);
669      server = new CContextServer(this, intraCommServer, interCommServer);
670      client->setAssociatedServer(server) ;
671      server->setAssociatedClient(client) ;
672    }
673   
674    if (serviceType_ == CServicesManager::GATHERER)
675    {
676      int commRank ;
677      MPI_Comm_rank(intraComm_,&commRank) ;
678     
679      int nbPartitions ;
680      if (commRank==0) 
681      { 
682        CXios::getServicesManager()->getServiceNbPartitions(CXios::defaultPoolId, CXios::defaultServerId, 0, nbPartitions) ;
683        for(int i=0 ; i<nbPartitions; i++)
684          CXios::getContextsManager()->createServerContext(CXios::defaultPoolId, CXios::defaultServerId, i, getContextId()) ;
685      }     
686      MPI_Bcast(&nbPartitions, 1, MPI_INT, 0, intraComm_) ;
687     
688      MPI_Comm interComm ;
689      for(int i=0 ; i<nbPartitions; i++)
690      {
691        parentServerContext_->createIntercomm(CXios::defaultPoolId, CXios::defaultServerId, i, getContextId(), intraComm_, interCommClient, interCommServer) ;
692        int type ; 
693        if (commRank==0) CXios::getServicesManager()->getServiceType(CXios::defaultPoolId, CXios::defaultServerId, 0, type) ;
694        MPI_Bcast(&type,1,MPI_INT,0,intraComm_) ;
695        primServerId_.push_back(CXios::getContextsManager()->getServerContextName(CXios::defaultPoolId, CXios::defaultServerId, i, type, getContextId())) ;
696
697        // intraComm client is not duplicated. In all the code we use client->intraComm for MPI
698        // in future better to replace it by intracommuncator associated to the context
699     
700        MPI_Comm intraCommClient, intraCommServer ;
701
702        intraCommClient=intraComm_ ;
703        MPI_Comm_dup(intraComm_, &intraCommServer) ;
704
705        CContextClient* client = new CContextClient(this, intraCommClient, interCommClient) ;
706        CContextServer* server = new CContextServer(this, intraCommServer, interCommServer) ;
707        client->setAssociatedServer(server) ;
708        server->setAssociatedClient(client) ;
709        clientPrimServer.push_back(client);
710        serverPrimServer.push_back(server); 
711
712     
713      }
714    }
715  }
716  CATCH_DUMP_ATTR
717
718  bool CContext::scheduledEventLoop(bool enableEventsProcessing) 
719  {
720    bool out, finished; 
721    size_t timeLine=timeLine_ ;
722    if (serviceType_==CServicesManager::CLIENT)
723    {
724      timeLine_++ ;
725      eventScheduler_->registerEvent(timeLine, hashId_) ;
726    }
727
728    do
729    { 
730      finished=eventLoop(enableEventsProcessing) ;
731      if (serviceType_==CServicesManager::CLIENT) out = eventScheduler_->queryEvent(timeLine,hashId_) ;
732      else out=true ;
733    }  while(!out) ;
734   
735    return finished ;
736  }
737
738  bool CContext::eventLoop(bool enableEventsProcessing)
739  {
740    bool  finished; 
741    setCurrent(getId()) ;
742
743    if (client!=nullptr && !finalized) client->checkBuffers();
744   
745    for (int i = 0; i < clientPrimServer.size(); ++i)
746    {
747      if (!finalized) clientPrimServer[i]->checkBuffers();
748      if (!finalized) finished &= serverPrimServer[i]->eventLoop(enableEventsProcessing);
749    }
750
751    for (auto couplerOut : couplerOutClient_)
752      if (!finalized) couplerOut.second->checkBuffers();
753   
754    for (auto couplerIn : couplerInClient_)
755      if (!finalized) couplerIn.second->checkBuffers();
756   
757    for (auto couplerOut : couplerOutServer_)
758      if (!finalized) couplerOut.second->eventLoop(enableEventsProcessing);
759
760    for (auto couplerIn : couplerInServer_)
761      if (!finalized) couplerIn.second->eventLoop(enableEventsProcessing);
762   
763    if (server!=nullptr) if (!finalized) finished &= server->eventLoop(enableEventsProcessing);
764    setCurrent(getId()) ;
765    return finalized && finished ;
766  }
767
768  void CContext::addCouplingChanel(const std::string& fullContextId, bool out)
769  {
770     int contextLeader ;
771     
772     if (out)
773     { 
774       if (couplerOutClient_.find(fullContextId)==couplerOutClient_.end()) 
775       {
776         bool ok=CXios::getContextsManager()->getContextLeader(fullContextId, contextLeader, getIntraComm()) ;
777     
778         MPI_Comm interComm, interCommClient, interCommServer  ;
779         MPI_Comm intraCommClient, intraCommServer ;
780
781         if (ok) MPI_Intercomm_create(getIntraComm(), 0, CXios::getXiosComm(), contextLeader, 0, &interComm) ;
782
783        MPI_Comm_dup(intraComm_, &intraCommClient) ;
784        MPI_Comm_dup(intraComm_, &intraCommServer) ;
785        MPI_Comm_dup(interComm, &interCommClient) ;
786        MPI_Comm_dup(interComm, &interCommServer) ;
787        CContextClient* client = new CContextClient(this, intraCommClient, interCommClient);
788        CContextServer* server = new CContextServer(this, intraCommServer, interCommServer);
789        client->setAssociatedServer(server) ;
790        server->setAssociatedClient(client) ;
791        MPI_Comm_free(&interComm) ;
792        couplerOutClient_[fullContextId] = client ;
793        couplerOutServer_[fullContextId] = server ;
794
795/*
796      // for now, we don't now which beffer size must be used for client coupler
797      // It will be evaluated later. Fix a constant size for now...
798      // set to 10Mb for development
799       map<int,size_t> bufferSize, maxEventSize ;
800       for(int i=0;i<client->getRemoteSize();i++)
801       {
802         bufferSize[i]=10000000 ;
803         maxEventSize[i]=10000000 ;
804       }
805
806       client->setBufferSize(bufferSize, maxEventSize);   
807*/
808      }
809    }
810    else if (couplerInClient_.find(fullContextId)==couplerInClient_.end())
811    {
812      bool ok=CXios::getContextsManager()->getContextLeader(fullContextId, contextLeader, getIntraComm()) ;
813     
814       MPI_Comm interComm, interCommClient, interCommServer  ;
815       MPI_Comm intraCommClient, intraCommServer ;
816
817       if (ok) MPI_Intercomm_create(getIntraComm(), 0, CXios::getXiosComm(), contextLeader, 0, &interComm) ;
818
819       MPI_Comm_dup(intraComm_, &intraCommClient) ;
820       MPI_Comm_dup(intraComm_, &intraCommServer) ;
821       MPI_Comm_dup(interComm, &interCommServer) ;
822       MPI_Comm_dup(interComm, &interCommClient) ;
823       CContextServer* server = new CContextServer(this, intraCommServer, interCommServer);
824       CContextClient* client = new CContextClient(this, intraCommClient, interCommClient);
825       client->setAssociatedServer(server) ;
826       server->setAssociatedClient(client) ;
827       MPI_Comm_free(&interComm) ;
828
829       map<int,size_t> bufferSize, maxEventSize ;
830       for(int i=0;i<client->getRemoteSize();i++)
831       {
832         bufferSize[i]=10000000 ;
833         maxEventSize[i]=10000000 ;
834       }
835
836       client->setBufferSize(bufferSize, maxEventSize);   
837       couplerInClient_[fullContextId] = client ;
838       couplerInServer_[fullContextId] = server ;       
839    }
840  }
841 
842  void CContext::globalEventLoop(void)
843  {
844    CXios::getDaemonsManager()->eventLoop() ;
845    setCurrent(getId()) ;
846  }
847
848
849   void CContext::finalize(void)
850   TRY
851   {
852      registryOut->hierarchicalGatherRegistry() ;
853      if (server->intraCommRank==0) CXios::globalRegistry->mergeRegistry(*registryOut) ;
854
855      if (serviceType_==CServicesManager::CLIENT)
856      {
857//ym        doPreTimestepOperationsForEnabledReadModeFiles(); // For now we only use server level 1 to read data
858
859        triggerLateFields() ;
860
861        // inform couplerIn that I am finished
862        for(auto& couplerInClient : couplerInClient_) sendCouplerInContextFinalized(couplerInClient.second) ;
863
864        // wait until received message from couplerOut that they have finished
865        bool couplersInFinalized ;
866        do
867        {
868          couplersInFinalized=true ;
869          for(auto& couplerOutClient : couplerOutClient_) couplersInFinalized &= isCouplerInContextFinalized(couplerOutClient.second) ; 
870          globalEventLoop() ;
871        } while (!couplersInFinalized) ;
872
873        info(100)<<"DEBUG: context "<<getId()<<" Send client finalize"<<endl ;
874        client->finalize();
875        info(100)<<"DEBUG: context "<<getId()<<" Client finalize sent"<<endl ;
876        while (client->havePendingRequests()) client->checkBuffers();
877        info(100)<<"DEBUG: context "<<getId()<<" no pending request ok"<<endl ;
878        bool notifiedFinalized=false ;
879        do
880        {
881          notifiedFinalized=client->isNotifiedFinalized() ;
882        } while (!notifiedFinalized) ;
883        client->releaseBuffers();
884        info(100)<<"DEBUG: context "<<getId()<<" release client ok"<<endl ;
885      }
886      else if (serviceType_==CServicesManager::GATHERER)
887      {
888         for (int i = 0; i < clientPrimServer.size(); ++i)
889         {
890           clientPrimServer[i]->finalize();
891           bool bufferReleased;
892           do
893           {
894             clientPrimServer[i]->checkBuffers();
895             bufferReleased = !clientPrimServer[i]->havePendingRequests();
896           } while (!bufferReleased);
897           
898           bool notifiedFinalized=false ;
899           do
900           {
901             notifiedFinalized=clientPrimServer[i]->isNotifiedFinalized() ;
902           } while (!notifiedFinalized) ;
903           clientPrimServer[i]->releaseBuffers();
904         }
905         closeAllFile();
906
907      }
908      else if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER)
909      {
910        closeAllFile();
911      }
912
913      freeComms() ;
914       
915      parentServerContext_->freeComm() ;
916      finalized = true;
917      info(20)<<"CContext: Context <"<<getId()<<"> is finalized."<<endl;
918   }
919   CATCH_DUMP_ATTR
920
921   //! Free internally allocated communicators
922   void CContext::freeComms(void)
923   TRY
924   {
925     for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it)
926       MPI_Comm_free(&(*it));
927     comms.clear();
928   }
929   CATCH_DUMP_ATTR
930
931   //! Deallocate buffers allocated by clientContexts
932   void CContext::releaseClientBuffers(void)
933   TRY
934   {
935     client->releaseBuffers();
936     for (int i = 0; i < clientPrimServer.size(); ++i)
937       clientPrimServer[i]->releaseBuffers();
938   }
939   CATCH_DUMP_ATTR
940
941   
942   /*!
943   \brief Close all the context defintion and do processing data
944      After everything is well defined on client side, they will be processed and sent to server
945   From the version 2.0, sever and client work no more on the same database. Moreover, client(s) will send
946   all necessary information to server, from which each server can build its own database.
947   Because the role of server is to write out field data on a specific netcdf file,
948   the only information that it needs is the enabled files
949   and the active fields (fields will be written onto active files)
950   */
951  void CContext::closeDefinition(void)
952   TRY
953   {
954     CTimer::get("Context : close definition").resume() ;
955     
956     // create intercommunicator with servers.
957     // not sure it is the good place to be called here
958     createServerInterComm() ;
959
960
961     // After xml is parsed, there are some more works with post processing
962//     postProcessing();
963
964   
965    // Make sure the calendar was correctly created
966    if (serviceType_!=CServicesManager::CLIENT) CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar();
967    if (!calendar)
968      ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"")
969    else if (calendar->getTimeStep() == NoneDu)
970      ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"")
971    // Calendar first update to set the current date equals to the start date
972    calendar->update(0);
973
974    // Résolution des héritages descendants (càd des héritages de groupes)
975    // pour chacun des contextes.
976    solveDescInheritance(true);
977 
978    // Solve inheritance for field to know if enabled or not.
979    for (auto field : CField::getAll()) field->solveRefInheritance();
980
981    // Check if some axis, domains or grids are eligible to for compressed indexed output.
982    // Warning: This must be done after solving the inheritance and before the rest of post-processing
983    // --> later ????    checkAxisDomainsGridsEligibilityForCompressedOutput();     
984
985      // Check if some automatic time series should be generated
986      // Warning: This must be done after solving the inheritance and before the rest of post-processing     
987
988    // The timeseries should only be prepared in client
989    prepareTimeseries();
990
991    //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
992    findEnabledFiles();
993    findEnabledWriteModeFiles();
994    findEnabledReadModeFiles();
995    findEnabledCouplerIn();
996    findEnabledCouplerOut();
997    createCouplerInterCommunicator() ;
998
999    // Find all enabled fields of each file     
1000    vector<CField*>&& fileOutField = findAllEnabledFieldsInFileOut(this->enabledWriteModeFiles);
1001    vector<CField*>&& fileInField = findAllEnabledFieldsInFileIn(this->enabledReadModeFiles);
1002    vector<CField*>&& couplerOutField = findAllEnabledFieldsCouplerOut(this->enabledCouplerOut);
1003    vector<CField*>&& couplerInField = findAllEnabledFieldsCouplerIn(this->enabledCouplerIn);
1004    findFieldsWithReadAccess();
1005    vector<CField*>& fieldWithReadAccess = fieldsWithReadAccess_ ;
1006    vector<CField*> fieldModelIn ; // fields potentially from model
1007     
1008    // define if files are on clientSied or serverSide
1009    if (serviceType_==CServicesManager::CLIENT)
1010    {
1011      for (auto& file : enabledWriteModeFiles) file->setClientSide() ;
1012      for (auto& file : enabledReadModeFiles) file->setClientSide() ;
1013    }
1014    else
1015    {
1016      for (auto& file : enabledWriteModeFiles) file->setServerSide() ;
1017      for (auto& file : enabledReadModeFiles) file->setServerSide() ;
1018    }
1019
1020   
1021    for (auto& field : couplerInField)
1022    {
1023      field->unsetGridCompleted() ;
1024    }
1025// find all field potentially at workflow end
1026    vector<CField*> endWorkflowFields ;
1027    endWorkflowFields.reserve(fileOutField.size()+couplerOutField.size()+fieldWithReadAccess.size()) ;
1028    endWorkflowFields.insert(endWorkflowFields.end(),fileOutField.begin(), fileOutField.end()) ;
1029    endWorkflowFields.insert(endWorkflowFields.end(),couplerOutField.begin(), couplerOutField.end()) ;
1030    endWorkflowFields.insert(endWorkflowFields.end(),fieldWithReadAccess.begin(), fieldWithReadAccess.end()) ;
1031
1032    bool workflowGraphIsCompleted ;
1033   
1034    bool first=true ;
1035   
1036    do
1037    {
1038      workflowGraphIsCompleted=true; 
1039      for(auto endWorkflowField : endWorkflowFields) 
1040      {
1041        workflowGraphIsCompleted &= endWorkflowField->buildWorkflowGraph(garbageCollector) ;
1042      }
1043   
1044      for(auto couplerIn : enabledCouplerIn) couplerIn->assignContext() ;
1045      for(auto field : couplerInField) field->makeGridAliasForCoupling();
1046      for(auto field : couplerInField) this->sendCouplerInReady(field->getContextClient()) ;
1047   
1048
1049      // assign context to coupler out and related fields
1050      for(auto couplerOut : enabledCouplerOut) couplerOut->assignContext() ;
1051      // for now supose that all coupling out endpoint are succesfull. The difficultie is client/server buffer evaluation
1052      for(auto field : couplerOutField) 
1053      {
1054        // connect to couplerOut -> to do
1055      }
1056      if (first) setClientServerBuffer(couplerOutField, true) ; // set buffer context --> to check
1057
1058      bool couplersReady ;
1059      do 
1060      {
1061        couplersReady=true ;
1062        for(auto field : couplerOutField)
1063        {
1064          bool ready = isCouplerInReady(field->getContextClient()) ; 
1065          if (ready) field->sendFieldToCouplerOut() ;
1066          couplersReady &= ready ;
1067        }
1068        this->scheduledEventLoop() ;
1069
1070      } while (!couplersReady) ;
1071     
1072      first=false ;
1073      this->scheduledEventLoop() ;
1074
1075    } while (!workflowGraphIsCompleted) ;
1076
1077
1078    for( auto field : couplerInField) couplerInFields_.push_back(field) ;
1079
1080    // get all field coming potentially from model
1081    for (auto field : CField::getAll() ) if (field->getModelIn()) fieldModelIn.push_back(field) ;
1082
1083    // Distribute files between secondary servers according to the data size => assign a context to a file and then to fields
1084    if (serviceType_==CServicesManager::GATHERER) distributeFiles(this->enabledWriteModeFiles);
1085    else if (serviceType_==CServicesManager::CLIENT) for(auto file : this->enabledWriteModeFiles) file->setContextClient(client) ;
1086
1087    // client side, assign context for file reading
1088    if (serviceType_==CServicesManager::CLIENT) for(auto file : this->enabledReadModeFiles) file->setContextClient(client) ;
1089   
1090    // server side, assign context where to send file data read
1091    if (serviceType_==CServicesManager::CServicesManager::GATHERER || serviceType_==CServicesManager::IO_SERVER) 
1092      for(auto file : this->enabledReadModeFiles) file->setContextClient(client) ;
1093   
1094    // workflow endpoint => sent to IO/SERVER
1095    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER)
1096    {
1097      for(auto field : fileOutField) 
1098      {
1099        field->connectToFileServer(garbageCollector) ; // connect the field to server filter
1100      }
1101      setClientServerBuffer(fileOutField, true) ; // set buffer context --> to review
1102      for(auto field : fileOutField) field->sendFieldToFileServer() ;
1103    }
1104
1105    // workflow endpoint => write to file
1106    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER)
1107    {
1108      for(auto field : fileOutField) 
1109      {
1110        field->connectToFileWriter(garbageCollector) ; // connect the field to server filter
1111      }
1112    }
1113   
1114    // workflow endpoint => Send data from server to client
1115    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::GATHERER)
1116    {
1117      for(auto field : fileInField) 
1118      {
1119        field->connectToServerToClient(garbageCollector) ;
1120      }
1121    }
1122
1123    // workflow endpoint => sent to model on client side
1124    if (serviceType_==CServicesManager::CLIENT)
1125    {
1126      for(auto field : fieldWithReadAccess) field->connectToModelOutput(garbageCollector) ;
1127    }
1128
1129
1130    // workflow startpoint => data from model
1131    if (serviceType_==CServicesManager::CLIENT)
1132    {
1133      for(auto field : fieldModelIn) 
1134      {
1135        field->connectToModelInput(garbageCollector) ; // connect the field to server filter
1136        // grid index will be computed on the fly
1137      }
1138    }
1139   
1140    // workflow startpoint => data from client on server side
1141    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::GATHERER || serviceType_==CServicesManager::OUT_SERVER)
1142    {
1143      for(auto field : fieldModelIn) 
1144      {
1145        field->connectToClientInput(garbageCollector) ; // connect the field to server filter
1146      }
1147    }
1148
1149   
1150    for(auto field : couplerInField) 
1151    {
1152      field->connectToCouplerIn(garbageCollector) ; // connect the field to server filter
1153    }
1154   
1155   
1156    for(auto field : couplerOutField) 
1157    {
1158      field->connectToCouplerOut(garbageCollector) ; // for now the same kind of filter that for file server
1159    }
1160
1161     // workflow startpoint => data from server on client side
1162    if (serviceType_==CServicesManager::CLIENT)
1163    {
1164      for(auto field : fileInField) 
1165      {
1166        field->sendFieldToInputFileServer() ;
1167        field->connectToServerInput(garbageCollector) ; // connect the field to server filter
1168        fileInFields_.push_back(field) ;
1169      }
1170    }
1171
1172    // workflow startpoint => data read from file on server side
1173    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::GATHERER)
1174    {
1175      for(auto field : fileInField) 
1176      {
1177        field->connectToFileReader(garbageCollector) ;
1178      }
1179    }
1180   
1181    // construct slave server list
1182    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) 
1183    {
1184      for(auto field : fileOutField) slaveServers_.insert(field->getContextClient()) ; 
1185      for(auto field : fileInField)  slaveServers_.insert(field->getContextClient()) ; 
1186    }
1187
1188    for(auto& slaveServer : slaveServers_) sendCloseDefinition(slaveServer) ;
1189
1190    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER) 
1191    {
1192      createFileHeader();
1193    }
1194
1195    if (serviceType_==CServicesManager::CLIENT) startPrefetchingOfEnabledReadModeFiles();
1196   
1197    // send signal to couplerIn context that definition phasis is done
1198
1199    for(auto& couplerInClient : couplerInClient_) sendCouplerInCloseDefinition(couplerInClient.second) ;
1200
1201    // wait until all couplerIn signal that closeDefition is done.
1202    bool ok;
1203    do
1204    {
1205      ok = true ;
1206      for(auto& couplerOutClient : couplerOutClient_) ok &= isCouplerInCloseDefinition(couplerOutClient.second) ;
1207      this->scheduledEventLoop() ;
1208    } while (!ok) ;
1209
1210     CTimer::get("Context : close definition").suspend() ;
1211  }
1212  CATCH_DUMP_ATTR
1213
1214
1215  vector<CField*> CContext::findAllEnabledFieldsInFileOut(const std::vector<CFile*>& activeFiles)
1216   TRY
1217   {
1218     vector<CField*> fields ;
1219     for(auto file : activeFiles)
1220     {
1221        const vector<CField*>&& fieldList=file->getEnabledFields() ;
1222        for(auto field : fieldList) field->setFileOut(file) ;
1223        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
1224     }
1225     return fields ;
1226   }
1227   CATCH_DUMP_ATTR
1228
1229   vector<CField*> CContext::findAllEnabledFieldsInFileIn(const std::vector<CFile*>& activeFiles)
1230   TRY
1231   {
1232     vector<CField*> fields ;
1233     for(auto file : activeFiles)
1234     {
1235        const vector<CField*>&& fieldList=file->getEnabledFields() ;
1236        for(auto field : fieldList) field->setFileIn(file) ;
1237        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
1238     }
1239     return fields ;
1240   }
1241   CATCH_DUMP_ATTR
1242
1243   vector<CField*> CContext::findAllEnabledFieldsCouplerOut(const std::vector<CCouplerOut*>& activeCouplerOut)
1244   TRY
1245   {
1246     vector<CField*> fields ;
1247     for (auto couplerOut :activeCouplerOut)
1248     {
1249        const vector<CField*>&& fieldList=couplerOut->getEnabledFields() ;
1250        for(auto field : fieldList) field->setCouplerOut(couplerOut) ;
1251        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
1252     }
1253     return fields ;
1254   }
1255   CATCH_DUMP_ATTR
1256
1257   vector<CField*> CContext::findAllEnabledFieldsCouplerIn(const std::vector<CCouplerIn*>& activeCouplerIn)
1258   TRY
1259   {
1260     vector<CField*> fields ;
1261     for (auto couplerIn :activeCouplerIn)
1262     {
1263        const vector<CField*>&& fieldList=couplerIn->getEnabledFields() ;
1264        for(auto field : fieldList) field->setCouplerIn(couplerIn) ;
1265        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
1266     }
1267     return fields ;
1268   }
1269   CATCH_DUMP_ATTR
1270
1271 /*!
1272  * Send context attribute and calendar to file server, it must be done once by context file server
1273  * \param[in] client : context client to send   
1274  */ 
1275  void CContext::sendContextToFileServer(CContextClient* client)
1276  {
1277    if (sendToFileServer_done_.count(client)!=0) return ;
1278    else sendToFileServer_done_.insert(client) ;
1279   
1280    this->sendAllAttributesToServer(client); // Send all attributes of current context to server
1281    CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer(client); // Send all attributes of current cale
1282  }
1283
1284 
1285   void CContext::readAttributesOfEnabledFieldsInReadModeFiles()
1286   TRY
1287   {
1288      for (unsigned int i = 0; i < this->enabledReadModeFiles.size(); ++i)
1289        (void)this->enabledReadModeFiles[i]->readAttributesOfEnabledFieldsInReadMode();
1290   }
1291   CATCH_DUMP_ATTR
1292
1293
1294   void CContext::postProcessFilterGraph()
1295   TRY
1296   {
1297     int size = enabledFiles.size();
1298     for (int i = 0; i < size; ++i)
1299     {
1300        enabledFiles[i]->postProcessFilterGraph();
1301     }
1302   }
1303   CATCH_DUMP_ATTR
1304
1305   void CContext::startPrefetchingOfEnabledReadModeFiles()
1306   TRY
1307   {
1308     int size = enabledReadModeFiles.size();
1309     for (int i = 0; i < size; ++i)
1310     {
1311        enabledReadModeFiles[i]->prefetchEnabledReadModeFields();
1312     }
1313   }
1314   CATCH_DUMP_ATTR
1315
1316   void CContext::doPreTimestepOperationsForEnabledReadModeFiles()
1317   TRY
1318   {
1319     int size = enabledReadModeFiles.size();
1320     for (int i = 0; i < size; ++i)
1321     {
1322        enabledReadModeFiles[i]->doPreTimestepOperationsForEnabledReadModeFields();
1323     }
1324   }
1325   CATCH_DUMP_ATTR
1326
1327   void CContext::doPostTimestepOperationsForEnabledReadModeFiles()
1328   TRY
1329   {
1330     int size = enabledReadModeFiles.size();
1331     for (int i = 0; i < size; ++i)
1332     {
1333        enabledReadModeFiles[i]->doPostTimestepOperationsForEnabledReadModeFields();
1334     }
1335   }
1336   CATCH_DUMP_ATTR
1337
1338  void CContext::findFieldsWithReadAccess(void)
1339  TRY
1340  {
1341    fieldsWithReadAccess_.clear();
1342    const vector<CField*> allFields = CField::getAll();
1343    for (size_t i = 0; i < allFields.size(); ++i)
1344    {
1345      CField* field = allFields[i];
1346      if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled))
1347      {
1348        fieldsWithReadAccess_.push_back(field);
1349        field->setModelOut() ;
1350      }
1351    }
1352  }
1353  CATCH_DUMP_ATTR
1354
1355 
1356   void CContext::solveAllInheritance(bool apply)
1357   TRY
1358   {
1359     // Résolution des héritages descendants (càd des héritages de groupes)
1360     // pour chacun des contextes.
1361      solveDescInheritance(apply);
1362
1363     // Résolution des héritages par référence au niveau des fichiers.
1364      const vector<CFile*> allFiles=CFile::getAll();
1365      const vector<CCouplerIn*> allCouplerIn=CCouplerIn::getAll();
1366      const vector<CCouplerOut*> allCouplerOut=CCouplerOut::getAll();
1367      const vector<CGrid*> allGrids= CGrid::getAll();
1368
1369      if (serviceType_==CServicesManager::CLIENT)
1370      {
1371        for (unsigned int i = 0; i < allFiles.size(); i++)
1372          allFiles[i]->solveFieldRefInheritance(apply);
1373
1374        for (unsigned int i = 0; i < allCouplerIn.size(); i++)
1375          allCouplerIn[i]->solveFieldRefInheritance(apply);
1376
1377        for (unsigned int i = 0; i < allCouplerOut.size(); i++)
1378          allCouplerOut[i]->solveFieldRefInheritance(apply);
1379      }
1380
1381      unsigned int vecSize = allGrids.size();
1382      unsigned int i = 0;
1383      for (i = 0; i < vecSize; ++i)
1384        allGrids[i]->solveElementsRefInheritance(apply);
1385
1386   }
1387  CATCH_DUMP_ATTR
1388
1389   void CContext::findEnabledFiles(void)
1390   TRY
1391   {
1392      const std::vector<CFile*> allFiles = CFile::getAll();
1393      const CDate& initDate = calendar->getInitDate();
1394
1395      for (unsigned int i = 0; i < allFiles.size(); i++)
1396         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
1397         {
1398            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
1399            {
1400              if (allFiles[i]->output_freq.isEmpty())
1401              {
1402                 ERROR("CContext::findEnabledFiles()",
1403                     << "Mandatory attribute output_freq must be defined for file \""<<allFiles[i]->getFileOutputName()
1404                     <<" \".")
1405              }
1406              if ((initDate + allFiles[i]->output_freq.getValue()) < (initDate + this->getCalendar()->getTimeStep()))
1407              {
1408                error(0)<<"WARNING: void CContext::findEnabledFiles()"<<endl
1409                    << "Output frequency in file \""<<allFiles[i]->getFileOutputName()
1410                    <<"\" is less than the time step. File will not be written."<<endl;
1411              }
1412              else
1413               enabledFiles.push_back(allFiles[i]);
1414            }
1415         }
1416         else
1417         {
1418           if (allFiles[i]->output_freq.isEmpty())
1419           {
1420              ERROR("CContext::findEnabledFiles()",
1421                  << "Mandatory attribute output_freq must be defined for file \""<<allFiles[i]->getFileOutputName()
1422                  <<" \".")
1423           }
1424           if ( (initDate + allFiles[i]->output_freq.getValue()) < (initDate + this->getCalendar()->getTimeStep()))
1425           {
1426             error(0)<<"WARNING: void CContext::findEnabledFiles()"<<endl
1427                 << "Output frequency in file \""<<allFiles[i]->getFileOutputName()
1428                 <<"\" is less than the time step. File will not be written."<<endl;
1429           }
1430           else
1431             enabledFiles.push_back(allFiles[i]); // otherwise true by default
1432         }
1433
1434      if (enabledFiles.size() == 0)
1435         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
1436               << getId() << "\" !");
1437
1438   }
1439   CATCH_DUMP_ATTR
1440
1441   void CContext::findEnabledCouplerIn(void)
1442   TRY
1443   {
1444      const std::vector<CCouplerIn*> allCouplerIn = CCouplerIn::getAll();
1445      bool enabled ;
1446      for (size_t i = 0; i < allCouplerIn.size(); i++)
1447      {
1448        if (allCouplerIn[i]->enabled.isEmpty()) enabled=true ;
1449        else enabled=allCouplerIn[i]->enabled ;
1450        if (enabled) enabledCouplerIn.push_back(allCouplerIn[i]) ;
1451      }
1452   }
1453   CATCH_DUMP_ATTR
1454
1455   void CContext::findEnabledCouplerOut(void)
1456   TRY
1457   {
1458      const std::vector<CCouplerOut*> allCouplerOut = CCouplerOut::getAll();
1459      bool enabled ;
1460      for (size_t i = 0; i < allCouplerOut.size(); i++)
1461      {
1462        if (allCouplerOut[i]->enabled.isEmpty()) enabled=true ;
1463        else enabled=allCouplerOut[i]->enabled ;
1464        if (enabled) enabledCouplerOut.push_back(allCouplerOut[i]) ;
1465      }
1466   }
1467   CATCH_DUMP_ATTR
1468
1469
1470
1471
1472   void CContext::distributeFiles(const vector<CFile*>& files)
1473   TRY
1474   {
1475     bool distFileMemory=false ;
1476     distFileMemory=CXios::getin<bool>("server2_dist_file_memory", distFileMemory);
1477
1478     if (distFileMemory) distributeFileOverMemoryBandwith(files) ;
1479     else distributeFileOverBandwith(files) ;
1480   }
1481   CATCH_DUMP_ATTR
1482
1483   void CContext::distributeFileOverBandwith(const vector<CFile*>& files)
1484   TRY
1485   {
1486     double eps=std::numeric_limits<double>::epsilon()*10 ;
1487     
1488     std::ofstream ofs(("distribute_file_"+getId()+".dat").c_str(), std::ofstream::out);
1489     int nbPools = clientPrimServer.size();
1490
1491     // (1) Find all enabled files in write mode
1492     // for (int i = 0; i < this->enabledFiles.size(); ++i)
1493     // {
1494     //   if (enabledFiles[i]->mode.isEmpty() || (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write ))
1495     //    enabledWriteModeFiles.push_back(enabledFiles[i]);
1496     // }
1497
1498     // (2) Estimate the data volume for each file
1499     int size = files.size();
1500     std::vector<std::pair<double, CFile*> > dataSizeMap;
1501     double dataPerPool = 0;
1502     int nfield=0 ;
1503     ofs<<size<<endl ;
1504     for (size_t i = 0; i < size; ++i)
1505     {
1506       CFile* file = files[i];
1507       ofs<<file->getId()<<endl ;
1508       StdSize dataSize=0;
1509       std::vector<CField*> enabledFields = file->getEnabledFields();
1510       size_t numEnabledFields = enabledFields.size();
1511       ofs<<numEnabledFields<<endl ;
1512       for (size_t j = 0; j < numEnabledFields; ++j)
1513       {
1514         dataSize += enabledFields[j]->getGlobalWrittenSize() ;
1515         ofs<<enabledFields[j]->getGrid()->getId()<<endl ;
1516         ofs<<enabledFields[j]->getGlobalWrittenSize()<<endl ;
1517       }
1518       double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ;
1519       double dataSizeSec= dataSize/ outFreqSec;
1520       ofs<<dataSizeSec<<endl ;
1521       nfield++ ;
1522// add epsilon*nField to dataSizeSec in order to  preserve reproductive ordering when sorting
1523       dataSizeMap.push_back(make_pair(dataSizeSec + dataSizeSec * eps * nfield , file));
1524       dataPerPool += dataSizeSec;
1525     }
1526     dataPerPool /= nbPools;
1527     std::sort(dataSizeMap.begin(), dataSizeMap.end());
1528
1529     // (3) Assign contextClient to each enabled file
1530
1531     std::multimap<double,int> poolDataSize ;
1532// multimap is not garanty to preserve stable sorting in c++98 but it seems it does for c++11
1533
1534     int j;
1535     double dataSize ;
1536     for (j = 0 ; j < nbPools ; ++j) poolDataSize.insert(std::pair<double,int>(0.,j)) ; 
1537             
1538     for (int i = dataSizeMap.size()-1; i >= 0; --i)
1539     {
1540       dataSize=(*poolDataSize.begin()).first ;
1541       j=(*poolDataSize.begin()).second ;
1542       dataSizeMap[i].second->setContextClient(clientPrimServer[j]);
1543       dataSize+=dataSizeMap[i].first;
1544       poolDataSize.erase(poolDataSize.begin()) ;
1545       poolDataSize.insert(std::pair<double,int>(dataSize,j)) ; 
1546     }
1547
1548     for (std::multimap<double,int>:: iterator it=poolDataSize.begin() ; it!=poolDataSize.end(); ++it) info(30)<<"Load Balancing for servers (perfect=1) : "<<it->second<<" :  ratio "<<it->first*1./dataPerPool<<endl ;
1549   }
1550   CATCH_DUMP_ATTR
1551
1552   void CContext::distributeFileOverMemoryBandwith(const vector<CFile*>& filesList)
1553   TRY
1554   {
1555     int nbPools = clientPrimServer.size();
1556     double ratio=0.5 ;
1557     ratio=CXios::getin<double>("server2_dist_file_memory_ratio", ratio);
1558
1559     int nFiles = filesList.size();
1560     vector<SDistFile> files(nFiles);
1561     vector<SDistGrid> grids;
1562     map<string,int> gridMap ;
1563     string gridId; 
1564     int gridIndex=0 ;
1565
1566     for (size_t i = 0; i < nFiles; ++i)
1567     {
1568       StdSize dataSize=0;
1569       CFile* file = filesList[i];
1570       std::vector<CField*> enabledFields = file->getEnabledFields();
1571       size_t numEnabledFields = enabledFields.size();
1572
1573       files[i].id_=file->getId() ;
1574       files[i].nbGrids_=numEnabledFields;
1575       files[i].assignedGrid_ = new int[files[i].nbGrids_] ;
1576         
1577       for (size_t j = 0; j < numEnabledFields; ++j)
1578       {
1579         gridId=enabledFields[j]->getGrid()->getId() ;
1580         if (gridMap.find(gridId)==gridMap.end())
1581         {
1582            gridMap[gridId]=gridIndex  ;
1583            SDistGrid newGrid; 
1584            grids.push_back(newGrid) ;
1585            gridIndex++ ;
1586         }
1587         files[i].assignedGrid_[j]=gridMap[gridId] ;
1588         grids[files[i].assignedGrid_[j]].size_=enabledFields[j]->getGlobalWrittenSize() ;
1589         dataSize += enabledFields[j]->getGlobalWrittenSize() ; // usefull
1590       }
1591       double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ;
1592       files[i].bandwith_= dataSize/ outFreqSec ;
1593     }
1594
1595     double bandwith=0 ;
1596     double memory=0 ;
1597   
1598     for(int i=0; i<nFiles; i++)  bandwith+=files[i].bandwith_ ;
1599     for(int i=0; i<nFiles; i++)  files[i].bandwith_ = files[i].bandwith_/bandwith * ratio ;
1600
1601     for(int i=0; i<grids.size(); i++)  memory+=grids[i].size_ ;
1602     for(int i=0; i<grids.size(); i++)  grids[i].size_ = grids[i].size_ / memory * (1.0-ratio) ;
1603       
1604     distributeFileOverServer2(nbPools, grids.size(), &grids[0], nFiles, &files[0]) ;
1605
1606     vector<double> memorySize(nbPools,0.) ;
1607     vector< set<int> > serverGrids(nbPools) ;
1608     vector<double> bandwithSize(nbPools,0.) ;
1609       
1610     for (size_t i = 0; i < nFiles; ++i)
1611     {
1612       bandwithSize[files[i].assignedServer_] += files[i].bandwith_* bandwith /ratio ;
1613       for(int j=0 ; j<files[i].nbGrids_;j++)
1614       {
1615         if (serverGrids[files[i].assignedServer_].find(files[i].assignedGrid_[j]) == serverGrids[files[i].assignedServer_].end())
1616         {
1617           memorySize[files[i].assignedServer_]+= grids[files[i].assignedGrid_[j]].size_ * memory / (1.0-ratio);
1618           serverGrids[files[i].assignedServer_].insert(files[i].assignedGrid_[j]) ;
1619         }
1620       }
1621       filesList[i]->setContextClient(clientPrimServer[files[i].assignedServer_]) ;
1622       delete [] files[i].assignedGrid_ ;
1623     }
1624
1625     for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<"   assigned file bandwith "<<bandwithSize[i]*86400.*4./1024/1024.<<" Mb / days"<<endl ;
1626     for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<"   assigned grid memory "<<memorySize[i]*100/1024./1024.<<" Mb"<<endl ;
1627
1628   }
1629   CATCH_DUMP_ATTR
1630
1631   /*!
1632      Find all files in write mode
1633   */
1634   void CContext::findEnabledWriteModeFiles(void)
1635   TRY
1636   {
1637     int size = this->enabledFiles.size();
1638     for (int i = 0; i < size; ++i)
1639     {
1640       if (enabledFiles[i]->mode.isEmpty() || 
1641          (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write ))
1642        enabledWriteModeFiles.push_back(enabledFiles[i]);
1643     }
1644   }
1645   CATCH_DUMP_ATTR
1646
1647   /*!
1648      Find all files in read mode
1649   */
1650   void CContext::findEnabledReadModeFiles(void)
1651   TRY
1652   {
1653     int size = this->enabledFiles.size();
1654     for (int i = 0; i < size; ++i)
1655     {
1656       if (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::read)
1657        enabledReadModeFiles.push_back(enabledFiles[i]);
1658     }
1659   }
1660   CATCH_DUMP_ATTR
1661
1662   void CContext::closeAllFile(void)
1663   TRY
1664   {
1665     std::vector<CFile*>::const_iterator
1666            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
1667
1668     for (; it != end; it++)
1669     {
1670       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
1671       (*it)->close();
1672     }
1673   }
1674   CATCH_DUMP_ATTR
1675
1676   /*!
1677   \brief Dispatch event received from client
1678      Whenever a message is received in buffer of server, it will be processed depending on
1679   its event type. A new event type should be added in the switch list to make sure
1680   it processed on server side.
1681   \param [in] event: Received message
1682   */
1683   bool CContext::dispatchEvent(CEventServer& event)
1684   TRY
1685   {
1686
1687      if (SuperClass::dispatchEvent(event)) return true;
1688      else
1689      {
1690        switch(event.type)
1691        {
1692           case EVENT_ID_CLOSE_DEFINITION :
1693             recvCloseDefinition(event);
1694             return true;
1695             break;
1696           case EVENT_ID_UPDATE_CALENDAR:
1697             recvUpdateCalendar(event);
1698             return true;
1699             break;
1700           case EVENT_ID_CREATE_FILE_HEADER :
1701             recvCreateFileHeader(event);
1702             return true;
1703             break;
1704           case EVENT_ID_SEND_REGISTRY:
1705             recvRegistry(event);
1706             return true;
1707             break;
1708           case EVENT_ID_COUPLER_IN_READY:
1709             recvCouplerInReady(event);
1710             return true;
1711             break;
1712           case EVENT_ID_COUPLER_IN_CLOSE_DEFINITION:
1713             recvCouplerInCloseDefinition(event);
1714             return true;
1715             break;
1716           case EVENT_ID_COUPLER_IN_CONTEXT_FINALIZED:
1717             recvCouplerInContextFinalized(event);
1718             return true;
1719             break; 
1720           default :
1721             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
1722                    <<"Unknown Event");
1723           return false;
1724         }
1725      }
1726   }
1727   CATCH
1728
1729   //! Client side: Send a message to server to make it close
1730   // ym obsolete
1731   void CContext::sendCloseDefinition(void)
1732   TRY
1733   {
1734    int nbSrvPools ;
1735    if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ;
1736    else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ;
1737    else nbSrvPools = 0 ;
1738    CContextClient* contextClientTmp ;
1739
1740    for (int i = 0; i < nbSrvPools; ++i)
1741     {
1742       if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ;
1743       else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ;
1744       CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
1745       if (contextClientTmp->isServerLeader())
1746       {
1747         CMessage msg;
1748         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1749         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1750           event.push(*itRank,1,msg);
1751         contextClientTmp->sendEvent(event);
1752       }
1753       else contextClientTmp->sendEvent(event);
1754     }
1755   }
1756   CATCH_DUMP_ATTR
1757   
1758   //  ! Client side: Send a message to server to make it close
1759   void CContext::sendCloseDefinition(CContextClient* client)
1760   TRY
1761   {
1762      if (sendCloseDefinition_done_.count(client)!=0) return ;
1763      else sendCloseDefinition_done_.insert(client) ;
1764
1765      CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
1766      if (client->isServerLeader())
1767      {
1768        CMessage msg;
1769        for(auto rank : client->getRanksServerLeader()) event.push(rank,1,msg);
1770        client->sendEvent(event);
1771      }
1772     else client->sendEvent(event);
1773   }
1774   CATCH_DUMP_ATTR
1775
1776   //! Server side: Receive a message of client announcing a context close
1777   void CContext::recvCloseDefinition(CEventServer& event)
1778   TRY
1779   {
1780      CBufferIn* buffer=event.subEvents.begin()->buffer;
1781      getCurrent()->closeDefinition();
1782   }
1783   CATCH
1784
1785   //! Client side: Send a message to update calendar in each time step
1786   void CContext::sendUpdateCalendar(int step)
1787   TRY
1788   {
1789     CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR);
1790     for(auto client : slaveServers_) 
1791     {
1792       if (client->isServerLeader())
1793       {
1794         CMessage msg;
1795         msg<<step;
1796         for (auto& rank : client->getRanksServerLeader() ) event.push(rank,1,msg);
1797         client->sendEvent(event);
1798       }
1799       else client->sendEvent(event);
1800     }
1801   }
1802   CATCH_DUMP_ATTR
1803
1804   //! Server side: Receive a message of client annoucing calendar update
1805   void CContext::recvUpdateCalendar(CEventServer& event)
1806   TRY
1807   {
1808      CBufferIn* buffer=event.subEvents.begin()->buffer;
1809      getCurrent()->recvUpdateCalendar(*buffer);
1810   }
1811   CATCH
1812
1813   //! Server side: Receive a message of client annoucing calendar update
1814   void CContext::recvUpdateCalendar(CBufferIn& buffer)
1815   TRY
1816   {
1817      int step;
1818      buffer>>step;
1819      updateCalendar(step);
1820      if (serviceType_==CServicesManager::GATHERER)
1821      {       
1822        sendUpdateCalendar(step);
1823      }
1824   }
1825   CATCH_DUMP_ATTR
1826
1827   //! Client side: Send a message to create header part of netcdf file
1828   void CContext::sendCreateFileHeader(void)
1829   TRY
1830   {
1831     int nbSrvPools ;
1832     if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ;
1833     else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ;
1834     else nbSrvPools = 0 ;
1835     CContextClient* contextClientTmp ;
1836
1837     for (int i = 0; i < nbSrvPools; ++i)
1838     {
1839       if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ;
1840       else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ;
1841       CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER);
1842
1843       if (contextClientTmp->isServerLeader())
1844       {
1845         CMessage msg;
1846         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1847         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1848           event.push(*itRank,1,msg) ;
1849         contextClientTmp->sendEvent(event);
1850       }
1851       else contextClientTmp->sendEvent(event);
1852     }
1853   }
1854   CATCH_DUMP_ATTR
1855
1856   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
1857   void CContext::recvCreateFileHeader(CEventServer& event)
1858   TRY
1859   {
1860      CBufferIn* buffer=event.subEvents.begin()->buffer;
1861      getCurrent()->recvCreateFileHeader(*buffer);
1862   }
1863   CATCH
1864
1865   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
1866   void CContext::recvCreateFileHeader(CBufferIn& buffer)
1867   TRY
1868   {
1869      if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER) 
1870        createFileHeader();
1871   }
1872   CATCH_DUMP_ATTR
1873
1874   void CContext::createCouplerInterCommunicator(void)
1875   TRY
1876   {
1877      int rank=this->getIntraCommRank() ;
1878      map<string,list<CCouplerOut*>> listCouplerOut ; 
1879      map<string,list<CCouplerIn*>> listCouplerIn ; 
1880
1881      for(auto couplerOut : enabledCouplerOut) listCouplerOut[couplerOut->getCouplingContextId()].push_back(couplerOut) ;
1882      for(auto couplerIn : enabledCouplerIn) listCouplerIn[couplerIn->getCouplingContextId()].push_back(couplerIn) ;
1883
1884      CCouplerManager* couplerManager = CXios::getCouplerManager() ;
1885      if (rank==0)
1886      {
1887        for(auto couplerOut : listCouplerOut) couplerManager->registerCoupling(this->getContextId(),couplerOut.first) ;
1888        for(auto couplerIn : listCouplerIn) couplerManager->registerCoupling(couplerIn.first,this->getContextId()) ;
1889      }
1890
1891      do
1892      {
1893        for(auto couplerOut : listCouplerOut) 
1894        {
1895          bool isNextCoupling ;
1896          if (rank==0) isNextCoupling = couplerManager->isNextCoupling(this->getContextId(),couplerOut.first) ;
1897          MPI_Bcast(&isNextCoupling,1,MPI_C_BOOL, 0, getIntraComm()) ; 
1898          if (isNextCoupling) 
1899          {
1900            addCouplingChanel(couplerOut.first, true) ;
1901            listCouplerOut.erase(couplerOut.first) ;
1902            break ;
1903          }           
1904        }
1905        for(auto couplerIn : listCouplerIn) 
1906        {
1907          bool isNextCoupling ;
1908          if (rank==0) isNextCoupling = couplerManager->isNextCoupling(couplerIn.first,this->getContextId());
1909          MPI_Bcast(&isNextCoupling,1,MPI_C_BOOL, 0, getIntraComm()) ; 
1910          if (isNextCoupling) 
1911          {
1912            addCouplingChanel(couplerIn.first, false) ;
1913            listCouplerIn.erase(couplerIn.first) ;
1914            break ;
1915          }           
1916        }
1917
1918      } while (!listCouplerOut.empty() || !listCouplerIn.empty()) ;
1919
1920   }
1921   CATCH_DUMP_ATTR
1922
1923 
1924     //! Client side: Send infomation of active files (files are enabled to write out)
1925   void CContext::sendEnabledFiles(const std::vector<CFile*>& activeFiles)
1926   TRY
1927   {
1928     int size = activeFiles.size();
1929
1930     // In a context, each type has a root definition, e.g: axis, domain, field.
1931     // Every object must be a child of one of these root definition. In this case
1932     // all new file objects created on server must be children of the root "file_definition"
1933     StdString fileDefRoot("file_definition");
1934     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
1935
1936     for (int i = 0; i < size; ++i)
1937     {
1938       CFile* f = activeFiles[i];
1939       cfgrpPtr->sendCreateChild(f->getId(),f->getContextClient());
1940       f->sendAllAttributesToServer(f->getContextClient());
1941       f->sendAddAllVariables(f->getContextClient());
1942     }
1943   }
1944   CATCH_DUMP_ATTR
1945
1946   //! Client side: Send information of active fields (ones are written onto files)
1947   void CContext::sendEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)
1948   TRY
1949   {
1950     int size = activeFiles.size();
1951     for (int i = 0; i < size; ++i)
1952     {
1953       activeFiles[i]->sendEnabledFields(activeFiles[i]->getContextClient());
1954     }
1955   }
1956   CATCH_DUMP_ATTR
1957
1958 
1959   //! Client side: Prepare the timeseries by adding the necessary files
1960   void CContext::prepareTimeseries()
1961   TRY
1962   {
1963     const std::vector<CFile*> allFiles = CFile::getAll();
1964     for (size_t i = 0; i < allFiles.size(); i++)
1965     {
1966       CFile* file = allFiles[i];
1967
1968       std::vector<CVariable*> fileVars, fieldVars, vars = file->getAllVariables();
1969       for (size_t k = 0; k < vars.size(); k++)
1970       {
1971         CVariable* var = vars[k];
1972
1973         if (var->ts_target.isEmpty()
1974              || var->ts_target == CVariable::ts_target_attr::file || var->ts_target == CVariable::ts_target_attr::both)
1975           fileVars.push_back(var);
1976
1977         if (!var->ts_target.isEmpty()
1978              && (var->ts_target == CVariable::ts_target_attr::field || var->ts_target == CVariable::ts_target_attr::both))
1979           fieldVars.push_back(var);
1980       }
1981
1982       if (!file->timeseries.isEmpty() && file->timeseries != CFile::timeseries_attr::none)
1983       {
1984         StdString fileNameStr("%file_name%") ;
1985         StdString tsPrefix = !file->ts_prefix.isEmpty() ? file->ts_prefix : fileNameStr ;
1986         
1987         StdString fileName=file->getFileOutputName();
1988         size_t pos=tsPrefix.find(fileNameStr) ;
1989         while (pos!=std::string::npos)
1990         {
1991           tsPrefix=tsPrefix.replace(pos,fileNameStr.size(),fileName) ;
1992           pos=tsPrefix.find(fileNameStr) ;
1993         }
1994       
1995         const std::vector<CField*> allFields = file->getAllFields();
1996         for (size_t j = 0; j < allFields.size(); j++)
1997         {
1998           CField* field = allFields[j];
1999
2000           if (!field->ts_enabled.isEmpty() && field->ts_enabled)
2001           {
2002             CFile* tsFile = CFile::create();
2003             tsFile->duplicateAttributes(file);
2004
2005             // Add variables originating from file and targeted to timeserie file
2006             for (size_t k = 0; k < fileVars.size(); k++)
2007               tsFile->getVirtualVariableGroup()->addChild(fileVars[k]);
2008
2009           
2010             tsFile->name = tsPrefix + "_";
2011             if (!field->name.isEmpty())
2012               tsFile->name.get() += field->name;
2013             else if (field->hasDirectFieldReference()) // We cannot use getBaseFieldReference() just yet
2014               tsFile->name.get() += field->field_ref;
2015             else
2016               tsFile->name.get() += field->getId();
2017
2018             if (!field->ts_split_freq.isEmpty())
2019               tsFile->split_freq = field->ts_split_freq;
2020
2021             CField* tsField = tsFile->addField();
2022             tsField->field_ref = field->getId();
2023
2024             // Add variables originating from file and targeted to timeserie field
2025             for (size_t k = 0; k < fieldVars.size(); k++)
2026               tsField->getVirtualVariableGroup()->addChild(fieldVars[k]);
2027
2028             vars = field->getAllVariables();
2029             for (size_t k = 0; k < vars.size(); k++)
2030             {
2031               CVariable* var = vars[k];
2032
2033               // Add variables originating from field and targeted to timeserie field
2034               if (var->ts_target.isEmpty()
2035                    || var->ts_target == CVariable::ts_target_attr::field || var->ts_target == CVariable::ts_target_attr::both)
2036                 tsField->getVirtualVariableGroup()->addChild(var);
2037
2038               // Add variables originating from field and targeted to timeserie file
2039               if (!var->ts_target.isEmpty()
2040                    && (var->ts_target == CVariable::ts_target_attr::file || var->ts_target == CVariable::ts_target_attr::both))
2041                 tsFile->getVirtualVariableGroup()->addChild(var);
2042             }
2043
2044             tsFile->solveFieldRefInheritance(true);
2045
2046             if (file->timeseries == CFile::timeseries_attr::exclusive)
2047               field->enabled = false;
2048           }
2049         }
2050
2051         // Finally disable the original file is need be
2052         if (file->timeseries == CFile::timeseries_attr::only)
2053          file->enabled = false;
2054       }
2055     }
2056   }
2057   CATCH_DUMP_ATTR
2058
2059 
2060   //! Client side: Send information of reference domain, axis and scalar of active fields
2061   void CContext::sendRefDomainsAxisScalars(const std::vector<CFile*>& activeFiles)
2062   TRY
2063   {
2064     std::set<pair<StdString,CContextClient*>> domainIds, axisIds, scalarIds;
2065
2066     // Find all reference domain and axis of all active fields
2067     int numEnabledFiles = activeFiles.size();
2068     for (int i = 0; i < numEnabledFiles; ++i)
2069     {
2070       std::vector<CField*> enabledFields = activeFiles[i]->getEnabledFields();
2071       int numEnabledFields = enabledFields.size();
2072       for (int j = 0; j < numEnabledFields; ++j)
2073       {
2074         CContextClient* contextClient=enabledFields[j]->getContextClient() ;
2075         const std::vector<StdString>& prDomAxisScalarId = enabledFields[j]->getRefDomainAxisIds();
2076         if ("" != prDomAxisScalarId[0]) domainIds.insert(make_pair(prDomAxisScalarId[0],contextClient));
2077         if ("" != prDomAxisScalarId[1]) axisIds.insert(make_pair(prDomAxisScalarId[1],contextClient));
2078         if ("" != prDomAxisScalarId[2]) scalarIds.insert(make_pair(prDomAxisScalarId[2],contextClient));
2079       }
2080     }
2081
2082     // Create all reference axis on server side
2083     std::set<StdString>::iterator itDom, itAxis, itScalar;
2084     std::set<StdString>::const_iterator itE;
2085
2086     StdString scalarDefRoot("scalar_definition");
2087     CScalarGroup* scalarPtr = CScalarGroup::get(scalarDefRoot);
2088     
2089     for (auto itScalar = scalarIds.begin(); itScalar != scalarIds.end(); ++itScalar)
2090     {
2091       if (!itScalar->first.empty())
2092       {
2093         scalarPtr->sendCreateChild(itScalar->first,itScalar->second);
2094         CScalar::get(itScalar->first)->sendAllAttributesToServer(itScalar->second);
2095       }
2096     }
2097
2098     StdString axiDefRoot("axis_definition");
2099     CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
2100     
2101     for (auto itAxis = axisIds.begin(); itAxis != axisIds.end(); ++itAxis)
2102     {
2103       if (!itAxis->first.empty())
2104       {
2105         axisPtr->sendCreateChild(itAxis->first, itAxis->second);
2106         CAxis::get(itAxis->first)->sendAllAttributesToServer(itAxis->second);
2107       }
2108     }
2109
2110     // Create all reference domains on server side
2111     StdString domDefRoot("domain_definition");
2112     CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
2113     
2114     for (auto itDom = domainIds.begin(); itDom != domainIds.end(); ++itDom)
2115     {
2116       if (!itDom->first.empty()) {
2117          domPtr->sendCreateChild(itDom->first, itDom->second);
2118          CDomain::get(itDom->first)->sendAllAttributesToServer(itDom->second);
2119       }
2120     }
2121   }
2122   CATCH_DUMP_ATTR
2123
2124   void CContext::triggerLateFields(void)
2125   TRY
2126   {
2127    for(auto& field : fileInFields_) field->triggerLateField() ;
2128    for(auto& field : couplerInFields_) field->triggerLateField() ;
2129   }
2130   CATCH_DUMP_ATTR
2131
2132   //! Update calendar in each time step
2133   void CContext::updateCalendar(int step)
2134   TRY
2135   {
2136      int prevStep = calendar->getStep();
2137
2138      if (prevStep < step)
2139      {
2140        if (serviceType_==CServicesManager::CLIENT) // For now we only use server level 1 to read data
2141        {
2142          triggerLateFields();
2143        }
2144
2145        info(50) << "updateCalendar : before : " << calendar->getCurrentDate() << endl;
2146        calendar->update(step);
2147        info(50) << "updateCalendar : after : " << calendar->getCurrentDate() << endl;
2148  #ifdef XIOS_MEMTRACK_LIGHT
2149        info(50) << " Current memory used by XIOS : "<<  MemTrack::getCurrentMemorySize()*1.0/(1024*1024)<<" Mbyte, at timestep "<<step<<" of context "<<this->getId()<<endl ;
2150  #endif
2151
2152        if (serviceType_==CServicesManager::CLIENT) // For now we only use server level 1 to read data
2153        {
2154          doPostTimestepOperationsForEnabledReadModeFiles();
2155          garbageCollector.invalidate(calendar->getCurrentDate());
2156        }
2157      }
2158      else if (prevStep == step)
2159        info(50) << "updateCalendar: already at step " << step << ", no operation done." << endl;
2160      else // if (prevStep > step)
2161        ERROR("void CContext::updateCalendar(int step)",
2162              << "Illegal calendar update: previous step was " << prevStep << ", new step " << step << "is in the past!")
2163   }
2164   CATCH_DUMP_ATTR
2165
2166   void CContext::initReadFiles(void)
2167   TRY
2168   {
2169      vector<CFile*>::const_iterator it;
2170
2171      for (it=enabledReadModeFiles.begin(); it != enabledReadModeFiles.end(); it++)
2172      {
2173         (*it)->initRead();
2174      }
2175   }
2176   CATCH_DUMP_ATTR
2177
2178   //! Server side: Create header of netcdf file
2179   void CContext::createFileHeader(void)
2180   TRY
2181   {
2182      vector<CFile*>::const_iterator it;
2183
2184      //for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
2185      for (it=enabledWriteModeFiles.begin(); it != enabledWriteModeFiles.end(); it++)
2186      {
2187         (*it)->initWrite();
2188      }
2189   }
2190   CATCH_DUMP_ATTR
2191
2192   //! Get current context
2193   CContext* CContext::getCurrent(void)
2194   TRY
2195   {
2196     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get();
2197   }
2198   CATCH
2199
2200   /*!
2201   \brief Set context with an id be the current context
2202   \param [in] id identity of context to be set to current
2203   */
2204   void CContext::setCurrent(const string& id)
2205   TRY
2206   {
2207     CObjectFactory::SetCurrentContextId(id);
2208     CGroupFactory::SetCurrentContextId(id);
2209   }
2210   CATCH
2211
2212  /*!
2213  \brief Create a context with specific id
2214  \param [in] id identity of new context
2215  \return pointer to the new context or already-existed one with identity id
2216  */
2217  CContext* CContext::create(const StdString& id)
2218  TRY
2219  {
2220    CContext::setCurrent(id);
2221
2222    bool hasctxt = CContext::has(id);
2223    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
2224    getRoot();
2225    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
2226
2227#define DECLARE_NODE(Name_, name_) \
2228    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
2229#define DECLARE_NODE_PAR(Name_, name_)
2230#include "node_type.conf"
2231
2232    return (context);
2233  }
2234  CATCH
2235
2236     //! Server side: Receive a message to do some post processing
2237  void CContext::recvRegistry(CEventServer& event)
2238  TRY
2239  {
2240    CBufferIn* buffer=event.subEvents.begin()->buffer;
2241    getCurrent()->recvRegistry(*buffer);
2242  }
2243  CATCH
2244
2245  void CContext::recvRegistry(CBufferIn& buffer)
2246  TRY
2247  {
2248    if (server->intraCommRank==0)
2249    {
2250      CRegistry registry(server->intraComm) ;
2251      registry.fromBuffer(buffer) ;
2252      registryOut->mergeRegistry(registry) ;
2253    }
2254  }
2255  CATCH_DUMP_ATTR
2256
2257  void CContext::sendRegistry(void)
2258  TRY
2259  {
2260    registryOut->hierarchicalGatherRegistry() ;
2261
2262    int nbSrvPools ;
2263    if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ;
2264    else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ;
2265    else nbSrvPools = 0 ;
2266    CContextClient* contextClientTmp ;
2267
2268    for (int i = 0; i < nbSrvPools; ++i)
2269    {
2270      if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ;
2271      else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ;
2272
2273      CEventClient event(CContext::GetType(), CContext::EVENT_ID_SEND_REGISTRY);
2274      if (contextClientTmp->isServerLeader())
2275      {
2276        CMessage msg ;
2277        if (contextClientTmp->clientRank==0) msg<<*registryOut ;
2278        const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
2279        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
2280             event.push(*itRank,1,msg);
2281        contextClientTmp->sendEvent(event);
2282      }
2283      else contextClientTmp->sendEvent(event);
2284    }
2285  }
2286  CATCH_DUMP_ATTR
2287
2288 
2289  void CContext::sendFinalizeClient(CContextClient* contextClient, const string& contextClientId)
2290  TRY
2291  {
2292    CEventClient event(getType(),EVENT_ID_CONTEXT_FINALIZE_CLIENT);
2293    if (contextClient->isServerLeader())
2294    {
2295      CMessage msg;
2296      msg<<contextClientId ;
2297      const std::list<int>& ranks = contextClient->getRanksServerLeader();
2298      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
2299           event.push(*itRank,1,msg);
2300      contextClient->sendEvent(event);
2301    }
2302    else contextClient->sendEvent(event);
2303  }
2304  CATCH_DUMP_ATTR
2305
2306 
2307  void CContext::recvFinalizeClient(CEventServer& event)
2308  TRY
2309  {
2310    CBufferIn* buffer=event.subEvents.begin()->buffer;
2311    string id;
2312    *buffer>>id;
2313    get(id)->recvFinalizeClient(*buffer);
2314  }
2315  CATCH
2316
2317  void CContext::recvFinalizeClient(CBufferIn& buffer)
2318  TRY
2319  {
2320    countChildContextFinalized_++ ;
2321  }
2322  CATCH_DUMP_ATTR
2323
2324
2325
2326
2327 //! Client side: Send a message  announcing that context can receive grid definition from coupling
2328   void CContext::sendCouplerInReady(CContextClient* client)
2329   TRY
2330   {
2331      if (sendCouplerInReady_done_.count(client)!=0) return ;
2332      else sendCouplerInReady_done_.insert(client) ;
2333
2334      CEventClient event(getType(),EVENT_ID_COUPLER_IN_READY);
2335
2336      if (client->isServerLeader())
2337      {
2338        CMessage msg;
2339        msg<<this->getId();
2340        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
2341        client->sendEvent(event);
2342      }
2343      else client->sendEvent(event);
2344   }
2345   CATCH_DUMP_ATTR
2346
2347   //! Server side: Receive a message announcing that context can send grid definition for context coupling
2348   void CContext::recvCouplerInReady(CEventServer& event)
2349   TRY
2350   {
2351      CBufferIn* buffer=event.subEvents.begin()->buffer;
2352      getCurrent()->recvCouplerInReady(*buffer);
2353   }
2354   CATCH
2355
2356   //! Server side: Receive a message announcing that context can send grid definition for context coupling
2357   void CContext::recvCouplerInReady(CBufferIn& buffer)
2358   TRY
2359   {
2360      string contextId ;
2361      buffer>>contextId;
2362      couplerInReady_.insert(getCouplerOutClient(contextId)) ;
2363   }
2364   CATCH_DUMP_ATTR
2365
2366
2367
2368
2369
2370 //! Client side: Send a message  announcing that a coupling context have done it closeDefinition, so data can be sent now.
2371   void CContext::sendCouplerInCloseDefinition(CContextClient* client)
2372   TRY
2373   {
2374      if (sendCouplerInCloseDefinition_done_.count(client)!=0) return ;
2375      else sendCouplerInCloseDefinition_done_.insert(client) ;
2376
2377      CEventClient event(getType(),EVENT_ID_COUPLER_IN_CLOSE_DEFINITION);
2378
2379      if (client->isServerLeader())
2380      {
2381        CMessage msg;
2382        msg<<this->getId();
2383        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
2384        client->sendEvent(event);
2385      }
2386      else client->sendEvent(event);
2387   }
2388   CATCH_DUMP_ATTR
2389
2390   //! Server side: Receive a message announcing that a coupling context have done it closeDefinition, so data can be sent now.
2391   void CContext::recvCouplerInCloseDefinition(CEventServer& event)
2392   TRY
2393   {
2394      CBufferIn* buffer=event.subEvents.begin()->buffer;
2395      getCurrent()->recvCouplerInCloseDefinition(*buffer);
2396   }
2397   CATCH
2398
2399   //! Server side: Receive a message announcing that a coupling context have done it closeDefinition, so data can be sent now.
2400   void CContext::recvCouplerInCloseDefinition(CBufferIn& buffer)
2401   TRY
2402   {
2403      string contextId ;
2404      buffer>>contextId;
2405      couplerInCloseDefinition_.insert(getCouplerOutClient(contextId)) ;
2406   }
2407   CATCH_DUMP_ATTR
2408
2409
2410
2411
2412//! Client side: Send a message  announcing that a coupling context have done it contextFinalize, so it can also close it own context.
2413   void CContext::sendCouplerInContextFinalized(CContextClient* client)
2414   TRY
2415   {
2416      if (sendCouplerInContextFinalized_done_.count(client)!=0) return ;
2417      else sendCouplerInContextFinalized_done_.insert(client) ;
2418
2419      CEventClient event(getType(),EVENT_ID_COUPLER_IN_CONTEXT_FINALIZED);
2420
2421      if (client->isServerLeader())
2422      {
2423        CMessage msg;
2424        msg<<this->getId();
2425        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
2426        client->sendEvent(event);
2427      }
2428      else client->sendEvent(event);
2429   }
2430   CATCH_DUMP_ATTR
2431
2432   //! Server side: Receive a message announcing that a coupling context have done it contextFinalize, so it can also close it own context.
2433   void CContext::recvCouplerInContextFinalized(CEventServer& event)
2434   TRY
2435   {
2436      CBufferIn* buffer=event.subEvents.begin()->buffer;
2437      getCurrent()->recvCouplerInContextFinalized(*buffer);
2438   }
2439   CATCH
2440
2441   //! Server side: Receive a message announcing that a coupling context have done it contextFinalize, so it can also close it own context.
2442   void CContext::recvCouplerInContextFinalized(CBufferIn& buffer)
2443   TRY
2444   {
2445      string contextId ;
2446      buffer>>contextId;
2447      couplerInContextFinalized_.insert(getCouplerOutClient(contextId)) ;
2448   }
2449   CATCH_DUMP_ATTR
2450
2451
2452
2453
2454  /*!
2455  * \fn bool CContext::isFinalized(void)
2456  * Context is finalized if it received context post finalize event.
2457  */
2458  bool CContext::isFinalized(void)
2459  TRY
2460  {
2461    return finalized;
2462  }
2463  CATCH_DUMP_ATTR
2464  ///--------------------------------------------------------------
2465  StdString CContext::dumpClassAttributes(void)
2466  {
2467    StdString str;
2468    str.append("enabled files=\"");
2469    int size = this->enabledFiles.size();
2470    for (int i = 0; i < size; ++i)
2471    {
2472      str.append(enabledFiles[i]->getId());
2473      str.append(" ");
2474    }
2475    str.append("\"");
2476    return str;
2477  }
2478
2479} // namespace xios
Note: See TracBrowser for help on using the repository browser.