source: XIOS/dev/dev_trunk_graph/src/node/context.cpp @ 2027

Last change on this file since 2027 was 2027, checked in by yushan, 9 months ago

Graph intermediate commit to a tmp branch. Integrate latest modifications of branch coupling

  • 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.7 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   void CContext::initEventScheduler(void)
76   {
77     SRegisterContextInfo contextInfo ;
78     CXios::getContextsManager()->getContextInfo(this->getId(), contextInfo, getIntraComm()) ;
79
80     eventScheduler_=CXios::getPoolRessource()->getService(contextInfo.serviceId,contextInfo.partitionId)->getEventScheduler() ;
81 
82     // generate unique hash for server
83     auto time=chrono::system_clock::now().time_since_epoch().count() ;
84     std::default_random_engine rd(time); // not reproducible from a run to another
85     std::uniform_int_distribution<size_t> dist;
86     hashId_=dist(rd) ;
87     MPI_Bcast(&hashId_,1,MPI_SIZE_T,0,getIntraComm()) ; // Bcast to all server of the context
88   }
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   
719  bool CContext::eventLoop(bool enableEventsProcessing)
720  {
721    bool finished=true; 
722    bool out; 
723    size_t timeLine=timeLine_ ;
724    if (serviceType_==CServicesManager::CLIENT)
725    {
726      timeLine_++ ;
727      eventScheduler_->registerEvent(timeLine, hashId_) ;
728    }
729
730    do
731    { 
732      if (client!=nullptr && !finalized) client->checkBuffers();
733   
734      for (int i = 0; i < clientPrimServer.size(); ++i)
735      {
736        if (!finalized) clientPrimServer[i]->checkBuffers();
737        if (!finalized) finished &= serverPrimServer[i]->eventLoop(enableEventsProcessing);
738      }
739
740      for (auto couplerOut : couplerOutClient_)
741        if (!finalized) couplerOut.second->checkBuffers();
742   
743      for (auto couplerIn : couplerInClient_)
744        if (!finalized) couplerIn.second->checkBuffers();
745   
746      for (auto couplerOut : couplerOutServer_)
747        if (!finalized) couplerOut.second->eventLoop(enableEventsProcessing);
748
749      for (auto couplerIn : couplerInServer_)
750        if (!finalized) couplerIn.second->eventLoop(enableEventsProcessing);
751   
752      if (server!=nullptr) if (!finalized) finished &= server->eventLoop(enableEventsProcessing);
753 
754      if (serviceType_==CServicesManager::CLIENT) out = eventScheduler_->queryEvent(timeLine,hashId_) ;
755      else out=true ;
756    }  while(!out) ;
757    return finalized && finished ;
758  }
759
760  void CContext::addCouplingChanel(const std::string& fullContextId, bool out)
761  {
762     int contextLeader ;
763     
764     if (out)
765     { 
766       if (couplerOutClient_.find(fullContextId)==couplerOutClient_.end()) 
767       {
768         bool ok=CXios::getContextsManager()->getContextLeader(fullContextId, contextLeader, getIntraComm()) ;
769     
770         MPI_Comm interComm, interCommClient, interCommServer  ;
771         MPI_Comm intraCommClient, intraCommServer ;
772
773         if (ok) MPI_Intercomm_create(getIntraComm(), 0, CXios::getXiosComm(), contextLeader, 0, &interComm) ;
774
775        MPI_Comm_dup(intraComm_, &intraCommClient) ;
776        MPI_Comm_dup(intraComm_, &intraCommServer) ;
777        MPI_Comm_dup(interComm, &interCommClient) ;
778        MPI_Comm_dup(interComm, &interCommServer) ;
779        CContextClient* client = new CContextClient(this, intraCommClient, interCommClient);
780        CContextServer* server = new CContextServer(this, intraCommServer, interCommServer);
781        client->setAssociatedServer(server) ;
782        server->setAssociatedClient(client) ;
783        MPI_Comm_free(&interComm) ;
784        couplerOutClient_[fullContextId] = client ;
785        couplerOutServer_[fullContextId] = server ;
786
787/*
788      // for now, we don't now which beffer size must be used for client coupler
789      // It will be evaluated later. Fix a constant size for now...
790      // set to 10Mb for development
791       map<int,size_t> bufferSize, maxEventSize ;
792       for(int i=0;i<client->getRemoteSize();i++)
793       {
794         bufferSize[i]=10000000 ;
795         maxEventSize[i]=10000000 ;
796       }
797
798       client->setBufferSize(bufferSize, maxEventSize);   
799*/
800      }
801    }
802    else if (couplerInClient_.find(fullContextId)==couplerInClient_.end())
803    {
804      bool ok=CXios::getContextsManager()->getContextLeader(fullContextId, contextLeader, getIntraComm()) ;
805     
806       MPI_Comm interComm, interCommClient, interCommServer  ;
807       MPI_Comm intraCommClient, intraCommServer ;
808
809       if (ok) MPI_Intercomm_create(getIntraComm(), 0, CXios::getXiosComm(), contextLeader, 0, &interComm) ;
810
811       MPI_Comm_dup(intraComm_, &intraCommClient) ;
812       MPI_Comm_dup(intraComm_, &intraCommServer) ;
813       MPI_Comm_dup(interComm, &interCommServer) ;
814       MPI_Comm_dup(interComm, &interCommClient) ;
815       CContextServer* server = new CContextServer(this, intraCommServer, interCommServer);
816       CContextClient* client = new CContextClient(this, intraCommClient, interCommClient);
817       client->setAssociatedServer(server) ;
818       server->setAssociatedClient(client) ;
819       MPI_Comm_free(&interComm) ;
820
821       map<int,size_t> bufferSize, maxEventSize ;
822       for(int i=0;i<client->getRemoteSize();i++)
823       {
824         bufferSize[i]=10000000 ;
825         maxEventSize[i]=10000000 ;
826       }
827
828       client->setBufferSize(bufferSize, maxEventSize);   
829       couplerInClient_[fullContextId] = client ;
830       couplerInServer_[fullContextId] = server ;       
831    }
832  }
833 
834  void CContext::globalEventLoop(void)
835  {
836    CXios::getDaemonsManager()->eventLoop() ;
837    setCurrent(getId()) ;
838  }
839
840
841   void CContext::finalize(void)
842   TRY
843   {
844      registryOut->hierarchicalGatherRegistry() ;
845      if (server->intraCommRank==0) CXios::globalRegistry->mergeRegistry(*registryOut) ;
846
847      if (serviceType_==CServicesManager::CLIENT)
848      {
849//ym        doPreTimestepOperationsForEnabledReadModeFiles(); // For now we only use server level 1 to read data
850
851        triggerLateFields() ;
852
853        // inform couplerIn that I am finished
854        for(auto& couplerInClient : couplerInClient_) sendCouplerInContextFinalized(couplerInClient.second) ;
855
856        // wait until received message from couplerOut that they have finished
857        bool couplersInFinalized ;
858        do
859        {
860          couplersInFinalized=true ;
861          for(auto& couplerOutClient : couplerOutClient_) couplersInFinalized &= isCouplerInContextFinalized(couplerOutClient.second) ; 
862          globalEventLoop() ;
863        } while (!couplersInFinalized) ;
864
865        info(100)<<"DEBUG: context "<<getId()<<" Send client finalize"<<endl ;
866        client->finalize();
867        info(100)<<"DEBUG: context "<<getId()<<" Client finalize sent"<<endl ;
868        while (client->havePendingRequests()) client->checkBuffers();
869        info(100)<<"DEBUG: context "<<getId()<<" no pending request ok"<<endl ;
870        bool notifiedFinalized=false ;
871        do
872        {
873          notifiedFinalized=client->isNotifiedFinalized() ;
874        } while (!notifiedFinalized) ;
875        client->releaseBuffers();
876        info(100)<<"DEBUG: context "<<getId()<<" release client ok"<<endl ;
877      }
878      else if (serviceType_==CServicesManager::GATHERER)
879      {
880         for (int i = 0; i < clientPrimServer.size(); ++i)
881         {
882           clientPrimServer[i]->finalize();
883           bool bufferReleased;
884           do
885           {
886             clientPrimServer[i]->checkBuffers();
887             bufferReleased = !clientPrimServer[i]->havePendingRequests();
888           } while (!bufferReleased);
889           
890           bool notifiedFinalized=false ;
891           do
892           {
893             notifiedFinalized=clientPrimServer[i]->isNotifiedFinalized() ;
894           } while (!notifiedFinalized) ;
895           clientPrimServer[i]->releaseBuffers();
896         }
897         closeAllFile();
898
899      }
900      else if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER)
901      {
902        closeAllFile();
903      }
904
905      freeComms() ;
906       
907      parentServerContext_->freeComm() ;
908      finalized = true;
909      info(20)<<"CContext: Context <"<<getId()<<"> is finalized."<<endl;
910   }
911   CATCH_DUMP_ATTR
912
913   //! Free internally allocated communicators
914   void CContext::freeComms(void)
915   TRY
916   {
917     for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it)
918       MPI_Comm_free(&(*it));
919     comms.clear();
920   }
921   CATCH_DUMP_ATTR
922
923   //! Deallocate buffers allocated by clientContexts
924   void CContext::releaseClientBuffers(void)
925   TRY
926   {
927     client->releaseBuffers();
928     for (int i = 0; i < clientPrimServer.size(); ++i)
929       clientPrimServer[i]->releaseBuffers();
930   }
931   CATCH_DUMP_ATTR
932
933   
934   /*!
935   \brief Close all the context defintion and do processing data
936      After everything is well defined on client side, they will be processed and sent to server
937   From the version 2.0, sever and client work no more on the same database. Moreover, client(s) will send
938   all necessary information to server, from which each server can build its own database.
939   Because the role of server is to write out field data on a specific netcdf file,
940   the only information that it needs is the enabled files
941   and the active fields (fields will be written onto active files)
942   */
943  void CContext::closeDefinition(void)
944   TRY
945   {
946     CTimer::get("Context : close definition").resume() ;
947     
948     // create intercommunicator with servers.
949     // not sure it is the good place to be called here
950     createServerInterComm() ;
951
952
953     // After xml is parsed, there are some more works with post processing
954//     postProcessing();
955
956   
957    // Make sure the calendar was correctly created
958    if (serviceType_!=CServicesManager::CLIENT) CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar();
959    if (!calendar)
960      ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"")
961    else if (calendar->getTimeStep() == NoneDu)
962      ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"")
963    // Calendar first update to set the current date equals to the start date
964    calendar->update(0);
965
966    // Résolution des héritages descendants (càd des héritages de groupes)
967    // pour chacun des contextes.
968    solveDescInheritance(true);
969 
970    // Solve inheritance for field to know if enabled or not.
971    for (auto field : CField::getAll()) field->solveRefInheritance();
972
973    // Check if some axis, domains or grids are eligible to for compressed indexed output.
974    // Warning: This must be done after solving the inheritance and before the rest of post-processing
975    // --> later ????    checkAxisDomainsGridsEligibilityForCompressedOutput();     
976
977      // Check if some automatic time series should be generated
978      // Warning: This must be done after solving the inheritance and before the rest of post-processing     
979
980    // The timeseries should only be prepared in client
981    prepareTimeseries();
982
983    //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
984    findEnabledFiles();
985    findEnabledWriteModeFiles();
986    findEnabledReadModeFiles();
987    findEnabledCouplerIn();
988    findEnabledCouplerOut();
989    createCouplerInterCommunicator() ;
990
991    // Find all enabled fields of each file     
992    vector<CField*>&& fileOutField = findAllEnabledFieldsInFileOut(this->enabledWriteModeFiles);
993    vector<CField*>&& fileInField = findAllEnabledFieldsInFileIn(this->enabledReadModeFiles);
994    vector<CField*>&& couplerOutField = findAllEnabledFieldsCouplerOut(this->enabledCouplerOut);
995    vector<CField*>&& couplerInField = findAllEnabledFieldsCouplerIn(this->enabledCouplerIn);
996    findFieldsWithReadAccess();
997    vector<CField*>& fieldWithReadAccess = fieldsWithReadAccess_ ;
998    vector<CField*> fieldModelIn ; // fields potentially from model
999     
1000    // define if files are on clientSied or serverSide
1001    if (serviceType_==CServicesManager::CLIENT)
1002    {
1003      for (auto& file : enabledWriteModeFiles) file->setClientSide() ;
1004      for (auto& file : enabledReadModeFiles) file->setClientSide() ;
1005    }
1006    else
1007    {
1008      for (auto& file : enabledWriteModeFiles) file->setServerSide() ;
1009      for (auto& file : enabledReadModeFiles) file->setServerSide() ;
1010    }
1011
1012   
1013    for (auto& field : couplerInField)
1014    {
1015      field->unsetGridCompleted() ;
1016    }
1017// find all field potentially at workflow end
1018    vector<CField*> endWorkflowFields ;
1019    endWorkflowFields.reserve(fileOutField.size()+couplerOutField.size()+fieldWithReadAccess.size()) ;
1020    endWorkflowFields.insert(endWorkflowFields.end(),fileOutField.begin(), fileOutField.end()) ;
1021    endWorkflowFields.insert(endWorkflowFields.end(),couplerOutField.begin(), couplerOutField.end()) ;
1022    endWorkflowFields.insert(endWorkflowFields.end(),fieldWithReadAccess.begin(), fieldWithReadAccess.end()) ;
1023
1024    bool workflowGraphIsCompleted ;
1025
1026    bool first=true ;
1027    do
1028    {
1029      workflowGraphIsCompleted=true; 
1030      for(auto endWorkflowField : endWorkflowFields) 
1031      {
1032        workflowGraphIsCompleted &= endWorkflowField->buildWorkflowGraph(garbageCollector) ;
1033      }
1034
1035      for(auto couplerIn : enabledCouplerIn) couplerIn->assignContext() ;
1036      for(auto field : couplerInField) field->makeGridAliasForCoupling();
1037      for(auto field : couplerInField) this->sendCouplerInReady(field->getContextClient()) ;
1038   
1039
1040      // assign context to coupler out and related fields
1041      for(auto couplerOut : enabledCouplerOut) couplerOut->assignContext() ;
1042      // for now supose that all coupling out endpoint are succesfull. The difficultie is client/server buffer evaluation
1043      for(auto field : couplerOutField) 
1044      {
1045        // connect to couplerOut -> to do
1046      }
1047      if (first) setClientServerBuffer(couplerOutField, true) ; // set buffer context --> to check
1048   
1049      bool couplersReady ;
1050      do 
1051      {
1052        couplersReady=true ;
1053        for(auto field : couplerOutField)
1054        {
1055          bool ready = isCouplerInReady(field->getContextClient()) ; 
1056          if (ready) field->sendFieldToCouplerOut() ;
1057          couplersReady &= ready ;
1058        }
1059        this->eventLoop() ;
1060      } while (!couplersReady) ;
1061
1062      first=false ;
1063      this->eventLoop() ;
1064    } while (!workflowGraphIsCompleted) ;
1065
1066    for( auto field : couplerInField) couplerInFields_.push_back(field) ;
1067
1068    // get all field coming potentially from model
1069    for (auto field : CField::getAll() ) if (field->getModelIn()) fieldModelIn.push_back(field) ;
1070
1071    // Distribute files between secondary servers according to the data size => assign a context to a file and then to fields
1072    if (serviceType_==CServicesManager::GATHERER) distributeFiles(this->enabledWriteModeFiles);
1073    else if (serviceType_==CServicesManager::CLIENT) for(auto file : this->enabledWriteModeFiles) file->setContextClient(client) ;
1074
1075    // client side, assign context for file reading
1076    if (serviceType_==CServicesManager::CLIENT) for(auto file : this->enabledReadModeFiles) file->setContextClient(client) ;
1077   
1078    // server side, assign context where to send file data read
1079    if (serviceType_==CServicesManager::CServicesManager::GATHERER || serviceType_==CServicesManager::IO_SERVER) 
1080      for(auto file : this->enabledReadModeFiles) file->setContextClient(client) ;
1081   
1082    // workflow endpoint => sent to IO/SERVER
1083    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER)
1084    {
1085      for(auto field : fileOutField) 
1086      {
1087        field->connectToFileServer(garbageCollector) ; // connect the field to server filter
1088      }
1089      setClientServerBuffer(fileOutField, true) ; // set buffer context --> to review
1090      for(auto field : fileOutField) field->sendFieldToFileServer() ;
1091    }
1092
1093    // workflow endpoint => write to file
1094    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER)
1095    {
1096      for(auto field : fileOutField) 
1097      {
1098        field->connectToFileWriter(garbageCollector) ; // connect the field to server filter
1099      }
1100    }
1101   
1102    // workflow endpoint => Send data from server to client
1103    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::GATHERER)
1104    {
1105      for(auto field : fileInField) 
1106      {
1107        field->connectToServerToClient(garbageCollector) ;
1108      }
1109    }
1110
1111    // workflow endpoint => sent to model on client side
1112    if (serviceType_==CServicesManager::CLIENT)
1113    {
1114      for(auto field : fieldWithReadAccess) field->connectToModelOutput(garbageCollector) ;
1115    }
1116
1117
1118    // workflow startpoint => data from model
1119    if (serviceType_==CServicesManager::CLIENT)
1120    {
1121      for(auto field : fieldModelIn) 
1122      {
1123        field->connectToModelInput(garbageCollector) ; // connect the field to server filter
1124        // grid index will be computed on the fly
1125      }
1126    }
1127   
1128    // workflow startpoint => data from client on server side
1129    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::GATHERER || serviceType_==CServicesManager::OUT_SERVER)
1130    {
1131      for(auto field : fieldModelIn) 
1132      {
1133        field->connectToClientInput(garbageCollector) ; // connect the field to server filter
1134      }
1135    }
1136
1137   
1138    for(auto field : couplerInField) 
1139    {
1140      field->connectToCouplerIn(garbageCollector) ; // connect the field to server filter
1141    }
1142   
1143   
1144    for(auto field : couplerOutField) 
1145    {
1146      field->connectToCouplerOut(garbageCollector) ; // for now the same kind of filter that for file server
1147    }
1148
1149     // workflow startpoint => data from server on client side
1150    if (serviceType_==CServicesManager::CLIENT)
1151    {
1152      for(auto field : fileInField) 
1153      {
1154        field->sendFieldToInputFileServer() ;
1155        field->connectToServerInput(garbageCollector) ; // connect the field to server filter
1156        fileInFields_.push_back(field) ;
1157      }
1158    }
1159
1160    // workflow startpoint => data read from file on server side
1161    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::GATHERER)
1162    {
1163      for(auto field : fileInField) 
1164      {
1165        field->connectToFileReader(garbageCollector) ;
1166      }
1167    }
1168   
1169    // construct slave server list
1170    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) 
1171    {
1172      for(auto field : fileOutField) slaveServers_.insert(field->getContextClient()) ; 
1173      for(auto field : fileInField)  slaveServers_.insert(field->getContextClient()) ; 
1174    }
1175
1176    for(auto& slaveServer : slaveServers_) sendCloseDefinition(slaveServer) ;
1177
1178    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER) 
1179    {
1180      createFileHeader();
1181    }
1182
1183    if (serviceType_==CServicesManager::CLIENT) startPrefetchingOfEnabledReadModeFiles();
1184   
1185    // send signal to couplerIn context that definition phasis is done
1186
1187    for(auto& couplerInClient : couplerInClient_) sendCouplerInCloseDefinition(couplerInClient.second) ;
1188
1189    // wait until all couplerIn signal that closeDefition is done.
1190    bool ok;
1191    do
1192    {
1193      ok = true ;
1194      for(auto& couplerOutClient : couplerOutClient_) ok &= isCouplerInCloseDefinition(couplerOutClient.second) ;
1195      this->eventLoop() ; 
1196    } while (!ok) ;
1197
1198     CTimer::get("Context : close definition").suspend() ;
1199  }
1200  CATCH_DUMP_ATTR
1201
1202
1203  vector<CField*> CContext::findAllEnabledFieldsInFileOut(const std::vector<CFile*>& activeFiles)
1204   TRY
1205   {
1206     vector<CField*> fields ;
1207     for(auto file : activeFiles)
1208     {
1209        const vector<CField*>&& fieldList=file->getEnabledFields() ;
1210        for(auto field : fieldList) field->setFileOut(file) ;
1211        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
1212     }
1213     return fields ;
1214   }
1215   CATCH_DUMP_ATTR
1216
1217   vector<CField*> CContext::findAllEnabledFieldsInFileIn(const std::vector<CFile*>& activeFiles)
1218   TRY
1219   {
1220     vector<CField*> fields ;
1221     for(auto file : activeFiles)
1222     {
1223        const vector<CField*>&& fieldList=file->getEnabledFields() ;
1224        for(auto field : fieldList) field->setFileIn(file) ;
1225        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
1226     }
1227     return fields ;
1228   }
1229   CATCH_DUMP_ATTR
1230
1231   vector<CField*> CContext::findAllEnabledFieldsCouplerOut(const std::vector<CCouplerOut*>& activeCouplerOut)
1232   TRY
1233   {
1234     vector<CField*> fields ;
1235     for (auto couplerOut :activeCouplerOut)
1236     {
1237        const vector<CField*>&& fieldList=couplerOut->getEnabledFields() ;
1238        for(auto field : fieldList) field->setCouplerOut(couplerOut) ;
1239        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
1240     }
1241     return fields ;
1242   }
1243   CATCH_DUMP_ATTR
1244
1245   vector<CField*> CContext::findAllEnabledFieldsCouplerIn(const std::vector<CCouplerIn*>& activeCouplerIn)
1246   TRY
1247   {
1248     vector<CField*> fields ;
1249     for (auto couplerIn :activeCouplerIn)
1250     {
1251        const vector<CField*>&& fieldList=couplerIn->getEnabledFields() ;
1252        for(auto field : fieldList) field->setCouplerIn(couplerIn) ;
1253        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
1254     }
1255     return fields ;
1256   }
1257   CATCH_DUMP_ATTR
1258
1259 /*!
1260  * Send context attribute and calendar to file server, it must be done once by context file server
1261  * \param[in] client : context client to send   
1262  */ 
1263  void CContext::sendContextToFileServer(CContextClient* client)
1264  {
1265    if (sendToFileServer_done_.count(client)!=0) return ;
1266    else sendToFileServer_done_.insert(client) ;
1267   
1268    this->sendAllAttributesToServer(client); // Send all attributes of current context to server
1269    CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer(client); // Send all attributes of current cale
1270  }
1271
1272 
1273   void CContext::readAttributesOfEnabledFieldsInReadModeFiles()
1274   TRY
1275   {
1276      for (unsigned int i = 0; i < this->enabledReadModeFiles.size(); ++i)
1277        (void)this->enabledReadModeFiles[i]->readAttributesOfEnabledFieldsInReadMode();
1278   }
1279   CATCH_DUMP_ATTR
1280
1281
1282   void CContext::postProcessFilterGraph()
1283   TRY
1284   {
1285     int size = enabledFiles.size();
1286     for (int i = 0; i < size; ++i)
1287     {
1288        enabledFiles[i]->postProcessFilterGraph();
1289     }
1290   }
1291   CATCH_DUMP_ATTR
1292
1293   void CContext::startPrefetchingOfEnabledReadModeFiles()
1294   TRY
1295   {
1296     int size = enabledReadModeFiles.size();
1297     for (int i = 0; i < size; ++i)
1298     {
1299        enabledReadModeFiles[i]->prefetchEnabledReadModeFields();
1300     }
1301   }
1302   CATCH_DUMP_ATTR
1303
1304   void CContext::doPreTimestepOperationsForEnabledReadModeFiles()
1305   TRY
1306   {
1307     int size = enabledReadModeFiles.size();
1308     for (int i = 0; i < size; ++i)
1309     {
1310        enabledReadModeFiles[i]->doPreTimestepOperationsForEnabledReadModeFields();
1311     }
1312   }
1313   CATCH_DUMP_ATTR
1314
1315   void CContext::doPostTimestepOperationsForEnabledReadModeFiles()
1316   TRY
1317   {
1318     int size = enabledReadModeFiles.size();
1319     for (int i = 0; i < size; ++i)
1320     {
1321        enabledReadModeFiles[i]->doPostTimestepOperationsForEnabledReadModeFields();
1322     }
1323   }
1324   CATCH_DUMP_ATTR
1325
1326  void CContext::findFieldsWithReadAccess(void)
1327  TRY
1328  {
1329    fieldsWithReadAccess_.clear();
1330    const vector<CField*> allFields = CField::getAll();
1331    for (size_t i = 0; i < allFields.size(); ++i)
1332    {
1333      CField* field = allFields[i];
1334      if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled))
1335      {
1336        fieldsWithReadAccess_.push_back(field);
1337        field->setModelOut() ;
1338      }
1339    }
1340  }
1341  CATCH_DUMP_ATTR
1342
1343 
1344   void CContext::solveAllInheritance(bool apply)
1345   TRY
1346   {
1347     // Résolution des héritages descendants (càd des héritages de groupes)
1348     // pour chacun des contextes.
1349      solveDescInheritance(apply);
1350
1351     // Résolution des héritages par référence au niveau des fichiers.
1352      const vector<CFile*> allFiles=CFile::getAll();
1353      const vector<CCouplerIn*> allCouplerIn=CCouplerIn::getAll();
1354      const vector<CCouplerOut*> allCouplerOut=CCouplerOut::getAll();
1355      const vector<CGrid*> allGrids= CGrid::getAll();
1356
1357      if (serviceType_==CServicesManager::CLIENT)
1358      {
1359        for (unsigned int i = 0; i < allFiles.size(); i++)
1360          allFiles[i]->solveFieldRefInheritance(apply);
1361
1362        for (unsigned int i = 0; i < allCouplerIn.size(); i++)
1363          allCouplerIn[i]->solveFieldRefInheritance(apply);
1364
1365        for (unsigned int i = 0; i < allCouplerOut.size(); i++)
1366          allCouplerOut[i]->solveFieldRefInheritance(apply);
1367      }
1368
1369      unsigned int vecSize = allGrids.size();
1370      unsigned int i = 0;
1371      for (i = 0; i < vecSize; ++i)
1372        allGrids[i]->solveElementsRefInheritance(apply);
1373
1374   }
1375  CATCH_DUMP_ATTR
1376
1377   void CContext::findEnabledFiles(void)
1378   TRY
1379   {
1380      const std::vector<CFile*> allFiles = CFile::getAll();
1381      const CDate& initDate = calendar->getInitDate();
1382
1383      for (unsigned int i = 0; i < allFiles.size(); i++)
1384         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
1385         {
1386            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
1387            {
1388              if (allFiles[i]->output_freq.isEmpty())
1389              {
1390                 ERROR("CContext::findEnabledFiles()",
1391                     << "Mandatory attribute output_freq must be defined for file \""<<allFiles[i]->getFileOutputName()
1392                     <<" \".")
1393              }
1394              if ((initDate + allFiles[i]->output_freq.getValue()) < (initDate + this->getCalendar()->getTimeStep()))
1395              {
1396                error(0)<<"WARNING: void CContext::findEnabledFiles()"<<endl
1397                    << "Output frequency in file \""<<allFiles[i]->getFileOutputName()
1398                    <<"\" is less than the time step. File will not be written."<<endl;
1399              }
1400              else
1401               enabledFiles.push_back(allFiles[i]);
1402            }
1403         }
1404         else
1405         {
1406           if (allFiles[i]->output_freq.isEmpty())
1407           {
1408              ERROR("CContext::findEnabledFiles()",
1409                  << "Mandatory attribute output_freq must be defined for file \""<<allFiles[i]->getFileOutputName()
1410                  <<" \".")
1411           }
1412           if ( (initDate + allFiles[i]->output_freq.getValue()) < (initDate + this->getCalendar()->getTimeStep()))
1413           {
1414             error(0)<<"WARNING: void CContext::findEnabledFiles()"<<endl
1415                 << "Output frequency in file \""<<allFiles[i]->getFileOutputName()
1416                 <<"\" is less than the time step. File will not be written."<<endl;
1417           }
1418           else
1419             enabledFiles.push_back(allFiles[i]); // otherwise true by default
1420         }
1421
1422      if (enabledFiles.size() == 0)
1423         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
1424               << getId() << "\" !");
1425
1426   }
1427   CATCH_DUMP_ATTR
1428
1429   void CContext::findEnabledCouplerIn(void)
1430   TRY
1431   {
1432      const std::vector<CCouplerIn*> allCouplerIn = CCouplerIn::getAll();
1433      bool enabled ;
1434      for (size_t i = 0; i < allCouplerIn.size(); i++)
1435      {
1436        if (allCouplerIn[i]->enabled.isEmpty()) enabled=true ;
1437        else enabled=allCouplerIn[i]->enabled ;
1438        if (enabled) enabledCouplerIn.push_back(allCouplerIn[i]) ;
1439      }
1440   }
1441   CATCH_DUMP_ATTR
1442
1443   void CContext::findEnabledCouplerOut(void)
1444   TRY
1445   {
1446      const std::vector<CCouplerOut*> allCouplerOut = CCouplerOut::getAll();
1447      bool enabled ;
1448      for (size_t i = 0; i < allCouplerOut.size(); i++)
1449      {
1450        if (allCouplerOut[i]->enabled.isEmpty()) enabled=true ;
1451        else enabled=allCouplerOut[i]->enabled ;
1452        if (enabled) enabledCouplerOut.push_back(allCouplerOut[i]) ;
1453      }
1454   }
1455   CATCH_DUMP_ATTR
1456
1457
1458
1459
1460   void CContext::distributeFiles(const vector<CFile*>& files)
1461   TRY
1462   {
1463     bool distFileMemory=false ;
1464     distFileMemory=CXios::getin<bool>("server2_dist_file_memory", distFileMemory);
1465
1466     if (distFileMemory) distributeFileOverMemoryBandwith(files) ;
1467     else distributeFileOverBandwith(files) ;
1468   }
1469   CATCH_DUMP_ATTR
1470
1471   void CContext::distributeFileOverBandwith(const vector<CFile*>& files)
1472   TRY
1473   {
1474     double eps=std::numeric_limits<double>::epsilon()*10 ;
1475     
1476     std::ofstream ofs(("distribute_file_"+getId()+".dat").c_str(), std::ofstream::out);
1477     int nbPools = clientPrimServer.size();
1478
1479     // (1) Find all enabled files in write mode
1480     // for (int i = 0; i < this->enabledFiles.size(); ++i)
1481     // {
1482     //   if (enabledFiles[i]->mode.isEmpty() || (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write ))
1483     //    enabledWriteModeFiles.push_back(enabledFiles[i]);
1484     // }
1485
1486     // (2) Estimate the data volume for each file
1487     int size = files.size();
1488     std::vector<std::pair<double, CFile*> > dataSizeMap;
1489     double dataPerPool = 0;
1490     int nfield=0 ;
1491     ofs<<size<<endl ;
1492     for (size_t i = 0; i < size; ++i)
1493     {
1494       CFile* file = files[i];
1495       ofs<<file->getId()<<endl ;
1496       StdSize dataSize=0;
1497       std::vector<CField*> enabledFields = file->getEnabledFields();
1498       size_t numEnabledFields = enabledFields.size();
1499       ofs<<numEnabledFields<<endl ;
1500       for (size_t j = 0; j < numEnabledFields; ++j)
1501       {
1502         dataSize += enabledFields[j]->getGlobalWrittenSize() ;
1503         ofs<<enabledFields[j]->getGrid()->getId()<<endl ;
1504         ofs<<enabledFields[j]->getGlobalWrittenSize()<<endl ;
1505       }
1506       double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ;
1507       double dataSizeSec= dataSize/ outFreqSec;
1508       ofs<<dataSizeSec<<endl ;
1509       nfield++ ;
1510// add epsilon*nField to dataSizeSec in order to  preserve reproductive ordering when sorting
1511       dataSizeMap.push_back(make_pair(dataSizeSec + dataSizeSec * eps * nfield , file));
1512       dataPerPool += dataSizeSec;
1513     }
1514     dataPerPool /= nbPools;
1515     std::sort(dataSizeMap.begin(), dataSizeMap.end());
1516
1517     // (3) Assign contextClient to each enabled file
1518
1519     std::multimap<double,int> poolDataSize ;
1520// multimap is not garanty to preserve stable sorting in c++98 but it seems it does for c++11
1521
1522     int j;
1523     double dataSize ;
1524     for (j = 0 ; j < nbPools ; ++j) poolDataSize.insert(std::pair<double,int>(0.,j)) ; 
1525             
1526     for (int i = dataSizeMap.size()-1; i >= 0; --i)
1527     {
1528       dataSize=(*poolDataSize.begin()).first ;
1529       j=(*poolDataSize.begin()).second ;
1530       dataSizeMap[i].second->setContextClient(clientPrimServer[j]);
1531       dataSize+=dataSizeMap[i].first;
1532       poolDataSize.erase(poolDataSize.begin()) ;
1533       poolDataSize.insert(std::pair<double,int>(dataSize,j)) ; 
1534     }
1535
1536     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 ;
1537   }
1538   CATCH_DUMP_ATTR
1539
1540   void CContext::distributeFileOverMemoryBandwith(const vector<CFile*>& filesList)
1541   TRY
1542   {
1543     int nbPools = clientPrimServer.size();
1544     double ratio=0.5 ;
1545     ratio=CXios::getin<double>("server2_dist_file_memory_ratio", ratio);
1546
1547     int nFiles = filesList.size();
1548     vector<SDistFile> files(nFiles);
1549     vector<SDistGrid> grids;
1550     map<string,int> gridMap ;
1551     string gridId; 
1552     int gridIndex=0 ;
1553
1554     for (size_t i = 0; i < nFiles; ++i)
1555     {
1556       StdSize dataSize=0;
1557       CFile* file = filesList[i];
1558       std::vector<CField*> enabledFields = file->getEnabledFields();
1559       size_t numEnabledFields = enabledFields.size();
1560
1561       files[i].id_=file->getId() ;
1562       files[i].nbGrids_=numEnabledFields;
1563       files[i].assignedGrid_ = new int[files[i].nbGrids_] ;
1564         
1565       for (size_t j = 0; j < numEnabledFields; ++j)
1566       {
1567         gridId=enabledFields[j]->getGrid()->getId() ;
1568         if (gridMap.find(gridId)==gridMap.end())
1569         {
1570            gridMap[gridId]=gridIndex  ;
1571            SDistGrid newGrid; 
1572            grids.push_back(newGrid) ;
1573            gridIndex++ ;
1574         }
1575         files[i].assignedGrid_[j]=gridMap[gridId] ;
1576         grids[files[i].assignedGrid_[j]].size_=enabledFields[j]->getGlobalWrittenSize() ;
1577         dataSize += enabledFields[j]->getGlobalWrittenSize() ; // usefull
1578       }
1579       double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ;
1580       files[i].bandwith_= dataSize/ outFreqSec ;
1581     }
1582
1583     double bandwith=0 ;
1584     double memory=0 ;
1585   
1586     for(int i=0; i<nFiles; i++)  bandwith+=files[i].bandwith_ ;
1587     for(int i=0; i<nFiles; i++)  files[i].bandwith_ = files[i].bandwith_/bandwith * ratio ;
1588
1589     for(int i=0; i<grids.size(); i++)  memory+=grids[i].size_ ;
1590     for(int i=0; i<grids.size(); i++)  grids[i].size_ = grids[i].size_ / memory * (1.0-ratio) ;
1591       
1592     distributeFileOverServer2(nbPools, grids.size(), &grids[0], nFiles, &files[0]) ;
1593
1594     vector<double> memorySize(nbPools,0.) ;
1595     vector< set<int> > serverGrids(nbPools) ;
1596     vector<double> bandwithSize(nbPools,0.) ;
1597       
1598     for (size_t i = 0; i < nFiles; ++i)
1599     {
1600       bandwithSize[files[i].assignedServer_] += files[i].bandwith_* bandwith /ratio ;
1601       for(int j=0 ; j<files[i].nbGrids_;j++)
1602       {
1603         if (serverGrids[files[i].assignedServer_].find(files[i].assignedGrid_[j]) == serverGrids[files[i].assignedServer_].end())
1604         {
1605           memorySize[files[i].assignedServer_]+= grids[files[i].assignedGrid_[j]].size_ * memory / (1.0-ratio);
1606           serverGrids[files[i].assignedServer_].insert(files[i].assignedGrid_[j]) ;
1607         }
1608       }
1609       filesList[i]->setContextClient(clientPrimServer[files[i].assignedServer_]) ;
1610       delete [] files[i].assignedGrid_ ;
1611     }
1612
1613     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 ;
1614     for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<"   assigned grid memory "<<memorySize[i]*100/1024./1024.<<" Mb"<<endl ;
1615
1616   }
1617   CATCH_DUMP_ATTR
1618
1619   /*!
1620      Find all files in write mode
1621   */
1622   void CContext::findEnabledWriteModeFiles(void)
1623   TRY
1624   {
1625     int size = this->enabledFiles.size();
1626     for (int i = 0; i < size; ++i)
1627     {
1628       if (enabledFiles[i]->mode.isEmpty() || 
1629          (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write ))
1630        enabledWriteModeFiles.push_back(enabledFiles[i]);
1631     }
1632   }
1633   CATCH_DUMP_ATTR
1634
1635   /*!
1636      Find all files in read mode
1637   */
1638   void CContext::findEnabledReadModeFiles(void)
1639   TRY
1640   {
1641     int size = this->enabledFiles.size();
1642     for (int i = 0; i < size; ++i)
1643     {
1644       if (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::read)
1645        enabledReadModeFiles.push_back(enabledFiles[i]);
1646     }
1647   }
1648   CATCH_DUMP_ATTR
1649
1650   void CContext::closeAllFile(void)
1651   TRY
1652   {
1653     std::vector<CFile*>::const_iterator
1654            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
1655
1656     for (; it != end; it++)
1657     {
1658       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
1659       (*it)->close();
1660     }
1661   }
1662   CATCH_DUMP_ATTR
1663
1664   /*!
1665   \brief Dispatch event received from client
1666      Whenever a message is received in buffer of server, it will be processed depending on
1667   its event type. A new event type should be added in the switch list to make sure
1668   it processed on server side.
1669   \param [in] event: Received message
1670   */
1671   bool CContext::dispatchEvent(CEventServer& event)
1672   TRY
1673   {
1674
1675      if (SuperClass::dispatchEvent(event)) return true;
1676      else
1677      {
1678        switch(event.type)
1679        {
1680           case EVENT_ID_CLOSE_DEFINITION :
1681             recvCloseDefinition(event);
1682             return true;
1683             break;
1684           case EVENT_ID_UPDATE_CALENDAR:
1685             recvUpdateCalendar(event);
1686             return true;
1687             break;
1688           case EVENT_ID_CREATE_FILE_HEADER :
1689             recvCreateFileHeader(event);
1690             return true;
1691             break;
1692           case EVENT_ID_SEND_REGISTRY:
1693             recvRegistry(event);
1694             return true;
1695             break;
1696           case EVENT_ID_COUPLER_IN_READY:
1697             recvCouplerInReady(event);
1698             return true;
1699             break;
1700           case EVENT_ID_COUPLER_IN_CLOSE_DEFINITION:
1701             recvCouplerInCloseDefinition(event);
1702             return true;
1703             break;
1704           case EVENT_ID_COUPLER_IN_CONTEXT_FINALIZED:
1705             recvCouplerInContextFinalized(event);
1706             return true;
1707             break; 
1708           default :
1709             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
1710                    <<"Unknown Event");
1711           return false;
1712         }
1713      }
1714   }
1715   CATCH
1716
1717   //! Client side: Send a message to server to make it close
1718   // ym obsolete
1719   void CContext::sendCloseDefinition(void)
1720   TRY
1721   {
1722    int nbSrvPools ;
1723    if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ;
1724    else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ;
1725    else nbSrvPools = 0 ;
1726    CContextClient* contextClientTmp ;
1727
1728    for (int i = 0; i < nbSrvPools; ++i)
1729     {
1730       if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ;
1731       else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ;
1732       CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
1733       if (contextClientTmp->isServerLeader())
1734       {
1735         CMessage msg;
1736         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1737         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1738           event.push(*itRank,1,msg);
1739         contextClientTmp->sendEvent(event);
1740       }
1741       else contextClientTmp->sendEvent(event);
1742     }
1743   }
1744   CATCH_DUMP_ATTR
1745   
1746   //  ! Client side: Send a message to server to make it close
1747   void CContext::sendCloseDefinition(CContextClient* client)
1748   TRY
1749   {
1750      if (sendCloseDefinition_done_.count(client)!=0) return ;
1751      else sendCloseDefinition_done_.insert(client) ;
1752
1753      CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
1754      if (client->isServerLeader())
1755      {
1756        CMessage msg;
1757        for(auto rank : client->getRanksServerLeader()) event.push(rank,1,msg);
1758        client->sendEvent(event);
1759      }
1760     else client->sendEvent(event);
1761   }
1762   CATCH_DUMP_ATTR
1763
1764   //! Server side: Receive a message of client announcing a context close
1765   void CContext::recvCloseDefinition(CEventServer& event)
1766   TRY
1767   {
1768      CBufferIn* buffer=event.subEvents.begin()->buffer;
1769      getCurrent()->closeDefinition();
1770   }
1771   CATCH
1772
1773   //! Client side: Send a message to update calendar in each time step
1774   void CContext::sendUpdateCalendar(int step)
1775   TRY
1776   {
1777     CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR);
1778     for(auto client : slaveServers_) 
1779     {
1780       if (client->isServerLeader())
1781       {
1782         CMessage msg;
1783         msg<<step;
1784         for (auto& rank : client->getRanksServerLeader() ) event.push(rank,1,msg);
1785         client->sendEvent(event);
1786       }
1787       else client->sendEvent(event);
1788     }
1789   }
1790   CATCH_DUMP_ATTR
1791
1792   //! Server side: Receive a message of client annoucing calendar update
1793   void CContext::recvUpdateCalendar(CEventServer& event)
1794   TRY
1795   {
1796      CBufferIn* buffer=event.subEvents.begin()->buffer;
1797      getCurrent()->recvUpdateCalendar(*buffer);
1798   }
1799   CATCH
1800
1801   //! Server side: Receive a message of client annoucing calendar update
1802   void CContext::recvUpdateCalendar(CBufferIn& buffer)
1803   TRY
1804   {
1805      int step;
1806      buffer>>step;
1807      updateCalendar(step);
1808      if (serviceType_==CServicesManager::GATHERER)
1809      {       
1810        sendUpdateCalendar(step);
1811      }
1812   }
1813   CATCH_DUMP_ATTR
1814
1815   //! Client side: Send a message to create header part of netcdf file
1816   void CContext::sendCreateFileHeader(void)
1817   TRY
1818   {
1819     int nbSrvPools ;
1820     if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ;
1821     else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ;
1822     else nbSrvPools = 0 ;
1823     CContextClient* contextClientTmp ;
1824
1825     for (int i = 0; i < nbSrvPools; ++i)
1826     {
1827       if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ;
1828       else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ;
1829       CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER);
1830
1831       if (contextClientTmp->isServerLeader())
1832       {
1833         CMessage msg;
1834         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1835         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1836           event.push(*itRank,1,msg) ;
1837         contextClientTmp->sendEvent(event);
1838       }
1839       else contextClientTmp->sendEvent(event);
1840     }
1841   }
1842   CATCH_DUMP_ATTR
1843
1844   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
1845   void CContext::recvCreateFileHeader(CEventServer& event)
1846   TRY
1847   {
1848      CBufferIn* buffer=event.subEvents.begin()->buffer;
1849      getCurrent()->recvCreateFileHeader(*buffer);
1850   }
1851   CATCH
1852
1853   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
1854   void CContext::recvCreateFileHeader(CBufferIn& buffer)
1855   TRY
1856   {
1857      if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER) 
1858        createFileHeader();
1859   }
1860   CATCH_DUMP_ATTR
1861
1862   void CContext::createCouplerInterCommunicator(void)
1863   TRY
1864   {
1865      int rank=this->getIntraCommRank() ;
1866      map<string,list<CCouplerOut*>> listCouplerOut ; 
1867      map<string,list<CCouplerIn*>> listCouplerIn ; 
1868
1869      for(auto couplerOut : enabledCouplerOut) listCouplerOut[couplerOut->getCouplingContextId()].push_back(couplerOut) ;
1870      for(auto couplerIn : enabledCouplerIn) listCouplerIn[couplerIn->getCouplingContextId()].push_back(couplerIn) ;
1871
1872      CCouplerManager* couplerManager = CXios::getCouplerManager() ;
1873      if (rank==0)
1874      {
1875        for(auto couplerOut : listCouplerOut) couplerManager->registerCoupling(this->getContextId(),couplerOut.first) ;
1876        for(auto couplerIn : listCouplerIn) couplerManager->registerCoupling(couplerIn.first,this->getContextId()) ;
1877      }
1878
1879      do
1880      {
1881        for(auto couplerOut : listCouplerOut) 
1882        {
1883          bool isNextCoupling ;
1884          if (rank==0) isNextCoupling = couplerManager->isNextCoupling(this->getContextId(),couplerOut.first) ;
1885          MPI_Bcast(&isNextCoupling,1,MPI_C_BOOL, 0, getIntraComm()) ; 
1886          if (isNextCoupling) 
1887          {
1888            addCouplingChanel(couplerOut.first, true) ;
1889            listCouplerOut.erase(couplerOut.first) ;
1890            break ;
1891          }           
1892        }
1893        for(auto couplerIn : listCouplerIn) 
1894        {
1895          bool isNextCoupling ;
1896          if (rank==0) isNextCoupling = couplerManager->isNextCoupling(couplerIn.first,this->getContextId());
1897          MPI_Bcast(&isNextCoupling,1,MPI_C_BOOL, 0, getIntraComm()) ; 
1898          if (isNextCoupling) 
1899          {
1900            addCouplingChanel(couplerIn.first, false) ;
1901            listCouplerIn.erase(couplerIn.first) ;
1902            break ;
1903          }           
1904        }
1905
1906      } while (!listCouplerOut.empty() || !listCouplerIn.empty()) ;
1907
1908   }
1909   CATCH_DUMP_ATTR
1910
1911 
1912     //! Client side: Send infomation of active files (files are enabled to write out)
1913   void CContext::sendEnabledFiles(const std::vector<CFile*>& activeFiles)
1914   TRY
1915   {
1916     int size = activeFiles.size();
1917
1918     // In a context, each type has a root definition, e.g: axis, domain, field.
1919     // Every object must be a child of one of these root definition. In this case
1920     // all new file objects created on server must be children of the root "file_definition"
1921     StdString fileDefRoot("file_definition");
1922     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
1923
1924     for (int i = 0; i < size; ++i)
1925     {
1926       CFile* f = activeFiles[i];
1927       cfgrpPtr->sendCreateChild(f->getId(),f->getContextClient());
1928       f->sendAllAttributesToServer(f->getContextClient());
1929       f->sendAddAllVariables(f->getContextClient());
1930     }
1931   }
1932   CATCH_DUMP_ATTR
1933
1934   //! Client side: Send information of active fields (ones are written onto files)
1935   void CContext::sendEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)
1936   TRY
1937   {
1938     int size = activeFiles.size();
1939     for (int i = 0; i < size; ++i)
1940     {
1941       activeFiles[i]->sendEnabledFields(activeFiles[i]->getContextClient());
1942     }
1943   }
1944   CATCH_DUMP_ATTR
1945
1946 
1947   //! Client side: Prepare the timeseries by adding the necessary files
1948   void CContext::prepareTimeseries()
1949   TRY
1950   {
1951     const std::vector<CFile*> allFiles = CFile::getAll();
1952     for (size_t i = 0; i < allFiles.size(); i++)
1953     {
1954       CFile* file = allFiles[i];
1955
1956       std::vector<CVariable*> fileVars, fieldVars, vars = file->getAllVariables();
1957       for (size_t k = 0; k < vars.size(); k++)
1958       {
1959         CVariable* var = vars[k];
1960
1961         if (var->ts_target.isEmpty()
1962              || var->ts_target == CVariable::ts_target_attr::file || var->ts_target == CVariable::ts_target_attr::both)
1963           fileVars.push_back(var);
1964
1965         if (!var->ts_target.isEmpty()
1966              && (var->ts_target == CVariable::ts_target_attr::field || var->ts_target == CVariable::ts_target_attr::both))
1967           fieldVars.push_back(var);
1968       }
1969
1970       if (!file->timeseries.isEmpty() && file->timeseries != CFile::timeseries_attr::none)
1971       {
1972         StdString fileNameStr("%file_name%") ;
1973         StdString tsPrefix = !file->ts_prefix.isEmpty() ? file->ts_prefix : fileNameStr ;
1974         
1975         StdString fileName=file->getFileOutputName();
1976         size_t pos=tsPrefix.find(fileNameStr) ;
1977         while (pos!=std::string::npos)
1978         {
1979           tsPrefix=tsPrefix.replace(pos,fileNameStr.size(),fileName) ;
1980           pos=tsPrefix.find(fileNameStr) ;
1981         }
1982       
1983         const std::vector<CField*> allFields = file->getAllFields();
1984         for (size_t j = 0; j < allFields.size(); j++)
1985         {
1986           CField* field = allFields[j];
1987
1988           if (!field->ts_enabled.isEmpty() && field->ts_enabled)
1989           {
1990             CFile* tsFile = CFile::create();
1991             tsFile->duplicateAttributes(file);
1992
1993             // Add variables originating from file and targeted to timeserie file
1994             for (size_t k = 0; k < fileVars.size(); k++)
1995               tsFile->getVirtualVariableGroup()->addChild(fileVars[k]);
1996
1997           
1998             tsFile->name = tsPrefix + "_";
1999             if (!field->name.isEmpty())
2000               tsFile->name.get() += field->name;
2001             else if (field->hasDirectFieldReference()) // We cannot use getBaseFieldReference() just yet
2002               tsFile->name.get() += field->field_ref;
2003             else
2004               tsFile->name.get() += field->getId();
2005
2006             if (!field->ts_split_freq.isEmpty())
2007               tsFile->split_freq = field->ts_split_freq;
2008
2009             CField* tsField = tsFile->addField();
2010             tsField->field_ref = field->getId();
2011
2012             // Add variables originating from file and targeted to timeserie field
2013             for (size_t k = 0; k < fieldVars.size(); k++)
2014               tsField->getVirtualVariableGroup()->addChild(fieldVars[k]);
2015
2016             vars = field->getAllVariables();
2017             for (size_t k = 0; k < vars.size(); k++)
2018             {
2019               CVariable* var = vars[k];
2020
2021               // Add variables originating from field and targeted to timeserie field
2022               if (var->ts_target.isEmpty()
2023                    || var->ts_target == CVariable::ts_target_attr::field || var->ts_target == CVariable::ts_target_attr::both)
2024                 tsField->getVirtualVariableGroup()->addChild(var);
2025
2026               // Add variables originating from field and targeted to timeserie file
2027               if (!var->ts_target.isEmpty()
2028                    && (var->ts_target == CVariable::ts_target_attr::file || var->ts_target == CVariable::ts_target_attr::both))
2029                 tsFile->getVirtualVariableGroup()->addChild(var);
2030             }
2031
2032             tsFile->solveFieldRefInheritance(true);
2033
2034             if (file->timeseries == CFile::timeseries_attr::exclusive)
2035               field->enabled = false;
2036           }
2037         }
2038
2039         // Finally disable the original file is need be
2040         if (file->timeseries == CFile::timeseries_attr::only)
2041          file->enabled = false;
2042       }
2043     }
2044   }
2045   CATCH_DUMP_ATTR
2046
2047 
2048   //! Client side: Send information of reference domain, axis and scalar of active fields
2049   void CContext::sendRefDomainsAxisScalars(const std::vector<CFile*>& activeFiles)
2050   TRY
2051   {
2052     std::set<pair<StdString,CContextClient*>> domainIds, axisIds, scalarIds;
2053
2054     // Find all reference domain and axis of all active fields
2055     int numEnabledFiles = activeFiles.size();
2056     for (int i = 0; i < numEnabledFiles; ++i)
2057     {
2058       std::vector<CField*> enabledFields = activeFiles[i]->getEnabledFields();
2059       int numEnabledFields = enabledFields.size();
2060       for (int j = 0; j < numEnabledFields; ++j)
2061       {
2062         CContextClient* contextClient=enabledFields[j]->getContextClient() ;
2063         const std::vector<StdString>& prDomAxisScalarId = enabledFields[j]->getRefDomainAxisIds();
2064         if ("" != prDomAxisScalarId[0]) domainIds.insert(make_pair(prDomAxisScalarId[0],contextClient));
2065         if ("" != prDomAxisScalarId[1]) axisIds.insert(make_pair(prDomAxisScalarId[1],contextClient));
2066         if ("" != prDomAxisScalarId[2]) scalarIds.insert(make_pair(prDomAxisScalarId[2],contextClient));
2067       }
2068     }
2069
2070     // Create all reference axis on server side
2071     std::set<StdString>::iterator itDom, itAxis, itScalar;
2072     std::set<StdString>::const_iterator itE;
2073
2074     StdString scalarDefRoot("scalar_definition");
2075     CScalarGroup* scalarPtr = CScalarGroup::get(scalarDefRoot);
2076     
2077     for (auto itScalar = scalarIds.begin(); itScalar != scalarIds.end(); ++itScalar)
2078     {
2079       if (!itScalar->first.empty())
2080       {
2081         scalarPtr->sendCreateChild(itScalar->first,itScalar->second);
2082         CScalar::get(itScalar->first)->sendAllAttributesToServer(itScalar->second);
2083       }
2084     }
2085
2086     StdString axiDefRoot("axis_definition");
2087     CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
2088     
2089     for (auto itAxis = axisIds.begin(); itAxis != axisIds.end(); ++itAxis)
2090     {
2091       if (!itAxis->first.empty())
2092       {
2093         axisPtr->sendCreateChild(itAxis->first, itAxis->second);
2094         CAxis::get(itAxis->first)->sendAllAttributesToServer(itAxis->second);
2095       }
2096     }
2097
2098     // Create all reference domains on server side
2099     StdString domDefRoot("domain_definition");
2100     CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
2101     
2102     for (auto itDom = domainIds.begin(); itDom != domainIds.end(); ++itDom)
2103     {
2104       if (!itDom->first.empty()) {
2105          domPtr->sendCreateChild(itDom->first, itDom->second);
2106          CDomain::get(itDom->first)->sendAllAttributesToServer(itDom->second);
2107       }
2108     }
2109   }
2110   CATCH_DUMP_ATTR
2111
2112   void CContext::triggerLateFields(void)
2113   TRY
2114   {
2115    for(auto& field : fileInFields_) field->triggerLateField() ;
2116    for(auto& field : couplerInFields_) field->triggerLateField() ;
2117   }
2118   CATCH_DUMP_ATTR
2119
2120   //! Update calendar in each time step
2121   void CContext::updateCalendar(int step)
2122   TRY
2123   {
2124      int prevStep = calendar->getStep();
2125
2126      if (prevStep < step)
2127      {
2128        if (serviceType_==CServicesManager::CLIENT) // For now we only use server level 1 to read data
2129        {
2130          triggerLateFields();
2131        }
2132
2133        info(50) << "updateCalendar : before : " << calendar->getCurrentDate() << endl;
2134        calendar->update(step);
2135        info(50) << "updateCalendar : after : " << calendar->getCurrentDate() << endl;
2136  #ifdef XIOS_MEMTRACK_LIGHT
2137        info(50) << " Current memory used by XIOS : "<<  MemTrack::getCurrentMemorySize()*1.0/(1024*1024)<<" Mbyte, at timestep "<<step<<" of context "<<this->getId()<<endl ;
2138  #endif
2139
2140        if (serviceType_==CServicesManager::CLIENT) // For now we only use server level 1 to read data
2141        {
2142          doPostTimestepOperationsForEnabledReadModeFiles();
2143          garbageCollector.invalidate(calendar->getCurrentDate());
2144        }
2145      }
2146      else if (prevStep == step)
2147        info(50) << "updateCalendar: already at step " << step << ", no operation done." << endl;
2148      else // if (prevStep > step)
2149        ERROR("void CContext::updateCalendar(int step)",
2150              << "Illegal calendar update: previous step was " << prevStep << ", new step " << step << "is in the past!")
2151   }
2152   CATCH_DUMP_ATTR
2153
2154   void CContext::initReadFiles(void)
2155   TRY
2156   {
2157      vector<CFile*>::const_iterator it;
2158
2159      for (it=enabledReadModeFiles.begin(); it != enabledReadModeFiles.end(); it++)
2160      {
2161         (*it)->initRead();
2162      }
2163   }
2164   CATCH_DUMP_ATTR
2165
2166   //! Server side: Create header of netcdf file
2167   void CContext::createFileHeader(void)
2168   TRY
2169   {
2170      vector<CFile*>::const_iterator it;
2171
2172      //for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
2173      for (it=enabledWriteModeFiles.begin(); it != enabledWriteModeFiles.end(); it++)
2174      {
2175         (*it)->initWrite();
2176      }
2177   }
2178   CATCH_DUMP_ATTR
2179
2180   //! Get current context
2181   CContext* CContext::getCurrent(void)
2182   TRY
2183   {
2184     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get();
2185   }
2186   CATCH
2187
2188   /*!
2189   \brief Set context with an id be the current context
2190   \param [in] id identity of context to be set to current
2191   */
2192   void CContext::setCurrent(const string& id)
2193   TRY
2194   {
2195     CObjectFactory::SetCurrentContextId(id);
2196     CGroupFactory::SetCurrentContextId(id);
2197   }
2198   CATCH
2199
2200  /*!
2201  \brief Create a context with specific id
2202  \param [in] id identity of new context
2203  \return pointer to the new context or already-existed one with identity id
2204  */
2205  CContext* CContext::create(const StdString& id)
2206  TRY
2207  {
2208    CContext::setCurrent(id);
2209
2210    bool hasctxt = CContext::has(id);
2211    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
2212    getRoot();
2213    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
2214
2215#define DECLARE_NODE(Name_, name_) \
2216    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
2217#define DECLARE_NODE_PAR(Name_, name_)
2218#include "node_type.conf"
2219
2220    return (context);
2221  }
2222  CATCH
2223
2224     //! Server side: Receive a message to do some post processing
2225  void CContext::recvRegistry(CEventServer& event)
2226  TRY
2227  {
2228    CBufferIn* buffer=event.subEvents.begin()->buffer;
2229    getCurrent()->recvRegistry(*buffer);
2230  }
2231  CATCH
2232
2233  void CContext::recvRegistry(CBufferIn& buffer)
2234  TRY
2235  {
2236    if (server->intraCommRank==0)
2237    {
2238      CRegistry registry(server->intraComm) ;
2239      registry.fromBuffer(buffer) ;
2240      registryOut->mergeRegistry(registry) ;
2241    }
2242  }
2243  CATCH_DUMP_ATTR
2244
2245  void CContext::sendRegistry(void)
2246  TRY
2247  {
2248    registryOut->hierarchicalGatherRegistry() ;
2249
2250    int nbSrvPools ;
2251    if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ;
2252    else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ;
2253    else nbSrvPools = 0 ;
2254    CContextClient* contextClientTmp ;
2255
2256    for (int i = 0; i < nbSrvPools; ++i)
2257    {
2258      if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ;
2259      else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ;
2260
2261      CEventClient event(CContext::GetType(), CContext::EVENT_ID_SEND_REGISTRY);
2262      if (contextClientTmp->isServerLeader())
2263      {
2264        CMessage msg ;
2265        if (contextClientTmp->clientRank==0) msg<<*registryOut ;
2266        const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
2267        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
2268             event.push(*itRank,1,msg);
2269        contextClientTmp->sendEvent(event);
2270      }
2271      else contextClientTmp->sendEvent(event);
2272    }
2273  }
2274  CATCH_DUMP_ATTR
2275
2276 
2277  void CContext::sendFinalizeClient(CContextClient* contextClient, const string& contextClientId)
2278  TRY
2279  {
2280    CEventClient event(getType(),EVENT_ID_CONTEXT_FINALIZE_CLIENT);
2281    if (contextClient->isServerLeader())
2282    {
2283      CMessage msg;
2284      msg<<contextClientId ;
2285      const std::list<int>& ranks = contextClient->getRanksServerLeader();
2286      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
2287           event.push(*itRank,1,msg);
2288      contextClient->sendEvent(event);
2289    }
2290    else contextClient->sendEvent(event);
2291  }
2292  CATCH_DUMP_ATTR
2293
2294 
2295  void CContext::recvFinalizeClient(CEventServer& event)
2296  TRY
2297  {
2298    CBufferIn* buffer=event.subEvents.begin()->buffer;
2299    string id;
2300    *buffer>>id;
2301    get(id)->recvFinalizeClient(*buffer);
2302  }
2303  CATCH
2304
2305  void CContext::recvFinalizeClient(CBufferIn& buffer)
2306  TRY
2307  {
2308    countChildContextFinalized_++ ;
2309  }
2310  CATCH_DUMP_ATTR
2311
2312
2313
2314
2315 //! Client side: Send a message  announcing that context can receive grid definition from coupling
2316   void CContext::sendCouplerInReady(CContextClient* client)
2317   TRY
2318   {
2319      if (sendCouplerInReady_done_.count(client)!=0) return ;
2320      else sendCouplerInReady_done_.insert(client) ;
2321
2322      CEventClient event(getType(),EVENT_ID_COUPLER_IN_READY);
2323
2324      if (client->isServerLeader())
2325      {
2326        CMessage msg;
2327        msg<<this->getId();
2328        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
2329        client->sendEvent(event);
2330      }
2331      else client->sendEvent(event);
2332   }
2333   CATCH_DUMP_ATTR
2334
2335   //! Server side: Receive a message announcing that context can send grid definition for context coupling
2336   void CContext::recvCouplerInReady(CEventServer& event)
2337   TRY
2338   {
2339      CBufferIn* buffer=event.subEvents.begin()->buffer;
2340      getCurrent()->recvCouplerInReady(*buffer);
2341   }
2342   CATCH
2343
2344   //! Server side: Receive a message announcing that context can send grid definition for context coupling
2345   void CContext::recvCouplerInReady(CBufferIn& buffer)
2346   TRY
2347   {
2348      string contextId ;
2349      buffer>>contextId;
2350      couplerInReady_.insert(getCouplerOutClient(contextId)) ;
2351   }
2352   CATCH_DUMP_ATTR
2353
2354
2355
2356
2357
2358 //! Client side: Send a message  announcing that a coupling context have done it closeDefinition, so data can be sent now.
2359   void CContext::sendCouplerInCloseDefinition(CContextClient* client)
2360   TRY
2361   {
2362      if (sendCouplerInCloseDefinition_done_.count(client)!=0) return ;
2363      else sendCouplerInCloseDefinition_done_.insert(client) ;
2364
2365      CEventClient event(getType(),EVENT_ID_COUPLER_IN_CLOSE_DEFINITION);
2366
2367      if (client->isServerLeader())
2368      {
2369        CMessage msg;
2370        msg<<this->getId();
2371        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
2372        client->sendEvent(event);
2373      }
2374      else client->sendEvent(event);
2375   }
2376   CATCH_DUMP_ATTR
2377
2378   //! Server side: Receive a message announcing that a coupling context have done it closeDefinition, so data can be sent now.
2379   void CContext::recvCouplerInCloseDefinition(CEventServer& event)
2380   TRY
2381   {
2382      CBufferIn* buffer=event.subEvents.begin()->buffer;
2383      getCurrent()->recvCouplerInCloseDefinition(*buffer);
2384   }
2385   CATCH
2386
2387   //! Server side: Receive a message announcing that a coupling context have done it closeDefinition, so data can be sent now.
2388   void CContext::recvCouplerInCloseDefinition(CBufferIn& buffer)
2389   TRY
2390   {
2391      string contextId ;
2392      buffer>>contextId;
2393      couplerInCloseDefinition_.insert(getCouplerOutClient(contextId)) ;
2394   }
2395   CATCH_DUMP_ATTR
2396
2397
2398
2399
2400//! Client side: Send a message  announcing that a coupling context have done it contextFinalize, so it can also close it own context.
2401   void CContext::sendCouplerInContextFinalized(CContextClient* client)
2402   TRY
2403   {
2404      if (sendCouplerInContextFinalized_done_.count(client)!=0) return ;
2405      else sendCouplerInContextFinalized_done_.insert(client) ;
2406
2407      CEventClient event(getType(),EVENT_ID_COUPLER_IN_CONTEXT_FINALIZED);
2408
2409      if (client->isServerLeader())
2410      {
2411        CMessage msg;
2412        msg<<this->getId();
2413        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
2414        client->sendEvent(event);
2415      }
2416      else client->sendEvent(event);
2417   }
2418   CATCH_DUMP_ATTR
2419
2420   //! Server side: Receive a message announcing that a coupling context have done it contextFinalize, so it can also close it own context.
2421   void CContext::recvCouplerInContextFinalized(CEventServer& event)
2422   TRY
2423   {
2424      CBufferIn* buffer=event.subEvents.begin()->buffer;
2425      getCurrent()->recvCouplerInContextFinalized(*buffer);
2426   }
2427   CATCH
2428
2429   //! Server side: Receive a message announcing that a coupling context have done it contextFinalize, so it can also close it own context.
2430   void CContext::recvCouplerInContextFinalized(CBufferIn& buffer)
2431   TRY
2432   {
2433      string contextId ;
2434      buffer>>contextId;
2435      couplerInContextFinalized_.insert(getCouplerOutClient(contextId)) ;
2436   }
2437   CATCH_DUMP_ATTR
2438
2439
2440
2441
2442  /*!
2443  * \fn bool CContext::isFinalized(void)
2444  * Context is finalized if it received context post finalize event.
2445  */
2446  bool CContext::isFinalized(void)
2447  TRY
2448  {
2449    return finalized;
2450  }
2451  CATCH_DUMP_ATTR
2452  ///--------------------------------------------------------------
2453  StdString CContext::dumpClassAttributes(void)
2454  {
2455    StdString str;
2456    str.append("enabled files=\"");
2457    int size = this->enabledFiles.size();
2458    for (int i = 0; i < size; ++i)
2459    {
2460      str.append(enabledFiles[i]->getId());
2461      str.append(" ");
2462    }
2463    str.append("\"");
2464    return str;
2465  }
2466
2467} // namespace xios
Note: See TracBrowser for help on using the repository browser.