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

Last change on this file since 2452 was 2441, checked in by jderouillat, 19 months ago

Reverse partially commit 2438 : the integration of environment variables in XML soures inclusion (not XIOS_IODEF_PATH).

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