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

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

First rebond on the secondary server pool. XIOS finalizes correctly.

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