source: XIOS/dev/dev_ym/XIOS_SERVICES/src/node/context.cpp @ 1764

Last change on this file since 1764 was 1764, checked in by ymipsl, 5 years ago

Some Update on XIOS services
Seems to work on Irène for :

  • first level of servers
  • fisrt + second level of servers
  • attached mode

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