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

Last change on this file since 2405 was 2405, checked in by ymipsl, 22 months ago

Refactor service management from context
YM

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