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

Last change on this file since 2326 was 2326, checked in by ymipsl, 2 years ago

Fix Deadlock from reading phase.
YM

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