source: XIOS3/trunk/src/node/context.cpp @ 2588

Last change on this file since 2588 was 2588, checked in by ymipsl, 9 months ago

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