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

Last change on this file since 987 was 987, checked in by mhnguyen, 7 years ago

First working version.
There are more things to do with it

  • 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: 50.2 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    // We have a xml tree on the server side and now, it should be also processed
524   // if (hasClient && !hasServer) sendPostProcessing();
525
526//     // Now tell server that it can process all messages from client
527// //    if (hasClient && !hasServer) this->sendCloseDefinition();
528     if (hasClient) this->sendCloseDefinition();
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
540
541//    // Now tell server that it can process all messages from client
542////    if (hasClient && !hasServer) this->sendCloseDefinition();
543//    if (hasClient) this->sendCloseDefinition();
544
545    // Nettoyage de l'arborescence
546//    if (hasClient && !hasServer) CleanTree(); // Only on client side??
547    if (hasClient) CleanTree(); // Only on client side??
548
549    if (hasClient)
550    {
551      sendCreateFileHeader();
552      if (!hasServer) startPrefetchingOfEnabledReadModeFiles();
553    }
554   }
555
556   void CContext::findAllEnabledFields(void)
557   {
558     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
559     (void)this->enabledFiles[i]->getEnabledFields();
560   }
561
562   void CContext::findAllEnabledFieldsInReadModeFiles(void)
563   {
564     for (unsigned int i = 0; i < this->enabledReadModeFiles.size(); ++i)
565     (void)this->enabledReadModeFiles[i]->getEnabledFields();
566   }
567
568   void CContext::readAttributesOfEnabledFieldsInReadModeFiles()
569   {
570      for (unsigned int i = 0; i < this->enabledReadModeFiles.size(); ++i)
571        (void)this->enabledReadModeFiles[i]->readAttributesOfEnabledFieldsInReadMode();
572   }
573
574   void CContext::solveOnlyRefOfEnabledFields(bool sendToServer)
575   {
576     int size = this->enabledFiles.size();
577     for (int i = 0; i < size; ++i)
578     {
579       this->enabledFiles[i]->solveOnlyRefOfEnabledFields(sendToServer);
580     }
581
582     for (int i = 0; i < size; ++i)
583     {
584       this->enabledFiles[i]->generateNewTransformationGridDest();
585     }
586   }
587
588   void CContext::solveAllRefOfEnabledFields(bool sendToServer)
589   {
590     int size = this->enabledFiles.size();
591     for (int i = 0; i < size; ++i)
592     {
593       this->enabledFiles[i]->solveAllRefOfEnabledFields(sendToServer);
594     }
595   }
596
597   void CContext::buildFilterGraphOfEnabledFields()
598   {
599     int size = this->enabledFiles.size();
600     for (int i = 0; i < size; ++i)
601     {
602       this->enabledFiles[i]->buildFilterGraphOfEnabledFields(garbageCollector);
603     }
604   }
605
606   void CContext::startPrefetchingOfEnabledReadModeFiles()
607   {
608     int size = enabledReadModeFiles.size();
609     for (int i = 0; i < size; ++i)
610     {
611        enabledReadModeFiles[i]->prefetchEnabledReadModeFields();
612     }
613   }
614
615   void CContext::checkPrefetchingOfEnabledReadModeFiles()
616   {
617     int size = enabledReadModeFiles.size();
618     for (int i = 0; i < size; ++i)
619     {
620        enabledReadModeFiles[i]->prefetchEnabledReadModeFieldsIfNeeded();
621     }
622   }
623
624  void CContext::findFieldsWithReadAccess(void)
625  {
626    fieldsWithReadAccess.clear();
627    const vector<CField*> allFields = CField::getAll();
628    for (size_t i = 0; i < allFields.size(); ++i)
629    {
630      CField* field = allFields[i];
631
632      if (field->file && !field->file->mode.isEmpty() && field->file->mode == CFile::mode_attr::read)
633        field->read_access = true;
634      else if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled))
635        fieldsWithReadAccess.push_back(field);
636    }
637  }
638
639  void CContext::solveAllRefOfFieldsWithReadAccess()
640  {
641    for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
642      fieldsWithReadAccess[i]->solveAllReferenceEnabledField(false);
643  }
644
645  void CContext::buildFilterGraphOfFieldsWithReadAccess()
646  {
647    for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
648      fieldsWithReadAccess[i]->buildFilterGraph(garbageCollector, true);
649  }
650
651   void CContext::solveAllInheritance(bool apply)
652   {
653     // Résolution des héritages descendants (càd des héritages de groupes)
654     // pour chacun des contextes.
655      solveDescInheritance(apply);
656
657     // Résolution des héritages par référence au niveau des fichiers.
658      const vector<CFile*> allFiles=CFile::getAll();
659      const vector<CGrid*> allGrids= CGrid::getAll();
660
661      if (hasClient && !hasServer)
662      //if (hasClient)
663      {
664        for (unsigned int i = 0; i < allFiles.size(); i++)
665          allFiles[i]->solveFieldRefInheritance(apply);
666      }
667
668      unsigned int vecSize = allGrids.size();
669      unsigned int i = 0;
670      for (i = 0; i < vecSize; ++i)
671        allGrids[i]->solveDomainAxisRefInheritance(apply);
672
673   }
674
675   void CContext::findEnabledFiles(void)
676   {
677      const std::vector<CFile*> allFiles = CFile::getAll();
678
679      for (unsigned int i = 0; i < allFiles.size(); i++)
680         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
681         {
682            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
683               enabledFiles.push_back(allFiles[i]);
684         }
685         else enabledFiles.push_back(allFiles[i]); // otherwise true by default
686
687
688      if (enabledFiles.size() == 0)
689         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
690               << getId() << "\" !");
691   }
692
693   void CContext::findEnabledReadModeFiles(void)
694   {
695     int size = this->enabledFiles.size();
696     for (int i = 0; i < size; ++i)
697     {
698       if (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::read)
699        enabledReadModeFiles.push_back(enabledFiles[i]);
700     }
701   }
702
703   void CContext::closeAllFile(void)
704   {
705     std::vector<CFile*>::const_iterator
706            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
707
708     for (; it != end; it++)
709     {
710       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
711       (*it)->close();
712     }
713   }
714
715   /*!
716   \brief Dispatch event received from client
717      Whenever a message is received in buffer of server, it will be processed depending on
718   its event type. A new event type should be added in the switch list to make sure
719   it processed on server side.
720   \param [in] event: Received message
721   */
722   bool CContext::dispatchEvent(CEventServer& event)
723   {
724
725      if (SuperClass::dispatchEvent(event)) return true;
726      else
727      {
728        switch(event.type)
729        {
730           case EVENT_ID_CLOSE_DEFINITION :
731             recvCloseDefinition(event);
732             return true;
733             break;
734           case EVENT_ID_UPDATE_CALENDAR:
735             recvUpdateCalendar(event);
736             return true;
737             break;
738           case EVENT_ID_CREATE_FILE_HEADER :
739             recvCreateFileHeader(event);
740             return true;
741             break;
742           case EVENT_ID_POST_PROCESS:
743             recvPostProcessing(event);
744             return true;
745            case EVENT_ID_SEND_REGISTRY:
746             recvRegistry(event);
747             return true;
748            break;
749
750           default :
751             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
752                    <<"Unknown Event");
753           return false;
754         }
755      }
756   }
757
758//   // Only send close definition from process having hasClient
759//   void CContext::sendCloseDefinitionToServer(void)
760//   {
761//     CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
762//   }
763
764   //! Client side: Send a message to server to make it close
765   void CContext::sendCloseDefinition(void)
766   {
767     // Use correct context client to send message
768     CContextClient* contextClientTmp = (0 != clientPrimServer) ? clientPrimServer : client;
769     CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
770
771     if (contextClientTmp->isServerLeader())
772     {
773       CMessage msg;
774       msg<<this->getIdServer();
775       const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
776       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
777         event.push(*itRank,1,msg);
778       contextClientTmp->sendEvent(event);
779     }
780     else contextClientTmp->sendEvent(event);
781
782     // if (!hasServer)
783     // {
784     //   if (client->isServerLeader())
785     //   {
786     //     CMessage msg;
787     //     msg<<this->getIdServer();
788     //     const std::list<int>& ranks = client->getRanksServerLeader();
789     //     for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
790     //       event.push(*itRank,1,msg);
791     //     client->sendEvent(event);
792     //   }
793     //   else client->sendEvent(event);
794     // }
795     // else
796     // {
797     //   if (clientPrimServer->isServerLeader())
798     //   {
799     //     CMessage msg;
800     //     msg<<this->getIdServer();
801     //     const std::list<int>& ranks = clientPrimServer->getRanksServerLeader();
802     //     for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
803     //       event.push(*itRank,1,msg);
804     //     clientPrimServer->sendEvent(event);
805     //   }
806     //   else clientPrimServer->sendEvent(event);
807
808     // }
809   }
810
811   //! Server side: Receive a message of client announcing a context close
812   void CContext::recvCloseDefinition(CEventServer& event)
813   {
814      CBufferIn* buffer=event.subEvents.begin()->buffer;
815      string id;
816      *buffer>>id;
817      get(id)->closeDefinition();
818      if (get(id)->hasClient && get(id)->hasServer)
819      {       
820        get(id)->sendCloseDefinition();
821      }
822   }
823
824   //! Client side: Send a message to update calendar in each time step
825   void CContext::sendUpdateCalendar(int step)
826   {
827     // Use correct context client to send message
828     CContextClient* contextClientTmp = (0 != clientPrimServer) ? clientPrimServer : client;
829     CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR);
830
831       if (contextClientTmp->isServerLeader())
832       {
833         CMessage msg;
834         msg<<this->getIdServer()<<step;
835         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
836         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
837           event.push(*itRank,1,msg);
838         contextClientTmp->sendEvent(event);
839       }
840       else contextClientTmp->sendEvent(event);
841
842     // if (!hasServer)
843     // {
844     //   if (client->isServerLeader())
845     //   {
846     //     CMessage msg;
847     //     msg<<this->getIdServer()<<step;
848     //     const std::list<int>& ranks = client->getRanksServerLeader();
849     //     for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
850     //       event.push(*itRank,1,msg);
851     //     client->sendEvent(event);
852     //   }
853     //   else client->sendEvent(event);
854     // }
855     // else
856     // {
857     //   if (clientPrimServer->isServerLeader())
858     //   {
859     //     CMessage msg;
860     //     msg<<this->getIdServer()<<step;
861     //     const std::list<int>& ranks = clientPrimServer->getRanksServerLeader();
862     //     for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
863     //       event.push(*itRank,1,msg);
864     //     clientPrimServer->sendEvent(event);
865     //   }
866     //   else clientPrimServer->sendEvent(event);
867     // }
868   }
869
870   //! Server side: Receive a message of client annoucing calendar update
871   void CContext::recvUpdateCalendar(CEventServer& event)
872   {
873      CBufferIn* buffer=event.subEvents.begin()->buffer;
874      string id;
875      *buffer>>id;
876      get(id)->recvUpdateCalendar(*buffer);
877   }
878
879   //! Server side: Receive a message of client annoucing calendar update
880   void CContext::recvUpdateCalendar(CBufferIn& buffer)
881   {
882      int step;
883      buffer>>step;
884      updateCalendar(step);
885      if (hasClient && hasServer)
886      {       
887        sendUpdateCalendar(step);
888      }
889   }
890
891   //! Client side: Send a message to create header part of netcdf file
892   void CContext::sendCreateFileHeader(void)
893   {
894     // Use correct context client to send message
895     CContextClient* contextClientTmp = (0 != clientPrimServer) ? clientPrimServer : client;
896     CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER);
897
898     if (contextClientTmp->isServerLeader())
899     {
900       CMessage msg;
901       msg<<this->getIdServer();
902       const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
903       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
904         event.push(*itRank,1,msg) ;
905       contextClientTmp->sendEvent(event);
906     }
907     else contextClientTmp->sendEvent(event);
908
909     // if (!hasServer)
910     // {
911     //   if (client->isServerLeader())
912     //   {
913     //     CMessage msg;
914     //     msg<<this->getIdServer();
915     //     const std::list<int>& ranks = client->getRanksServerLeader();
916     //     for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
917     //       event.push(*itRank,1,msg) ;
918     //     client->sendEvent(event);
919     //   }
920     //   else client->sendEvent(event);
921     // }
922     // else
923     // {
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   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
938   void CContext::recvCreateFileHeader(CEventServer& event)
939   {
940      CBufferIn* buffer=event.subEvents.begin()->buffer;
941      string id;
942      *buffer>>id;
943      get(id)->recvCreateFileHeader(*buffer);
944   }
945
946   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
947   void CContext::recvCreateFileHeader(CBufferIn& buffer)
948   {
949     // The creation of header file should be delegated to server2, for now
950      if (hasClient && hasServer)
951      {       
952        sendCreateFileHeader();
953      }
954     
955      if (!hasClient && hasServer) 
956        createFileHeader();
957   }
958
959   //! Client side: Send a message to do some post processing on server
960   void CContext::sendPostProcessing()
961   {
962      // Use correct context client to send message
963     CContextClient* contextClientTmp = (0 != clientPrimServer) ? clientPrimServer : client;
964     CEventClient event(getType(),EVENT_ID_POST_PROCESS);
965
966     if (contextClientTmp->isServerLeader())
967     {
968       CMessage msg;
969       msg<<this->getIdServer();
970       const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
971       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
972         event.push(*itRank,1,msg);
973       contextClientTmp->sendEvent(event);
974     }
975     else contextClientTmp->sendEvent(event);
976
977     // if (hasClient)
978     // {
979     //   if (!hasServer)
980     //   {
981     //     CEventClient event(getType(),EVENT_ID_POST_PROCESS);
982     //     if (client->isServerLeader())
983     //     {
984     //       CMessage msg;
985     //       msg<<this->getIdServer();
986     //       const std::list<int>& ranks = client->getRanksServerLeader();
987     //       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
988     //         event.push(*itRank,1,msg);
989     //       client->sendEvent(event);
990     //     }
991     //     else client->sendEvent(event);
992     //   }
993     //   else
994     //   {
995     //     CEventClient event(getType(),EVENT_ID_POST_PROCESS);
996     //     if (clientPrimServer->isServerLeader())
997     //     {
998     //       CMessage msg;
999     //       msg<<this->getIdServer();
1000     //       const std::list<int>& ranks = clientPrimServer->getRanksServerLeader();
1001     //       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1002     //         event.push(*itRank,1,msg);
1003     //       clientPrimServer->sendEvent(event);
1004     //     }
1005     //     else clientPrimServer->sendEvent(event);
1006     //   }
1007     // }
1008   }
1009
1010   //! Server side: Receive a message to do some post processing
1011   void CContext::recvPostProcessing(CEventServer& event)
1012   {
1013      CBufferIn* buffer=event.subEvents.begin()->buffer;
1014      string id;
1015      *buffer>>id;
1016      get(id)->recvPostProcessing(*buffer);
1017   }
1018
1019   //! Server side: Receive a message to do some post processing
1020   void CContext::recvPostProcessing(CBufferIn& buffer)
1021   {
1022      CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar();
1023      postProcessing();
1024   }
1025
1026   const StdString& CContext::getIdServer()
1027   {
1028      if (hasClient)
1029      {
1030        idServer_ = this->getId();
1031        idServer_ += "_server";
1032        return idServer_;
1033      }
1034      if (hasServer) return (this->getId());
1035   }
1036
1037   /*!
1038   \brief Do some simple post processings after parsing xml file
1039      After the xml file (iodef.xml) is parsed, it is necessary to build all relations among
1040   created object, e.g: inhertance among fields, domain, axis. After that, all fiels as well as their parents (reference fields),
1041   which will be written out into netcdf files, are processed
1042   */
1043   void CContext::postProcessing()
1044   {
1045     if (isPostProcessed) return;
1046
1047      // Make sure the calendar was correctly created
1048      if (!calendar)
1049        ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"")
1050      else if (calendar->getTimeStep() == NoneDu)
1051        ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"")
1052      // Calendar first update to set the current date equals to the start date
1053      calendar->update(0);
1054
1055      // Find all inheritance in xml structure
1056      this->solveAllInheritance();
1057
1058      ShowTree(info(10));
1059
1060      // Check if some axis, domains or grids are eligible to for compressed indexed output.
1061      // Warning: This must be done after solving the inheritance and before the rest of post-processing
1062      checkAxisDomainsGridsEligibilityForCompressedOutput();
1063
1064      // Check if some automatic time series should be generated
1065      // Warning: This must be done after solving the inheritance and before the rest of post-processing
1066      prepareTimeseries();
1067
1068      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
1069      this->findEnabledFiles();
1070      this->findEnabledReadModeFiles();
1071
1072      // Find all enabled fields of each file
1073      this->findAllEnabledFields();
1074      this->findAllEnabledFieldsInReadModeFiles();
1075
1076//     if (hasClient)
1077     if (hasClient && !hasServer)
1078     {
1079      // Try to read attributes of fields in file then fill in corresponding grid (or domain, axis)
1080      this->readAttributesOfEnabledFieldsInReadModeFiles();
1081     }
1082
1083      // Only search and rebuild all reference objects of enable fields, don't transform
1084      this->solveOnlyRefOfEnabledFields(false);
1085
1086      // Search and rebuild all reference object of enabled fields
1087      this->solveAllRefOfEnabledFields(false);
1088
1089      // Find all fields with read access from the public API
1090      findFieldsWithReadAccess();
1091      // and solve the all reference for them
1092      solveAllRefOfFieldsWithReadAccess();
1093
1094      isPostProcessed = true;
1095   }
1096
1097   /*!
1098    * Compute the required buffer size to send the attributes (mostly those grid related).
1099    *
1100    * \param maxEventSize [in/out] the size of the bigger event for each connected server
1101    */
1102   std::map<int, StdSize> CContext::getAttributesBufferSize(std::map<int, StdSize>& maxEventSize)
1103   {
1104     std::map<int, StdSize> attributesSize;
1105
1106     if (hasClient)
1107     {
1108       size_t numEnabledFiles = this->enabledFiles.size();
1109       for (size_t i = 0; i < numEnabledFiles; ++i)
1110       {
1111         CFile* file = this->enabledFiles[i];
1112
1113         std::vector<CField*> enabledFields = file->getEnabledFields();
1114         size_t numEnabledFields = enabledFields.size();
1115         for (size_t j = 0; j < numEnabledFields; ++j)
1116         {
1117           const std::map<int, StdSize> mapSize = enabledFields[j]->getGridAttributesBufferSize();
1118           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
1119           for (; it != itE; ++it)
1120           {
1121             // If attributesSize[it->first] does not exist, it will be zero-initialized
1122             // so we can use it safely without checking for its existance
1123             if (attributesSize[it->first] < it->second)
1124               attributesSize[it->first] = it->second;
1125
1126             if (maxEventSize[it->first] < it->second)
1127               maxEventSize[it->first] = it->second;
1128           }
1129         }
1130       }
1131     }
1132
1133     return attributesSize;
1134   }
1135
1136   /*!
1137    * Compute the required buffer size to send the fields data.
1138    *
1139    * \param maxEventSize [in/out] the size of the bigger event for each connected server
1140    */
1141   std::map<int, StdSize> CContext::getDataBufferSize(std::map<int, StdSize>& maxEventSize)
1142   {
1143     CFile::mode_attr::t_enum mode = hasClient ? CFile::mode_attr::write : CFile::mode_attr::read;
1144
1145     std::map<int, StdSize> dataSize;
1146
1147     // Find all reference domain and axis of all active fields
1148     size_t numEnabledFiles = this->enabledFiles.size();
1149     for (size_t i = 0; i < numEnabledFiles; ++i)
1150     {
1151       CFile* file = this->enabledFiles[i];
1152       CFile::mode_attr::t_enum fileMode = file->mode.isEmpty() ? CFile::mode_attr::write : file->mode.getValue();
1153
1154       if (fileMode == mode)
1155       {
1156         std::vector<CField*> enabledFields = file->getEnabledFields();
1157         size_t numEnabledFields = enabledFields.size();
1158         for (size_t j = 0; j < numEnabledFields; ++j)
1159         {
1160           const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataBufferSize();
1161           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
1162           for (; it != itE; ++it)
1163           {
1164             // If dataSize[it->first] does not exist, it will be zero-initialized
1165             // so we can use it safely without checking for its existance
1166             if (CXios::isOptPerformance)
1167               dataSize[it->first] += it->second;
1168             else if (dataSize[it->first] < it->second)
1169               dataSize[it->first] = it->second;
1170
1171             if (maxEventSize[it->first] < it->second)
1172               maxEventSize[it->first] = it->second;
1173           }
1174         }
1175       }
1176     }
1177
1178     return dataSize;
1179   }
1180
1181   //! Client side: Send infomation of active files (files are enabled to write out)
1182   void CContext::sendEnabledFiles()
1183   {
1184     int size = this->enabledFiles.size();
1185
1186     // In a context, each type has a root definition, e.g: axis, domain, field.
1187     // Every object must be a child of one of these root definition. In this case
1188     // all new file objects created on server must be children of the root "file_definition"
1189     StdString fileDefRoot("file_definition");
1190     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
1191
1192     for (int i = 0; i < size; ++i)
1193     {
1194       cfgrpPtr->sendCreateChild(this->enabledFiles[i]->getId());
1195       this->enabledFiles[i]->sendAllAttributesToServer();
1196       this->enabledFiles[i]->sendAddAllVariables();
1197     }
1198   }
1199
1200   //! Client side: Send information of active fields (ones are written onto files)
1201   void CContext::sendEnabledFields()
1202   {
1203     int size = this->enabledFiles.size();
1204     for (int i = 0; i < size; ++i)
1205     {
1206       this->enabledFiles[i]->sendEnabledFields();
1207     }
1208   }
1209
1210   //! Client side: Check if the defined axis, domains and grids are eligible for compressed indexed output
1211   void CContext::checkAxisDomainsGridsEligibilityForCompressedOutput()
1212   {
1213     if (!hasClient) return;
1214
1215     const vector<CAxis*> allAxis = CAxis::getAll();
1216     for (vector<CAxis*>::const_iterator it = allAxis.begin(); it != allAxis.end(); it++)
1217       (*it)->checkEligibilityForCompressedOutput();
1218
1219     const vector<CDomain*> allDomains = CDomain::getAll();
1220     for (vector<CDomain*>::const_iterator it = allDomains.begin(); it != allDomains.end(); it++)
1221       (*it)->checkEligibilityForCompressedOutput();
1222
1223     const vector<CGrid*> allGrids = CGrid::getAll();
1224     for (vector<CGrid*>::const_iterator it = allGrids.begin(); it != allGrids.end(); it++)
1225       (*it)->checkEligibilityForCompressedOutput();
1226   }
1227
1228   //! Client side: Prepare the timeseries by adding the necessary files
1229   void CContext::prepareTimeseries()
1230   {
1231     if (!hasClient) return;
1232
1233     const std::vector<CFile*> allFiles = CFile::getAll();
1234     for (size_t i = 0; i < allFiles.size(); i++)
1235     {
1236       CFile* file = allFiles[i];
1237
1238       if (!file->timeseries.isEmpty() && file->timeseries != CFile::timeseries_attr::none)
1239       {
1240         StdString tsPrefix = !file->ts_prefix.isEmpty() ? file->ts_prefix : file->getFileOutputName();
1241
1242         const std::vector<CField*> allFields = file->getAllFields();
1243         for (size_t j = 0; j < allFields.size(); j++)
1244         {
1245           CField* field = allFields[j];
1246
1247           if (!field->ts_enabled.isEmpty() && field->ts_enabled)
1248           {
1249             CFile* tsFile = CFile::create();
1250             tsFile->duplicateAttributes(file);
1251             tsFile->setVirtualVariableGroup(file->getVirtualVariableGroup());
1252
1253             tsFile->name = tsPrefix + "_";
1254             if (!field->name.isEmpty())
1255               tsFile->name.get() += field->name;
1256             else if (field->hasDirectFieldReference()) // We cannot use getBaseFieldReference() just yet
1257               tsFile->name.get() += field->field_ref;
1258             else
1259               tsFile->name.get() += field->getId();
1260
1261             if (!field->ts_split_freq.isEmpty())
1262               tsFile->split_freq = field->ts_split_freq;
1263
1264             CField* tsField = tsFile->addField();
1265             tsField->field_ref = field->getId();
1266             tsField->setVirtualVariableGroup(field->getVirtualVariableGroup());
1267
1268             tsFile->solveFieldRefInheritance(true);
1269
1270             if (file->timeseries == CFile::timeseries_attr::exclusive)
1271               field->enabled = false;
1272           }
1273         }
1274
1275         // Finally disable the original file is need be
1276         if (file->timeseries == CFile::timeseries_attr::only)
1277          file->enabled = false;
1278       }
1279     }
1280   }
1281
1282   //! Client side: Send information of reference grid of active fields
1283   void CContext::sendRefGrid()
1284   {
1285     std::set<StdString> gridIds;
1286     int sizeFile = this->enabledFiles.size();
1287     CFile* filePtr(NULL);
1288
1289     // Firstly, find all reference grids of all active fields
1290     for (int i = 0; i < sizeFile; ++i)
1291     {
1292       filePtr = this->enabledFiles[i];
1293       std::vector<CField*> enabledFields = filePtr->getEnabledFields();
1294       int sizeField = enabledFields.size();
1295       for (int numField = 0; numField < sizeField; ++numField)
1296       {
1297         if (0 != enabledFields[numField]->getRelGrid())
1298           gridIds.insert(CGrid::get(enabledFields[numField]->getRelGrid())->getId());
1299       }
1300     }
1301
1302     // Create all reference grids on server side
1303     StdString gridDefRoot("grid_definition");
1304     CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
1305     std::set<StdString>::const_iterator it, itE = gridIds.end();
1306     for (it = gridIds.begin(); it != itE; ++it)
1307     {
1308       gridPtr->sendCreateChild(*it);
1309       CGrid::get(*it)->sendAllAttributesToServer();
1310       CGrid::get(*it)->sendAllDomains();
1311       CGrid::get(*it)->sendAllAxis();
1312       CGrid::get(*it)->sendAllScalars();
1313     }
1314   }
1315
1316
1317   //! Client side: Send information of reference domain and axis of active fields
1318   void CContext::sendRefDomainsAxis()
1319   {
1320     std::set<StdString> domainIds, axisIds, scalarIds;
1321
1322     // Find all reference domain and axis of all active fields
1323     int numEnabledFiles = this->enabledFiles.size();
1324     for (int i = 0; i < numEnabledFiles; ++i)
1325     {
1326       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
1327       int numEnabledFields = enabledFields.size();
1328       for (int j = 0; j < numEnabledFields; ++j)
1329       {
1330         const std::vector<StdString>& prDomAxisScalarId = enabledFields[j]->getRefDomainAxisIds();
1331         if ("" != prDomAxisScalarId[0]) domainIds.insert(prDomAxisScalarId[0]);
1332         if ("" != prDomAxisScalarId[1]) axisIds.insert(prDomAxisScalarId[1]);
1333         if ("" != prDomAxisScalarId[2]) scalarIds.insert(prDomAxisScalarId[2]);
1334       }
1335     }
1336
1337     // Create all reference axis on server side
1338     std::set<StdString>::iterator itDom, itAxis, itScalar;
1339     std::set<StdString>::const_iterator itE;
1340
1341     StdString scalarDefRoot("scalar_definition");
1342     CScalarGroup* scalarPtr = CScalarGroup::get(scalarDefRoot);
1343     itE = scalarIds.end();
1344     for (itScalar = scalarIds.begin(); itScalar != itE; ++itScalar)
1345     {
1346       if (!itScalar->empty())
1347       {
1348         scalarPtr->sendCreateChild(*itScalar);
1349         CScalar::get(*itScalar)->sendAllAttributesToServer();
1350       }
1351     }
1352
1353     StdString axiDefRoot("axis_definition");
1354     CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
1355     itE = axisIds.end();
1356     for (itAxis = axisIds.begin(); itAxis != itE; ++itAxis)
1357     {
1358       if (!itAxis->empty())
1359       {
1360         axisPtr->sendCreateChild(*itAxis);
1361         CAxis::get(*itAxis)->sendAllAttributesToServer();
1362       }
1363     }
1364
1365     // Create all reference domains on server side
1366     StdString domDefRoot("domain_definition");
1367     CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
1368     itE = domainIds.end();
1369     for (itDom = domainIds.begin(); itDom != itE; ++itDom)
1370     {
1371       if (!itDom->empty()) {
1372          domPtr->sendCreateChild(*itDom);
1373          CDomain::get(*itDom)->sendAllAttributesToServer();
1374       }
1375     }
1376   }
1377
1378   //! Update calendar in each time step
1379   void CContext::updateCalendar(int step)
1380   {
1381      info(50) << "updateCalendar : before : " << calendar->getCurrentDate() << endl;
1382      calendar->update(step);
1383      info(50) << "updateCalendar : after : " << calendar->getCurrentDate() << endl;
1384
1385      if (hasClient)
1386      {
1387        checkPrefetchingOfEnabledReadModeFiles();
1388        garbageCollector.invalidate(calendar->getCurrentDate());
1389      }
1390   }
1391
1392   //! Server side: Create header of netcdf file
1393   void CContext::createFileHeader(void )
1394   {
1395      vector<CFile*>::const_iterator it;
1396
1397      for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
1398      {
1399         (*it)->initFile();
1400      }
1401   }
1402
1403   //! Get current context
1404   CContext* CContext::getCurrent(void)
1405   {
1406     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get();
1407   }
1408
1409   /*!
1410   \brief Set context with an id be the current context
1411   \param [in] id identity of context to be set to current
1412   */
1413   void CContext::setCurrent(const string& id)
1414   {
1415     CObjectFactory::SetCurrentContextId(id);
1416     CGroupFactory::SetCurrentContextId(id);
1417   }
1418
1419  /*!
1420  \brief Create a context with specific id
1421  \param [in] id identity of new context
1422  \return pointer to the new context or already-existed one with identity id
1423  */
1424  CContext* CContext::create(const StdString& id)
1425  {
1426    CContext::setCurrent(id);
1427
1428    bool hasctxt = CContext::has(id);
1429    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
1430    getRoot();
1431    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
1432
1433#define DECLARE_NODE(Name_, name_) \
1434    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
1435#define DECLARE_NODE_PAR(Name_, name_)
1436#include "node_type.conf"
1437
1438    return (context);
1439  }
1440
1441
1442     //! Server side: Receive a message to do some post processing
1443  void CContext::recvRegistry(CEventServer& event)
1444  {
1445    CBufferIn* buffer=event.subEvents.begin()->buffer;
1446    string id;
1447    *buffer>>id;
1448    get(id)->recvRegistry(*buffer);
1449  }
1450
1451  void CContext::recvRegistry(CBufferIn& buffer)
1452  {
1453    if (server->intraCommRank==0)
1454    {
1455      CRegistry registry(server->intraComm) ;
1456      registry.fromBuffer(buffer) ;
1457      registryOut->mergeRegistry(registry) ;
1458    }
1459  }
1460
1461  void CContext::sendRegistry(void)
1462  {   
1463    registryOut->hierarchicalGatherRegistry() ;
1464
1465          // Use correct context client to send message
1466     CContextClient* contextClientTmp = (0 != clientPrimServer) ? clientPrimServer : client;
1467    CEventClient event(CContext::GetType(), CContext::EVENT_ID_SEND_REGISTRY);
1468          if (contextClientTmp->isServerLeader())
1469      {
1470         CMessage msg ;
1471         msg<<this->getIdServer();
1472         if (contextClientTmp->clientRank==0) msg<<*registryOut ;
1473         const std::list<int>& ranks = client->getRanksServerLeader();
1474         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1475           event.push(*itRank,1,msg);
1476         contextClientTmp->sendEvent(event);
1477       }
1478       else contextClientTmp->sendEvent(event);
1479
1480    // if (!hasServer)
1481    // {
1482    //   if (client->isServerLeader())
1483    //   {
1484    //      CMessage msg ;
1485    //      msg<<this->getIdServer();
1486    //      if (client->clientRank==0) msg<<*registryOut ;
1487    //      const std::list<int>& ranks = client->getRanksServerLeader();
1488    //      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1489    //        event.push(*itRank,1,msg);
1490    //      client->sendEvent(event);
1491    //    }
1492    //    else client->sendEvent(event);
1493    // }
1494    // else
1495    // {
1496    //   if (clientPrimServer->isServerLeader())
1497    //   {
1498    //      CMessage msg ;
1499    //      msg<<this->getIdServer();
1500    //      if (clientPrimServer->clientRank==0) msg<<*registryOut ;
1501    //      const std::list<int>& ranks = clientPrimServer->getRanksServerLeader();
1502    //      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1503    //        event.push(*itRank,1,msg);
1504    //      clientPrimServer->sendEvent(event);
1505    //    }
1506    //    else clientPrimServer->sendEvent(event);
1507    // }
1508  }
1509
1510} // namespace xios
Note: See TracBrowser for help on using the repository browser.