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

Last change on this file since 2423 was 2419, checked in by jderouillat, 21 months ago

Update the memory log system using plotly and CSV files, a dedicated viewer has been added.

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