source: XIOS/dev/dev_olga/src/node/context.cpp @ 983

Last change on this file since 983 was 983, checked in by oabramkina, 5 years ago

My branch

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