source: XIOS3/branches/xios-3.0-beta/src/node/context.cpp

Last change on this file was 2427, checked in by jderouillat, 20 months ago

Backport the system to log the memory consumption (commit ID [2418-2420,2425-2426])

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