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

Last change on this file since 1975 was 1974, checked in by ymipsl, 4 years ago

Big cleaning on XIOS coupling branch
YM

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