source: XIOS/trunk/src/node/context.cpp @ 1488

Last change on this file since 1488 was 1488, checked in by oabramkina, 6 years ago

Trunk and CMIP6: adding a check on output_freq attribute. Exception is thrown if it is empty.

  • 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: 45.5 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
19
20namespace xios {
21
22  shared_ptr<CContextGroup> CContext::root;
23
24   /// ////////////////////// Définitions ////////////////////// ///
25
26   CContext::CContext(void)
27      : CObjectTemplate<CContext>(), CContextAttributes()
28      , calendar(), hasClient(false), hasServer(false), isPostProcessed(false), finalized(false)
29      , idServer_(), client(0), server(0)
30   { /* Ne rien faire de plus */ }
31
32   CContext::CContext(const StdString & id)
33      : CObjectTemplate<CContext>(id), CContextAttributes()
34      , calendar(), hasClient(false), hasServer(false), isPostProcessed(false), finalized(false)
35      , idServer_(), client(0), server(0)
36   { /* Ne rien faire de plus */ }
37
38   CContext::~CContext(void)
39   {
40     delete client;
41     delete server;
42   }
43
44   //----------------------------------------------------------------
45   //! Get name of context
46   StdString CContext::GetName(void)   { return (StdString("context")); }
47   StdString CContext::GetDefName(void){ return (CContext::GetName()); }
48   ENodeType CContext::GetType(void)   { return (eContext); }
49
50   //----------------------------------------------------------------
51
52   /*!
53   \brief Get context group (context root)
54   \return Context root
55   */
56   CContextGroup* CContext::getRoot(void)
57   {
58      if (root.get()==NULL) root=shared_ptr<CContextGroup>(new CContextGroup(xml::CXMLNode::GetRootName()));
59      return root.get();
60   }
61
62   //----------------------------------------------------------------
63
64   /*!
65   \brief Get calendar of a context
66   \return Calendar
67   */
68   boost::shared_ptr<CCalendar> CContext::getCalendar(void) const
69   {
70      return (this->calendar);
71   }
72
73   //----------------------------------------------------------------
74
75   /*!
76   \brief Set a context with a calendar
77   \param[in] newCalendar new calendar
78   */
79   void CContext::setCalendar(boost::shared_ptr<CCalendar> newCalendar)
80   {
81      this->calendar = newCalendar;
82   }
83
84   //----------------------------------------------------------------
85   /*!
86   \brief Parse xml file and write information into context object
87   \param [in] node xmld node corresponding in xml file
88   */
89   void CContext::parse(xml::CXMLNode & node)
90   {
91      CContext::SuperClass::parse(node);
92
93      // PARSING POUR GESTION DES ENFANTS
94      xml::THashAttributes attributes = node.getAttributes();
95
96      if (attributes.end() != attributes.find("src"))
97      {
98         StdIFStream ifs ( attributes["src"].c_str() , StdIFStream::in );
99         if ( (ifs.rdstate() & std::ifstream::failbit ) != 0 )
100            ERROR("void CContext::parse(xml::CXMLNode & node)",
101                  <<endl<< "Can not open <"<<attributes["src"].c_str()<<"> file" );
102         if (!ifs.good())
103            ERROR("CContext::parse(xml::CXMLNode & node)",
104                  << "[ filename = " << attributes["src"] << " ] Bad xml stream !");
105         xml::CXMLParser::ParseInclude(ifs, attributes["src"], *this);
106      }
107
108      if (node.getElementName().compare(CContext::GetName()))
109         DEBUG("Le noeud is wrong defined but will be considered as a context !");
110
111      if (!(node.goToChildElement()))
112      {
113         DEBUG("Le context ne contient pas d'enfant !");
114      }
115      else
116      {
117         do { // Parcours des contextes pour traitement.
118
119            StdString name = node.getElementName();
120            attributes.clear();
121            attributes = node.getAttributes();
122
123            if (attributes.end() != attributes.find("id"))
124            {
125              DEBUG(<< "Definition node has an id,"
126                    << "it will not be taking account !");
127            }
128
129#define DECLARE_NODE(Name_, name_)    \
130   if (name.compare(C##Name_##Definition::GetDefName()) == 0) \
131   { C##Name_##Definition::create(C##Name_##Definition::GetDefName()) -> parse(node); continue; }
132#define DECLARE_NODE_PAR(Name_, name_)
133#include "node_type.conf"
134
135            DEBUG(<< "The element \'"     << name
136                  << "\' in the context \'" << CContext::getCurrent()->getId()
137                  << "\' is not a definition !");
138
139         } while (node.goToNextElement());
140
141         node.goToParentElement(); // Retour au parent
142      }
143   }
144
145   //----------------------------------------------------------------
146   //! Show tree structure of context
147   void CContext::ShowTree(StdOStream & out)
148   {
149      StdString currentContextId = CContext::getCurrent() -> getId();
150      std::vector<CContext*> def_vector =
151         CContext::getRoot()->getChildList();
152      std::vector<CContext*>::iterator
153         it = def_vector.begin(), end = def_vector.end();
154
155      out << "<? xml version=\"1.0\" ?>" << std::endl;
156      out << "<"  << xml::CXMLNode::GetRootName() << " >" << std::endl;
157
158      for (; it != end; it++)
159      {
160         CContext* context = *it;
161         CContext::setCurrent(context->getId());
162         out << *context << std::endl;
163      }
164
165      out << "</" << xml::CXMLNode::GetRootName() << " >" << std::endl;
166      CContext::setCurrent(currentContextId);
167   }
168
169
170   //----------------------------------------------------------------
171
172   //! Convert context object into string (to print)
173   StdString CContext::toString(void) const
174   {
175      StdOStringStream oss;
176      oss << "<" << CContext::GetName()
177          << " id=\"" << this->getId() << "\" "
178          << SuperClassAttribute::toString() << ">" << std::endl;
179      if (!this->hasChild())
180      {
181         //oss << "<!-- No definition -->" << std::endl; // fait planter l'incrémentation
182      }
183      else
184      {
185
186#define DECLARE_NODE(Name_, name_)    \
187   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
188   oss << * C##Name_##Definition::get(C##Name_##Definition::GetDefName()) << std::endl;
189#define DECLARE_NODE_PAR(Name_, name_)
190#include "node_type.conf"
191
192      }
193
194      oss << "</" << CContext::GetName() << " >";
195
196      return (oss.str());
197   }
198
199   //----------------------------------------------------------------
200
201   /*!
202   \brief Find all inheritace among objects in a context.
203   \param [in] apply (true) write attributes of parent into ones of child if they are empty
204                     (false) write attributes of parent into a new container of child
205   \param [in] parent unused
206   */
207   void CContext::solveDescInheritance(bool apply, const CAttributeMap * const UNUSED(parent))
208   {
209#define DECLARE_NODE(Name_, name_)    \
210   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
211     C##Name_##Definition::get(C##Name_##Definition::GetDefName())->solveDescInheritance(apply);
212#define DECLARE_NODE_PAR(Name_, name_)
213#include "node_type.conf"
214   }
215
216   //----------------------------------------------------------------
217
218   //! Verify if all root definition in the context have child.
219   bool CContext::hasChild(void) const
220   {
221      return (
222#define DECLARE_NODE(Name_, name_)    \
223   C##Name_##Definition::has(C##Name_##Definition::GetDefName())   ||
224#define DECLARE_NODE_PAR(Name_, name_)
225#include "node_type.conf"
226      false);
227}
228
229   //----------------------------------------------------------------
230
231   void CContext::CleanTree(void)
232   {
233#define DECLARE_NODE(Name_, name_) C##Name_##Definition::ClearAllAttributes();
234#define DECLARE_NODE_PAR(Name_, name_)
235#include "node_type.conf"
236   }
237   ///---------------------------------------------------------------
238
239   //! Initialize client side
240   void CContext::initClient(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtServer /*= 0*/)
241   {
242     hasClient=true;
243     client = new CContextClient(this,intraComm, interComm, cxtServer);
244     registryIn=new CRegistry(intraComm);
245     registryIn->setPath(getId()) ;
246     if (client->clientRank==0) registryIn->fromFile("xios_registry.bin") ;
247     registryIn->bcastRegistry() ;
248
249     registryOut=new CRegistry(intraComm) ;
250     registryOut->setPath(getId()) ;
251
252     MPI_Comm intraCommServer, interCommServer;
253     if (cxtServer) // Attached mode
254     {
255       intraCommServer = intraComm;
256       interCommServer = interComm;
257     }
258     else
259     {
260       MPI_Comm_dup(intraComm, &intraCommServer);
261       comms.push_back(intraCommServer);
262       MPI_Comm_dup(interComm, &interCommServer);
263       comms.push_back(interCommServer);
264     }
265     server = new CContextServer(this,intraCommServer,interCommServer);
266   }
267
268   void CContext::setClientServerBuffer()
269   {
270     // Estimated minimum event size for small events (10 is an arbitrary constant just for safety)
271     const size_t minEventSize = CEventClient::headerSize + getIdServer().size() + 10 * sizeof(int);
272     // Ensure there is at least some room for 20 of such events in the buffers
273     size_t minBufferSize = std::max(CXios::minBufferSize, 20 * minEventSize);
274#define DECLARE_NODE(Name_, name_)    \
275     if (minBufferSize < sizeof(C##Name_##Definition)) minBufferSize = sizeof(C##Name_##Definition);
276#define DECLARE_NODE_PAR(Name_, name_)
277#include "node_type.conf"
278#undef DECLARE_NODE
279#undef DECLARE_NODE_PAR
280
281     // Compute the buffer sizes needed to send the attributes and data corresponding to fields
282     std::map<int, StdSize> maxEventSize;
283     std::map<int, StdSize> bufferSize = getAttributesBufferSize(maxEventSize);
284     std::map<int, StdSize> dataBufferSize = getDataBufferSize(maxEventSize);
285
286     std::map<int, StdSize>::iterator it, ite = dataBufferSize.end();
287     for (it = dataBufferSize.begin(); it != ite; ++it)
288       if (it->second > bufferSize[it->first]) bufferSize[it->first] = it->second;
289
290     // Apply the buffer size factor and check that we are above the minimum buffer size
291     ite = bufferSize.end();
292     for (it = bufferSize.begin(); it != ite; ++it)
293     {
294       it->second *= CXios::bufferSizeFactor;
295       if (it->second < minBufferSize) it->second = minBufferSize;
296     }
297
298     // Leaders will have to send some control events so ensure there is some room for those in the buffers
299     if (client->isServerLeader())
300     {
301       const std::list<int>& ranks = client->getRanksServerLeader();
302       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
303       {
304         if (!bufferSize.count(*itRank))
305         {
306           bufferSize[*itRank] = minBufferSize;
307           maxEventSize[*itRank] = minEventSize;
308         }
309       }
310     }
311
312     client->setBufferSize(bufferSize, maxEventSize);
313   }
314
315   //! Verify whether a context is initialized
316   bool CContext::isInitialized(void)
317   {
318     return hasClient;
319   }
320
321   //! Initialize server
322   void CContext::initServer(MPI_Comm intraComm,MPI_Comm interComm, CContext* cxtClient /*= 0*/)
323   {
324     hasServer=true;
325     server = new CContextServer(this,intraComm,interComm);
326
327     registryIn=new CRegistry(intraComm);
328     registryIn->setPath(getId()) ;
329     if (server->intraCommRank==0) registryIn->fromFile("xios_registry.bin") ;
330     registryIn->bcastRegistry() ;
331     registryOut=new CRegistry(intraComm) ;
332     registryOut->setPath(getId()) ;
333
334     MPI_Comm intraCommClient, interCommClient;
335     if (cxtClient) // Attached mode
336     {
337       intraCommClient = intraComm;
338       interCommClient = interComm;
339     }
340     else
341     {
342       MPI_Comm_dup(intraComm, &intraCommClient);
343       comms.push_back(intraCommClient);
344       MPI_Comm_dup(interComm, &interCommClient);
345       comms.push_back(interCommClient);
346     }
347     client = new CContextClient(this,intraCommClient,interCommClient, cxtClient);
348   }
349
350   //! Try to send the buffers and receive possible answers
351   bool CContext::checkBuffersAndListen(void)
352   {
353     client->checkBuffers();
354
355     bool hasTmpBufferedEvent = client->hasTemporarilyBufferedEvent();
356     if (hasTmpBufferedEvent)
357       hasTmpBufferedEvent = !client->sendTemporarilyBufferedEvent();
358
359     // Don't process events if there is a temporarily buffered event
360     return server->eventLoop(!hasTmpBufferedEvent);
361   }
362
363   //! Terminate a context
364   void CContext::finalize(void)
365   {
366      if (!finalized)
367      {
368        finalized = true;
369        if (hasClient) sendRegistry() ;
370        client->finalize();
371        while (!server->hasFinished())
372        {
373          server->eventLoop();
374        }
375
376        if (hasServer)
377        {
378          closeAllFile();
379          registryOut->hierarchicalGatherRegistry() ;
380          if (server->intraCommRank==0) CXios::globalRegistry->mergeRegistry(*registryOut) ;
381        }
382
383        for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it)
384          MPI_Comm_free(&(*it));
385        comms.clear();
386      }
387   }
388
389   /*!
390   \brief Close all the context defintion and do processing data
391      After everything is well defined on client side, they will be processed and sent to server
392   From the version 2.0, sever and client work no more on the same database. Moreover, client(s) will send
393   all necessary information to server, from which each server can build its own database.
394   Because the role of server is to write out field data on a specific netcdf file,
395   the only information that it needs is the enabled files
396   and the active fields (fields will be written onto active files)
397   */
398   void CContext::closeDefinition(void)
399   {
400     CTimer::get("Context : close definition").resume() ;
401     // There is nothing client need to send to server
402     if (hasClient)
403     {
404       // After xml is parsed, there are some more works with post processing
405       postProcessing();
406     }
407     setClientServerBuffer();
408
409     if (hasClient && !hasServer)
410     {
411      // Send all attributes of current context to server
412      this->sendAllAttributesToServer();
413
414      // Send all attributes of current calendar
415      CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer();
416
417      // We have enough information to send to server
418      // First of all, send all enabled files
419       sendEnabledFiles();
420
421      // Then, send all enabled fields
422       sendEnabledFields();
423
424      // At last, we have all info of domain and axis, then send them
425       sendRefDomainsAxis();
426
427      // After that, send all grid (if any)
428       sendRefGrid();
429    }
430
431    // We have a xml tree on the server side and now, it should be also processed
432    if (hasClient && !hasServer) sendPostProcessing();
433
434    // There are some processings that should be done after all of above. For example: check mask or index
435    if (hasClient)
436    {
437      this->buildFilterGraphOfEnabledFields();
438      buildFilterGraphOfFieldsWithReadAccess();
439      this->solveAllRefOfEnabledFields(true);
440      postProcessFilterGraph();
441    }
442
443    // Now tell server that it can process all messages from client
444    if (hasClient && !hasServer) this->sendCloseDefinition();
445
446    // Nettoyage de l'arborescence
447    if (hasClient && !hasServer) CleanTree(); // Only on client side??
448
449    if (hasClient)
450    {
451      sendCreateFileHeader();
452
453      startPrefetchingOfEnabledReadModeFiles();
454    }
455    CTimer::get("Context : close definition").suspend() ;
456   }
457
458   void CContext::findAllEnabledFields(void)
459   {
460     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
461     (void)this->enabledFiles[i]->getEnabledFields();
462   }
463
464   void CContext::findAllEnabledFieldsInReadModeFiles(void)
465   {
466     for (unsigned int i = 0; i < this->enabledReadModeFiles.size(); ++i)
467     (void)this->enabledReadModeFiles[i]->getEnabledFields();
468   }
469
470   void CContext::readAttributesOfEnabledFieldsInReadModeFiles()
471   {
472      for (unsigned int i = 0; i < this->enabledReadModeFiles.size(); ++i)
473        (void)this->enabledReadModeFiles[i]->readAttributesOfEnabledFieldsInReadMode();
474   }
475
476   void CContext::solveOnlyRefOfEnabledFields(bool sendToServer)
477   {
478     int size = this->enabledFiles.size();
479     for (int i = 0; i < size; ++i)
480     {
481       this->enabledFiles[i]->solveOnlyRefOfEnabledFields(sendToServer);
482     }
483
484     for (int i = 0; i < size; ++i)
485     {
486       this->enabledFiles[i]->generateNewTransformationGridDest();
487     }
488   }
489
490   void CContext::solveAllRefOfEnabledFields(bool sendToServer)
491   {
492     int size = this->enabledFiles.size();
493     for (int i = 0; i < size; ++i)
494     {
495       this->enabledFiles[i]->solveAllRefOfEnabledFields(sendToServer);
496     }
497   }
498
499   void CContext::buildFilterGraphOfEnabledFields()
500   {
501     int size = this->enabledFiles.size();
502     for (int i = 0; i < size; ++i)
503     {
504       this->enabledFiles[i]->buildFilterGraphOfEnabledFields(garbageCollector);
505     }
506   }
507
508   void CContext::postProcessFilterGraph()
509   {
510     int size = enabledFiles.size();
511     for (int i = 0; i < size; ++i)
512     {
513        enabledFiles[i]->postProcessFilterGraph();
514     }
515   }
516
517   void CContext::startPrefetchingOfEnabledReadModeFiles()
518   {
519     int size = enabledReadModeFiles.size();
520     for (int i = 0; i < size; ++i)
521     {
522        enabledReadModeFiles[i]->prefetchEnabledReadModeFields();
523     }
524   }
525
526   void CContext::doPreTimestepOperationsForEnabledReadModeFiles()
527   {
528     int size = enabledReadModeFiles.size();
529     for (int i = 0; i < size; ++i)
530     {
531        enabledReadModeFiles[i]->doPreTimestepOperationsForEnabledReadModeFields();
532     }
533   }
534
535   void CContext::doPostTimestepOperationsForEnabledReadModeFiles()
536   {
537     int size = enabledReadModeFiles.size();
538     for (int i = 0; i < size; ++i)
539     {
540        enabledReadModeFiles[i]->doPostTimestepOperationsForEnabledReadModeFields();
541     }
542   }
543
544  void CContext::findFieldsWithReadAccess(void)
545  {
546    fieldsWithReadAccess.clear();
547    const vector<CField*> allFields = CField::getAll();
548    for (size_t i = 0; i < allFields.size(); ++i)
549    {
550      CField* field = allFields[i];
551
552      if (field->file && !field->file->mode.isEmpty() && field->file->mode == CFile::mode_attr::read)
553        field->read_access = true;
554      else if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled))
555        fieldsWithReadAccess.push_back(field);
556    }
557  }
558
559  void CContext::solveAllRefOfFieldsWithReadAccess()
560  {
561    for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
562      fieldsWithReadAccess[i]->solveAllReferenceEnabledField(false);
563  }
564
565  void CContext::buildFilterGraphOfFieldsWithReadAccess()
566  {
567    for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
568      fieldsWithReadAccess[i]->buildFilterGraph(garbageCollector, true);
569  }
570
571   void CContext::solveAllInheritance(bool apply)
572   {
573     // Résolution des héritages descendants (càd des héritages de groupes)
574     // pour chacun des contextes.
575      solveDescInheritance(apply);
576
577     // Résolution des héritages par référence au niveau des fichiers.
578      const vector<CFile*> allFiles=CFile::getAll();
579      const vector<CGrid*> allGrids= CGrid::getAll();
580
581     //if (hasClient && !hasServer)
582      if (hasClient)
583      {
584        for (unsigned int i = 0; i < allFiles.size(); i++)
585          allFiles[i]->solveFieldRefInheritance(apply);
586      }
587
588      unsigned int vecSize = allGrids.size();
589      unsigned int i = 0;
590      for (i = 0; i < vecSize; ++i)
591        allGrids[i]->solveDomainAxisRefInheritance(apply);
592
593   }
594
595   void CContext::findEnabledFiles(void)
596   {
597      const std::vector<CFile*> allFiles = CFile::getAll();
598      const CDate& initDate = calendar->getInitDate();
599
600      for (unsigned int i = 0; i < allFiles.size(); i++)
601         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
602         {
603            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
604            {
605              if (allFiles[i]->output_freq.isEmpty())
606              {
607                 ERROR("CContext::findEnabledFiles()",
608                     << "Mandatory attribute output_freq must be defined for file \""<<allFiles[i]->getFileOutputName()
609                     <<" \".")
610              }
611              if ((initDate + allFiles[i]->output_freq.getValue()) < (initDate + this->getCalendar()->getTimeStep()))
612              {
613                error(0)<<"WARNING: void CContext::findEnabledFiles()"<<endl
614                    << "Output frequency in file \""<<allFiles[i]->getFileOutputName()
615                    <<"\" is less than the time step. File will not be written."<<endl;
616              }
617              else
618               enabledFiles.push_back(allFiles[i]);
619            }
620         }
621         else
622         {
623           if (allFiles[i]->output_freq.isEmpty())
624           {
625              ERROR("CContext::findEnabledFiles()",
626                  << "Mandatory attribute output_freq must be defined for file \""<<allFiles[i]->getFileOutputName()
627                  <<" \".")
628           } 
629           if ( (initDate + allFiles[i]->output_freq.getValue()) < (initDate + this->getCalendar()->getTimeStep()))
630           {
631             error(0)<<"WARNING: void CContext::findEnabledFiles()"<<endl
632                 << "Output frequency in file \""<<allFiles[i]->getFileOutputName()
633                 <<"\" is less than the time step. File will not be written."<<endl;
634           }
635           else
636             enabledFiles.push_back(allFiles[i]); // otherwise true by default
637         }
638
639      if (enabledFiles.size() == 0)
640         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
641               << getId() << "\" !");
642   }
643
644   void CContext::findEnabledReadModeFiles(void)
645   {
646     int size = this->enabledFiles.size();
647     for (int i = 0; i < size; ++i)
648     {
649       if (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::read)
650        enabledReadModeFiles.push_back(enabledFiles[i]);
651     }
652   }
653
654   void CContext::closeAllFile(void)
655   {
656     std::vector<CFile*>::const_iterator
657            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
658
659     for (; it != end; it++)
660     {
661       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
662       (*it)->close();
663     }
664   }
665
666   /*!
667   \brief Dispatch event received from client
668      Whenever a message is received in buffer of server, it will be processed depending on
669   its event type. A new event type should be added in the switch list to make sure
670   it processed on server side.
671   \param [in] event: Received message
672   */
673   bool CContext::dispatchEvent(CEventServer& event)
674   {
675
676      if (SuperClass::dispatchEvent(event)) return true;
677      else
678      {
679        switch(event.type)
680        {
681           case EVENT_ID_CLOSE_DEFINITION :
682             recvCloseDefinition(event);
683             return true;
684             break;
685           case EVENT_ID_UPDATE_CALENDAR:
686             recvUpdateCalendar(event);
687             return true;
688             break;
689           case EVENT_ID_CREATE_FILE_HEADER :
690             recvCreateFileHeader(event);
691             return true;
692             break;
693           case EVENT_ID_POST_PROCESS:
694             recvPostProcessing(event);
695             return true;
696            case EVENT_ID_SEND_REGISTRY:
697             recvRegistry(event);
698             return true;
699            break;
700
701           default :
702             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
703                    <<"Unknown Event");
704           return false;
705         }
706      }
707   }
708
709   //! Client side: Send a message to server to make it close
710   void CContext::sendCloseDefinition(void)
711   {
712     CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
713     if (client->isServerLeader())
714     {
715       CMessage msg;
716       msg<<this->getIdServer();
717       const std::list<int>& ranks = client->getRanksServerLeader();
718       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
719         event.push(*itRank,1,msg);
720       client->sendEvent(event);
721     }
722     else client->sendEvent(event);
723   }
724
725   //! Server side: Receive a message of client announcing a context close
726   void CContext::recvCloseDefinition(CEventServer& event)
727   {
728
729      CBufferIn* buffer=event.subEvents.begin()->buffer;
730      string id;
731      *buffer>>id;
732      get(id)->closeDefinition();
733   }
734
735   //! Client side: Send a message to update calendar in each time step
736   void CContext::sendUpdateCalendar(int step)
737   {
738     if (!hasServer)
739     {
740       CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR);
741       if (client->isServerLeader())
742       {
743         CMessage msg;
744         msg<<this->getIdServer()<<step;
745         const std::list<int>& ranks = client->getRanksServerLeader();
746         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
747           event.push(*itRank,1,msg);
748         client->sendEvent(event);
749       }
750       else client->sendEvent(event);
751     }
752   }
753
754   //! Server side: Receive a message of client annoucing calendar update
755   void CContext::recvUpdateCalendar(CEventServer& event)
756   {
757      CBufferIn* buffer=event.subEvents.begin()->buffer;
758      string id;
759      *buffer>>id;
760      get(id)->recvUpdateCalendar(*buffer);
761   }
762
763   //! Server side: Receive a message of client annoucing calendar update
764   void CContext::recvUpdateCalendar(CBufferIn& buffer)
765   {
766      int step;
767      buffer>>step;
768      updateCalendar(step);
769   }
770
771   //! Client side: Send a message to create header part of netcdf file
772   void CContext::sendCreateFileHeader(void)
773   {
774     CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER);
775     if (client->isServerLeader())
776     {
777       CMessage msg;
778       msg<<this->getIdServer();
779       const std::list<int>& ranks = client->getRanksServerLeader();
780       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
781         event.push(*itRank,1,msg) ;
782       client->sendEvent(event);
783     }
784     else client->sendEvent(event);
785   }
786
787   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
788   void CContext::recvCreateFileHeader(CEventServer& event)
789   {
790      CBufferIn* buffer=event.subEvents.begin()->buffer;
791      string id;
792      *buffer>>id;
793      get(id)->recvCreateFileHeader(*buffer);
794   }
795
796   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
797   void CContext::recvCreateFileHeader(CBufferIn& buffer)
798   {
799      createFileHeader();
800   }
801
802   //! Client side: Send a message to do some post processing on server
803   void CContext::sendPostProcessing()
804   {
805     if (!hasServer)
806     {
807       CEventClient event(getType(),EVENT_ID_POST_PROCESS);
808       if (client->isServerLeader())
809       {
810         CMessage msg;
811         msg<<this->getIdServer();
812         const std::list<int>& ranks = client->getRanksServerLeader();
813         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
814           event.push(*itRank,1,msg);
815         client->sendEvent(event);
816       }
817       else client->sendEvent(event);
818     }
819   }
820
821   //! Server side: Receive a message to do some post processing
822   void CContext::recvPostProcessing(CEventServer& event)
823   {
824      CBufferIn* buffer=event.subEvents.begin()->buffer;
825      string id;
826      *buffer>>id;
827      get(id)->recvPostProcessing(*buffer);
828   }
829
830   //! Server side: Receive a message to do some post processing
831   void CContext::recvPostProcessing(CBufferIn& buffer)
832   {
833      CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar();
834      postProcessing();
835   }
836
837   const StdString& CContext::getIdServer()
838   {
839      if (hasClient)
840      {
841        idServer_ = this->getId();
842        idServer_ += "_server";
843        return idServer_;
844      }
845      if (hasServer) return (this->getId());
846   }
847
848   /*!
849   \brief Do some simple post processings after parsing xml file
850      After the xml file (iodef.xml) is parsed, it is necessary to build all relations among
851   created object, e.g: inhertance among fields, domain, axis. After that, all fiels as well as their parents (reference fields),
852   which will be written out into netcdf files, are processed
853   */
854   void CContext::postProcessing()
855   {
856     if (isPostProcessed) return;
857
858      // Make sure the calendar was correctly created
859      if (!calendar)
860        ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"")
861      else if (calendar->getTimeStep() == NoneDu)
862        ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"")
863      // Calendar first update to set the current date equals to the start date
864      calendar->update(0);
865
866      // Find all inheritance in xml structure
867      this->solveAllInheritance();
868
869      // Check if some axis, domains or grids are eligible to for compressed indexed output.
870      // Warning: This must be done after solving the inheritance and before the rest of post-processing
871      checkAxisDomainsGridsEligibilityForCompressedOutput();
872
873      // Check if some automatic time series should be generated
874      // Warning: This must be done after solving the inheritance and before the rest of post-processing
875      prepareTimeseries();
876
877      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
878      this->findEnabledFiles();
879      this->findEnabledReadModeFiles();
880
881      // Find all enabled fields of each file
882      this->findAllEnabledFields();
883      this->findAllEnabledFieldsInReadModeFiles();
884
885     if (hasClient && !hasServer)
886     {
887      // Try to read attributes of fields in file then fill in corresponding grid (or domain, axis)
888      this->readAttributesOfEnabledFieldsInReadModeFiles();
889     }
890
891      // Only search and rebuild all reference objects of enable fields, don't transform
892      this->solveOnlyRefOfEnabledFields(false);
893
894      // Search and rebuild all reference object of enabled fields
895      this->solveAllRefOfEnabledFields(false);
896
897      // Find all fields with read access from the public API
898      findFieldsWithReadAccess();
899      // and solve the all reference for them
900      solveAllRefOfFieldsWithReadAccess();
901
902      isPostProcessed = true;
903   }
904
905   /*!
906    * Compute the required buffer size to send the attributes (mostly those grid related).
907    *
908    * \param maxEventSize [in/out] the size of the bigger event for each connected server
909    */
910   std::map<int, StdSize> CContext::getAttributesBufferSize(std::map<int, StdSize>& maxEventSize)
911   {
912     std::map<int, StdSize> attributesSize;
913
914     if (hasClient)
915     {
916       size_t numEnabledFiles = this->enabledFiles.size();
917       for (size_t i = 0; i < numEnabledFiles; ++i)
918       {
919         CFile* file = this->enabledFiles[i];
920
921         std::vector<CField*> enabledFields = file->getEnabledFields();
922         size_t numEnabledFields = enabledFields.size();
923         for (size_t j = 0; j < numEnabledFields; ++j)
924         {
925           const std::map<int, StdSize> mapSize = enabledFields[j]->getGridAttributesBufferSize();
926           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
927           for (; it != itE; ++it)
928           {
929             // If attributesSize[it->first] does not exist, it will be zero-initialized
930             // so we can use it safely without checking for its existance
931             if (attributesSize[it->first] < it->second)
932               attributesSize[it->first] = it->second;
933
934             if (maxEventSize[it->first] < it->second)
935               maxEventSize[it->first] = it->second;
936           }
937         }
938       }
939     }
940
941     return attributesSize;
942   }
943
944   /*!
945    * Compute the required buffer size to send the fields data.
946    *
947    * \param maxEventSize [in/out] the size of the bigger event for each connected server
948    */
949   std::map<int, StdSize> CContext::getDataBufferSize(std::map<int, StdSize>& maxEventSize)
950   {
951     CFile::mode_attr::t_enum mode = hasClient ? CFile::mode_attr::write : CFile::mode_attr::read;
952
953     std::map<int, StdSize> dataSize;
954
955     // Find all reference domain and axis of all active fields
956     size_t numEnabledFiles = this->enabledFiles.size();
957     for (size_t i = 0; i < numEnabledFiles; ++i)
958     {
959       CFile* file = this->enabledFiles[i];
960       CFile::mode_attr::t_enum fileMode = file->mode.isEmpty() ? CFile::mode_attr::write : file->mode.getValue();
961
962       if (fileMode == mode)
963       {
964         std::vector<CField*> enabledFields = file->getEnabledFields();
965         size_t numEnabledFields = enabledFields.size();
966         for (size_t j = 0; j < numEnabledFields; ++j)
967         {
968           const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataBufferSize();
969           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
970           for (; it != itE; ++it)
971           {
972             // If dataSize[it->first] does not exist, it will be zero-initialized
973             // so we can use it safely without checking for its existance
974             if (CXios::isOptPerformance)
975               dataSize[it->first] += it->second;
976             else if (dataSize[it->first] < it->second)
977               dataSize[it->first] = it->second;
978
979             if (maxEventSize[it->first] < it->second)
980               maxEventSize[it->first] = it->second;
981           }
982         }
983       }
984     }
985
986     return dataSize;
987   }
988
989   //! Client side: Send infomation of active files (files are enabled to write out)
990   void CContext::sendEnabledFiles()
991   {
992     int size = this->enabledFiles.size();
993
994     // In a context, each type has a root definition, e.g: axis, domain, field.
995     // Every object must be a child of one of these root definition. In this case
996     // all new file objects created on server must be children of the root "file_definition"
997     StdString fileDefRoot("file_definition");
998     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
999
1000     for (int i = 0; i < size; ++i)
1001     {
1002       cfgrpPtr->sendCreateChild(this->enabledFiles[i]->getId());
1003       this->enabledFiles[i]->sendAllAttributesToServer();
1004       this->enabledFiles[i]->sendAddAllVariables();
1005     }
1006   }
1007
1008   //! Client side: Send information of active fields (ones are written onto files)
1009   void CContext::sendEnabledFields()
1010   {
1011     int size = this->enabledFiles.size();
1012     for (int i = 0; i < size; ++i)
1013     {
1014       this->enabledFiles[i]->sendEnabledFields();
1015     }
1016   }
1017
1018   //! Client side: Check if the defined axis, domains and grids are eligible for compressed indexed output
1019   void CContext::checkAxisDomainsGridsEligibilityForCompressedOutput()
1020   {
1021     if (!hasClient) return;
1022
1023     const vector<CAxis*> allAxis = CAxis::getAll();
1024     for (vector<CAxis*>::const_iterator it = allAxis.begin(); it != allAxis.end(); it++)
1025       (*it)->checkEligibilityForCompressedOutput();
1026
1027     const vector<CDomain*> allDomains = CDomain::getAll();
1028     for (vector<CDomain*>::const_iterator it = allDomains.begin(); it != allDomains.end(); it++)
1029       (*it)->checkEligibilityForCompressedOutput();
1030
1031     const vector<CGrid*> allGrids = CGrid::getAll();
1032     for (vector<CGrid*>::const_iterator it = allGrids.begin(); it != allGrids.end(); it++)
1033       (*it)->checkEligibilityForCompressedOutput();
1034   }
1035
1036   //! Client side: Prepare the timeseries by adding the necessary files
1037   void CContext::prepareTimeseries()
1038   {
1039     if (!hasClient) return;
1040
1041     const std::vector<CFile*> allFiles = CFile::getAll();
1042     for (size_t i = 0; i < allFiles.size(); i++)
1043     {
1044       CFile* file = allFiles[i];
1045
1046       std::vector<CVariable*> fileVars, fieldVars, vars = file->getAllVariables();
1047       for (size_t k = 0; k < vars.size(); k++)
1048       {
1049         CVariable* var = vars[k];
1050
1051         if (var->ts_target.isEmpty()
1052              || var->ts_target == CVariable::ts_target_attr::file || var->ts_target == CVariable::ts_target_attr::both)
1053           fileVars.push_back(var);
1054
1055         if (!var->ts_target.isEmpty()
1056              && (var->ts_target == CVariable::ts_target_attr::field || var->ts_target == CVariable::ts_target_attr::both))
1057           fieldVars.push_back(var);
1058       }
1059
1060       if (!file->timeseries.isEmpty() && file->timeseries != CFile::timeseries_attr::none)
1061       {
1062         StdString fileNameStr("%file_name%") ;
1063         StdString tsPrefix = !file->ts_prefix.isEmpty() ? file->ts_prefix : fileNameStr ;
1064         
1065         StdString fileName=file->getFileOutputName();
1066         size_t pos=tsPrefix.find(fileNameStr) ;
1067         while (pos!=std::string::npos)
1068         {
1069           tsPrefix=tsPrefix.replace(pos,fileNameStr.size(),fileName) ;
1070           pos=tsPrefix.find(fileNameStr) ;
1071         }
1072       
1073         const std::vector<CField*> allFields = file->getAllFields();
1074         for (size_t j = 0; j < allFields.size(); j++)
1075         {
1076           CField* field = allFields[j];
1077
1078           if (!field->ts_enabled.isEmpty() && field->ts_enabled)
1079           {
1080             CFile* tsFile = CFile::create();
1081             tsFile->duplicateAttributes(file);
1082
1083             // Add variables originating from file and targeted to timeserie file
1084             for (size_t k = 0; k < fileVars.size(); k++)
1085               tsFile->getVirtualVariableGroup()->addChild(fileVars[k]);
1086
1087           
1088             tsFile->name = tsPrefix + "_";
1089             if (!field->name.isEmpty())
1090               tsFile->name.get() += field->name;
1091             else if (field->hasDirectFieldReference()) // We cannot use getBaseFieldReference() just yet
1092               tsFile->name.get() += field->field_ref;
1093             else
1094               tsFile->name.get() += field->getId();
1095
1096             if (!field->ts_split_freq.isEmpty())
1097               tsFile->split_freq = field->ts_split_freq;
1098
1099             CField* tsField = tsFile->addField();
1100             tsField->field_ref = field->getId();
1101
1102             // Add variables originating from file and targeted to timeserie field
1103             for (size_t k = 0; k < fieldVars.size(); k++)
1104               tsField->getVirtualVariableGroup()->addChild(fieldVars[k]);
1105
1106             vars = field->getAllVariables();
1107             for (size_t k = 0; k < vars.size(); k++)
1108             {
1109               CVariable* var = vars[k];
1110
1111               // Add variables originating from field and targeted to timeserie field
1112               if (var->ts_target.isEmpty()
1113                    || var->ts_target == CVariable::ts_target_attr::field || var->ts_target == CVariable::ts_target_attr::both)
1114                 tsField->getVirtualVariableGroup()->addChild(var);
1115
1116               // Add variables originating from field and targeted to timeserie file
1117               if (!var->ts_target.isEmpty()
1118                    && (var->ts_target == CVariable::ts_target_attr::file || var->ts_target == CVariable::ts_target_attr::both))
1119                 tsFile->getVirtualVariableGroup()->addChild(var);
1120             }
1121
1122             tsFile->solveFieldRefInheritance(true);
1123
1124             if (file->timeseries == CFile::timeseries_attr::exclusive)
1125               field->enabled = false;
1126           }
1127         }
1128
1129         // Finally disable the original file is need be
1130         if (file->timeseries == CFile::timeseries_attr::only)
1131          file->enabled = false;
1132       }
1133     }
1134   }
1135
1136   //! Client side: Send information of reference grid of active fields
1137   void CContext::sendRefGrid()
1138   {
1139     std::set<StdString> gridIds;
1140     int sizeFile = this->enabledFiles.size();
1141     CFile* filePtr(NULL);
1142
1143     // Firstly, find all reference grids of all active fields
1144     for (int i = 0; i < sizeFile; ++i)
1145     {
1146       filePtr = this->enabledFiles[i];
1147       std::vector<CField*> enabledFields = filePtr->getEnabledFields();
1148       int sizeField = enabledFields.size();
1149       for (int numField = 0; numField < sizeField; ++numField)
1150       {
1151         if (0 != enabledFields[numField]->getRelGrid())
1152           gridIds.insert(CGrid::get(enabledFields[numField]->getRelGrid())->getId());
1153       }
1154     }
1155
1156     // Create all reference grids on server side
1157     StdString gridDefRoot("grid_definition");
1158     CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
1159     std::set<StdString>::const_iterator it, itE = gridIds.end();
1160     for (it = gridIds.begin(); it != itE; ++it)
1161     {
1162       gridPtr->sendCreateChild(*it);
1163       CGrid::get(*it)->sendAllAttributesToServer();
1164       CGrid::get(*it)->sendAllDomains();
1165       CGrid::get(*it)->sendAllAxis();
1166       CGrid::get(*it)->sendAllScalars();
1167     }
1168   }
1169
1170
1171   //! Client side: Send information of reference domain and axis of active fields
1172   void CContext::sendRefDomainsAxis()
1173   {
1174     std::set<StdString> domainIds, axisIds, scalarIds;
1175
1176     // Find all reference domain and axis of all active fields
1177     int numEnabledFiles = this->enabledFiles.size();
1178     for (int i = 0; i < numEnabledFiles; ++i)
1179     {
1180       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
1181       int numEnabledFields = enabledFields.size();
1182       for (int j = 0; j < numEnabledFields; ++j)
1183       {
1184         const std::vector<StdString>& prDomAxisScalarId = enabledFields[j]->getRefDomainAxisIds();
1185         if ("" != prDomAxisScalarId[0]) domainIds.insert(prDomAxisScalarId[0]);
1186         if ("" != prDomAxisScalarId[1]) axisIds.insert(prDomAxisScalarId[1]);
1187         if ("" != prDomAxisScalarId[2]) scalarIds.insert(prDomAxisScalarId[2]);
1188       }
1189     }
1190
1191     // Create all reference axis on server side
1192     std::set<StdString>::iterator itDom, itAxis, itScalar;
1193     std::set<StdString>::const_iterator itE;
1194
1195     StdString scalarDefRoot("scalar_definition");
1196     CScalarGroup* scalarPtr = CScalarGroup::get(scalarDefRoot);
1197     itE = scalarIds.end();
1198     for (itScalar = scalarIds.begin(); itScalar != itE; ++itScalar)
1199     {
1200       if (!itScalar->empty())
1201       {
1202         scalarPtr->sendCreateChild(*itScalar);
1203         CScalar::get(*itScalar)->sendAllAttributesToServer();
1204       }
1205     }
1206
1207     StdString axiDefRoot("axis_definition");
1208     CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
1209     itE = axisIds.end();
1210     for (itAxis = axisIds.begin(); itAxis != itE; ++itAxis)
1211     {
1212       if (!itAxis->empty())
1213       {
1214         axisPtr->sendCreateChild(*itAxis);
1215         CAxis::get(*itAxis)->sendAllAttributesToServer();
1216       }
1217     }
1218
1219     // Create all reference domains on server side
1220     StdString domDefRoot("domain_definition");
1221     CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
1222     itE = domainIds.end();
1223     for (itDom = domainIds.begin(); itDom != itE; ++itDom)
1224     {
1225       if (!itDom->empty()) {
1226          domPtr->sendCreateChild(*itDom);
1227          CDomain::get(*itDom)->sendAllAttributesToServer();
1228       }
1229     }
1230   }
1231
1232   //! Update calendar in each time step
1233   void CContext::updateCalendar(int step)
1234   {
1235      int prevStep = calendar->getStep();
1236
1237      if (prevStep < step)
1238      {
1239        if (hasClient)
1240        {
1241          doPreTimestepOperationsForEnabledReadModeFiles();
1242        }
1243
1244        info(50) << "updateCalendar : before : " << calendar->getCurrentDate() << endl;
1245        calendar->update(step);
1246        info(50) << "updateCalendar : after : " << calendar->getCurrentDate() << endl;
1247  #ifdef XIOS_MEMTRACK_LIGHT
1248        info(50) << " Current memory used by XIOS : "<<  MemTrack::getCurrentMemorySize()*1.0/(1024*1024)<<" Mbyte, at timestep "<<step<<" of context "<<this->getId()<<endl ;
1249  #endif
1250
1251        if (hasClient)
1252        {
1253          doPostTimestepOperationsForEnabledReadModeFiles();
1254          garbageCollector.invalidate(calendar->getCurrentDate());
1255        }
1256      }
1257      else if (prevStep == step)
1258        info(50) << "updateCalendar: already at step " << step << ", no operation done." << endl;
1259      else // if (prevStep > step)
1260        ERROR("void CContext::updateCalendar(int step)",
1261              << "Illegal calendar update: previous step was " << prevStep << ", new step " << step << "is in the past!")
1262   }
1263
1264   //! Server side: Create header of netcdf file
1265   void CContext::createFileHeader(void )
1266   {
1267      vector<CFile*>::const_iterator it;
1268
1269      for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
1270      {
1271         (*it)->initFile();
1272      }
1273   }
1274
1275   //! Get current context
1276   CContext* CContext::getCurrent(void)
1277   {
1278     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get();
1279   }
1280
1281   /*!
1282   \brief Set context with an id be the current context
1283   \param [in] id identity of context to be set to current
1284   */
1285   void CContext::setCurrent(const string& id)
1286   {
1287     CObjectFactory::SetCurrentContextId(id);
1288     CGroupFactory::SetCurrentContextId(id);
1289   }
1290
1291  /*!
1292  \brief Create a context with specific id
1293  \param [in] id identity of new context
1294  \return pointer to the new context or already-existed one with identity id
1295  */
1296  CContext* CContext::create(const StdString& id)
1297  {
1298    CContext::setCurrent(id);
1299
1300    bool hasctxt = CContext::has(id);
1301    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
1302    getRoot();
1303    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
1304
1305#define DECLARE_NODE(Name_, name_) \
1306    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
1307#define DECLARE_NODE_PAR(Name_, name_)
1308#include "node_type.conf"
1309
1310    return (context);
1311  }
1312
1313
1314
1315     //! Server side: Receive a message to do some post processing
1316  void CContext::recvRegistry(CEventServer& event)
1317  {
1318    CBufferIn* buffer=event.subEvents.begin()->buffer;
1319    string id;
1320    *buffer>>id;
1321    get(id)->recvRegistry(*buffer);
1322  }
1323
1324  void CContext::recvRegistry(CBufferIn& buffer)
1325  {
1326    if (server->intraCommRank==0)
1327    {
1328      CRegistry registry(server->intraComm) ;
1329      registry.fromBuffer(buffer) ;
1330      registryOut->mergeRegistry(registry) ;
1331    }
1332  }
1333
1334  void CContext::sendRegistry(void)
1335  {
1336    registryOut->hierarchicalGatherRegistry() ;
1337
1338    CEventClient event(CContext::GetType(), CContext::EVENT_ID_SEND_REGISTRY);
1339    if (client->isServerLeader())
1340    {
1341       CMessage msg ;
1342       msg<<this->getIdServer();
1343       if (client->clientRank==0) msg<<*registryOut ;
1344       const std::list<int>& ranks = client->getRanksServerLeader();
1345       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1346         event.push(*itRank,1,msg);
1347       client->sendEvent(event);
1348     }
1349     else client->sendEvent(event);
1350  }
1351
1352} // namespace xios
Note: See TracBrowser for help on using the repository browser.