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

Last change on this file since 509 was 509, checked in by mhnguyen, 10 years ago

Implementing buffer size auto-detection for mode client -server

+) Process xml tree in client side then send all the information to server
+) Only information enabled fields in enabled files are sent to server
+) Some important change in structure of code which must be refactored

Test
+) On Curie
+) Only mode client-server
+) Passed for all tests

  • 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: 28.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 "xmlioserver_spl.hpp"
16
17namespace xios {
18
19  shared_ptr<CContextGroup> CContext::root ;
20
21   /// ////////////////////// Définitions ////////////////////// ///
22
23   CContext::CContext(void)
24      : CObjectTemplate<CContext>(), CContextAttributes()
25      , calendar(),hasClient(false),hasServer(false), isPostProcessed(false), dataSize_()
26   { /* Ne rien faire de plus */ }
27
28   CContext::CContext(const StdString & id)
29      : CObjectTemplate<CContext>(id), CContextAttributes()
30      , calendar(),hasClient(false),hasServer(false), isPostProcessed(false), dataSize_()
31   { /* Ne rien faire de plus */ }
32
33   CContext::~CContext(void)
34   {
35     if (hasClient) delete client ;
36     if (hasServer) delete server ;
37   }
38
39   //----------------------------------------------------------------
40   //! Get name of context
41   StdString CContext::GetName(void)   { return (StdString("context")); }
42   StdString CContext::GetDefName(void){ return (CContext::GetName()); }
43   ENodeType CContext::GetType(void)   { return (eContext); }
44
45   //----------------------------------------------------------------
46   /*!
47   \brief Get context group (context root)
48   \return Context root
49   */
50   CContextGroup* CContext::getRoot(void)
51   {
52      if (root.get()==NULL) root=shared_ptr<CContextGroup>(new CContextGroup(xml::CXMLNode::GetRootName())) ;
53      return root.get();
54   }
55
56
57   //----------------------------------------------------------------
58   /*!
59   \brief Get calendar of a context
60   \return Calendar
61   */
62   boost::shared_ptr<CCalendar> CContext::getCalendar(void) const
63   {
64      return (this->calendar);
65   }
66
67   //----------------------------------------------------------------
68   /*!
69   \brief Set a context with a calendar
70   \param[in] newCalendar new calendar
71   */
72   void CContext::setCalendar(boost::shared_ptr<CCalendar> newCalendar)
73   {
74      this->calendar = newCalendar;
75      calendar_type.setValue(this->calendar->getId());
76      start_date.setValue(this->calendar->getInitDate().toString());
77   }
78
79   //----------------------------------------------------------------
80   //! Process all information of calendar
81   void CContext::solveCalendar(void)
82   {
83      if (this->calendar.get() != NULL) return;
84      if (calendar_type.isEmpty() || start_date.isEmpty())
85         ERROR(" CContext::solveCalendar(void)",
86               << "[ context id = " << this->getId() << " ] "
87               << "Impossible to define a calendar (an attribute is missing).");
88
89#define DECLARE_CALENDAR(MType  , mtype)                              \
90   if (calendar_type.getValue().compare(#mtype) == 0)                 \
91   {                                                                  \
92      if (time_origin.isEmpty())                                       \
93        this->calendar =  boost::shared_ptr<CCalendar>          \
94           (new C##MType##Calendar(start_date.getValue()));     \
95      else this->calendar =  boost::shared_ptr<CCalendar>       \
96           (new C##MType##Calendar(start_date.getValue(),time_origin.getValue()));     \
97      if (!this->timestep.isEmpty())                                  \
98       this->calendar->setTimeStep                                    \
99          (CDuration::FromString(this->timestep.getValue()));   \
100      return;                                                         \
101   }
102#include "calendar_type.conf"
103
104      ERROR("CContext::solveCalendar(void)",
105            << "[ calendar_type = " << calendar_type.getValue() << " ] "
106            << "The calendar is not defined !");
107   }
108
109   //----------------------------------------------------------------
110   /*!
111   \brief Parse xml file and write information into context object
112   \param [in] node xmld node corresponding in xml file
113   */
114   void CContext::parse(xml::CXMLNode & node)
115   {
116      CContext::SuperClass::parse(node);
117
118      // PARSING POUR GESTION DES ENFANTS
119      xml::THashAttributes attributes = node.getAttributes();
120
121      if (attributes.end() != attributes.find("src"))
122      {
123         StdIFStream ifs ( attributes["src"].c_str() , StdIFStream::in );
124         if ( (ifs.rdstate() & std::ifstream::failbit ) != 0 )
125            ERROR("void CContext::parse(xml::CXMLNode & node)",
126                  <<endl<< "Can not open <"<<attributes["src"].c_str()<<"> file" );
127         if (!ifs.good())
128            ERROR("CContext::parse(xml::CXMLNode & node)",
129                  << "[ filename = " << attributes["src"] << " ] Bad xml stream !");
130         xml::CXMLParser::ParseInclude(ifs, attributes["src"], *this);
131      }
132
133      if (node.getElementName().compare(CContext::GetName()))
134         DEBUG("Le noeud is wrong defined but will be considered as a context !");
135
136      if (!(node.goToChildElement()))
137      {
138         DEBUG("Le context ne contient pas d'enfant !");
139      }
140      else
141      {
142         do { // Parcours des contextes pour traitement.
143
144            StdString name = node.getElementName();
145            attributes.clear();
146            attributes = node.getAttributes();
147
148            if (attributes.end() != attributes.find("id"))
149            {
150              DEBUG(<< "Definition node has an id,"
151                    << "it will not be taking account !");
152            }
153
154#define DECLARE_NODE(Name_, name_)    \
155   if (name.compare(C##Name_##Definition::GetDefName()) == 0) \
156   { C##Name_##Definition::create(C##Name_##Definition::GetDefName()) -> parse(node) ; continue; }
157#define DECLARE_NODE_PAR(Name_, name_)
158#include "node_type.conf"
159
160            DEBUG(<< "The element \'"     << name
161                  << "\' in the context \'" << CContext::getCurrent()->getId()
162                  << "\' is not a definition !");
163
164         } while (node.goToNextElement());
165
166         node.goToParentElement(); // Retour au parent
167      }
168   }
169
170   //----------------------------------------------------------------
171   //! Show tree structure of context
172   void CContext::ShowTree(StdOStream & out)
173   {
174      StdString currentContextId = CContext::getCurrent() -> getId() ;
175      std::vector<CContext*> def_vector =
176         CContext::getRoot()->getChildList();
177      std::vector<CContext*>::iterator
178         it = def_vector.begin(), end = def_vector.end();
179
180      out << "<? xml version=\"1.0\" ?>" << std::endl;
181      out << "<"  << xml::CXMLNode::GetRootName() << " >" << std::endl;
182
183      for (; it != end; it++)
184      {
185         CContext* context = *it;
186         CContext::setCurrent(context->getId());
187         out << *context << std::endl;
188      }
189
190      out << "</" << xml::CXMLNode::GetRootName() << " >" << std::endl;
191      CContext::setCurrent(currentContextId);
192   }
193
194
195   //----------------------------------------------------------------
196
197   //! Convert context object into string (to print)
198   StdString CContext::toString(void) const
199   {
200      StdOStringStream oss;
201      oss << "<" << CContext::GetName()
202          << " id=\"" << this->getId() << "\" "
203          << SuperClassAttribute::toString() << ">" << std::endl;
204      if (!this->hasChild())
205      {
206         //oss << "<!-- No definition -->" << std::endl; // fait planter l'incrémentation
207      }
208      else
209      {
210
211#define DECLARE_NODE(Name_, name_)    \
212   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
213   oss << * C##Name_##Definition::get(C##Name_##Definition::GetDefName()) << std::endl;
214#define DECLARE_NODE_PAR(Name_, name_)
215#include "node_type.conf"
216
217      }
218
219      oss << "</" << CContext::GetName() << " >";
220
221      return (oss.str());
222   }
223
224   //----------------------------------------------------------------
225
226   /*!
227   \brief Find all inheritace among objects in a context.
228   \param [in] apply (true) write attributes of parent into ones of child if they are empty
229                     (false) write attributes of parent into a new container of child
230   \param [in] parent unused
231   */
232   void CContext::solveDescInheritance(bool apply, const CAttributeMap * const UNUSED(parent))
233   {
234#define DECLARE_NODE(Name_, name_)    \
235   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
236     C##Name_##Definition::get(C##Name_##Definition::GetDefName())->solveDescInheritance(apply);
237#define DECLARE_NODE_PAR(Name_, name_)
238#include "node_type.conf"
239   }
240
241   //----------------------------------------------------------------
242
243   //! Verify if all root definition in the context have child.
244   bool CContext::hasChild(void) const
245   {
246      return (
247#define DECLARE_NODE(Name_, name_)    \
248   C##Name_##Definition::has(C##Name_##Definition::GetDefName())   ||
249#define DECLARE_NODE_PAR(Name_, name_)
250#include "node_type.conf"
251      false);
252}
253
254//   //----------------------------------------------------------------
255//
256//   void CContext::solveFieldRefInheritance(bool apply)
257//   {
258//      if (!this->hasId()) return;
259//      vector<CField*> allField = CField::getAll() ;
260////              = CObjectTemplate<CField>::GetAllVectobject(this->getId());
261//      std::vector<CField*>::iterator
262//         it = allField.begin(), end = allField.end();
263//
264//      for (; it != end; it++)
265//      {
266//         CField* field = *it;
267//         field->solveRefInheritance(apply);
268//      }
269//   }
270
271   //----------------------------------------------------------------
272
273   void CContext::CleanTree(void)
274   {
275#define DECLARE_NODE(Name_, name_) C##Name_##Group::ClearAllAttributes();
276#define DECLARE_NODE_PAR(Name_, name_)
277#include "node_type.conf"
278   }
279   ///---------------------------------------------------------------
280
281   //! Initialize client side
282   void CContext::initClient(MPI_Comm intraComm, MPI_Comm interComm)
283   {
284     hasClient=true ;
285     client = new CContextClient(this,intraComm, interComm) ;
286   }
287
288   void CContext::setClientServerBuffer()
289   {
290     if (hasClient)
291     {
292       client->setBufferSize(getDataSize());
293     }
294   }
295
296   //! Verify whether a context is initialized
297   bool CContext::isInitialized(void)
298   {
299     return hasClient ;
300   }
301
302   //! Initialize server
303   void CContext::initServer(MPI_Comm intraComm,MPI_Comm interComm)
304   {
305     hasServer=true ;
306     server = new CContextServer(this,intraComm,interComm) ;
307   }
308
309   //! Server side: Put server into a loop in order to listen message from client
310   bool CContext::eventLoop(void)
311   {
312     return server->eventLoop() ;
313   }
314
315   //! Terminate a context
316   void CContext::finalize(void)
317   {
318      if (hasClient && !hasServer)
319      {
320         client->finalize() ;
321      }
322      if (hasServer)
323      {
324        closeAllFile() ;
325      }
326   }
327
328   /*!
329   \brief Close all the context defintion and do processing data
330      After everything is well defined on client side, they will be processed and sent to server
331   From the version 2.0, sever and client work no more on the same database. Moreover, client(s) will send
332   all necessary information to server, from which each server can build its own database.
333   Because the role of server is to write out field data on a specific netcdf file,
334   the only information that it needs is the enabled files
335   and the active fields (fields will be written onto active files)
336   */
337   void CContext::closeDefinition(void)
338   {
339     if (hasClient && !hasServer)
340     {
341       // After xml is parsed, there are some more works with post processing
342       postProcessing();
343
344       setClientServerBuffer();
345
346      // Send all attributes of current context to server
347      this->sendAllAttributesToServer();
348
349      // We have enough information to send to server
350      // First of all, send all enabled files
351       sendEnabledFiles();
352
353      // Then, send all enabled fields
354       sendEnabledFields();
355
356      // After that, send all grid (if any)
357       sendRefGrid();
358
359      // At last, we have all info of domain and axis, then send them
360       sendRefDomainsAxis();
361    }
362
363    // Now tell server that it can process all messages from client
364    if (hasClient && !hasServer) this->sendCloseDefinition();
365
366    // We have a xml tree on the server side and now, it should be also processed
367    if (hasClient && !hasServer) sendPostProcessing();
368
369    // There are some processings that should be done after all of above. For example: check mask or index
370    if (hasClient && !hasServer)
371    {
372      this->solveAllRefOfEnabledFields(true);
373      this->buildAllExpressionOfEnabledFields();
374    }
375
376//      if (hasClient)
377//      {
378//        //solveCalendar();
379//
380//        // Résolution des héritages pour le context actuel.
381////        this->solveAllInheritance();
382//
383//
384////        //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
385////        this->findEnabledFiles();
386//
387//        this->processEnabledFiles() ;
388//
389//        this->solveAllGridRef();
390//      }
391
392
393
394
395//      solveCalendar();
396//
397//      // Résolution des héritages pour le context actuel.
398//      this->solveAllInheritance();
399//
400//      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
401//      this->findEnabledFiles();
402//
403//
404//      this->processEnabledFiles() ;
405
406/*
407      //Recherche des champs à sortir (enable à true + niveau de sortie correct)
408      // pour chaque fichier précédemment listé.
409      this->findAllEnabledFields();
410
411      // Résolution des références de grilles pour chacun des champs.
412      this->solveAllGridRef();
413
414      // Traitement des opérations.
415      this->solveAllOperation();
416
417      // Traitement des expressions.
418      this->solveAllExpression();
419*/
420      // Nettoyage de l'arborescence
421      if (hasClient && !hasServer) CleanTree(); // Only on client side??
422//      if (hasClient) CleanTree();
423      if (hasClient) sendCreateFileHeader() ;
424   }
425
426   void CContext::findAllEnabledFields(void)
427   {
428     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
429     (void)this->enabledFiles[i]->getEnabledFields();
430   }
431
432//    void CContext::processEnabledFiles(void)
433//   {
434//     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
435//     this->enabledFiles[i]->processEnabledFile();
436//   }
437
438
439   void CContext::solveAllRefOfEnabledFields(bool sendToServer)
440   {
441     int size = this->enabledFiles.size();
442     for (int i = 0; i < size; ++i)
443     {
444       this->enabledFiles[i]->solveAllRefOfEnabledFields(sendToServer);
445     }
446   }
447
448   void CContext::buildAllExpressionOfEnabledFields()
449   {
450     int size = this->enabledFiles.size();
451     for (int i = 0; i < size; ++i)
452     {
453       this->enabledFiles[i]->buildAllExpressionOfEnabledFields();
454     }
455   }
456
457//   void CContext::solveAllGridRef(void)
458//   {
459//     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
460//     this->enabledFiles[i]->solveEFGridRef();
461//   }
462//
463//   void CContext::solveAllOperation(void)
464//   {
465//      for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
466//      this->enabledFiles[i]->solveEFOperation();
467//   }
468//
469//   void CContext::solveAllExpression(void)
470//   {
471//      for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
472//      this->enabledFiles[i]->solveEFExpression();
473//   }
474
475   void CContext::solveAllInheritance(bool apply)
476   {
477     // Résolution des héritages descendants (càd des héritages de groupes)
478     // pour chacun des contextes.
479      solveDescInheritance(apply);
480
481     // Résolution des héritages par référence au niveau des fichiers.
482      const vector<CFile*> allFiles=CFile::getAll() ;
483
484     if (hasClient && !hasServer)
485      for (unsigned int i = 0; i < allFiles.size(); i++)
486         allFiles[i]->solveFieldRefInheritance(apply);
487   }
488
489   void CContext::findEnabledFiles(void)
490   {
491      const std::vector<CFile*> allFiles = CFile::getAll();
492
493      for (unsigned int i = 0; i < allFiles.size(); i++)
494         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
495         {
496            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
497               enabledFiles.push_back(allFiles[i]);
498         }
499         else enabledFiles.push_back(allFiles[i]); // otherwise true by default
500
501
502      if (enabledFiles.size() == 0)
503         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
504               << getId() << "\" !");
505   }
506
507   void CContext::closeAllFile(void)
508   {
509     std::vector<CFile*>::const_iterator
510            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
511
512     for (; it != end; it++)
513     {
514       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
515       (*it)->close();
516     }
517   }
518
519   /*!
520   \brief Dispatch event received from client
521      Whenever a message is received in buffer of server, it will be processed depending on
522   its event type. A new event type should be added in the switch list to make sure
523   it processed on server side.
524   \param [in] event: Received message
525   */
526   bool CContext::dispatchEvent(CEventServer& event)
527   {
528
529      if (SuperClass::dispatchEvent(event)) return true ;
530      else
531      {
532        switch(event.type)
533        {
534           case EVENT_ID_CLOSE_DEFINITION :
535             recvCloseDefinition(event) ;
536             return true ;
537             break ;
538           case EVENT_ID_UPDATE_CALENDAR :
539             recvUpdateCalendar(event) ;
540             return true ;
541             break ;
542           case EVENT_ID_CREATE_FILE_HEADER :
543             recvCreateFileHeader(event) ;
544             return true ;
545             break ;
546           case EVENT_ID_POST_PROCESS:
547             recvPostProcessing(event) ;
548             return true ;
549             break ;
550           default :
551             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
552                    <<"Unknown Event") ;
553           return false ;
554         }
555      }
556   }
557
558   //! Client side: Send a message to server to make it close
559   void CContext::sendCloseDefinition(void)
560   {
561     CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION) ;
562     if (client->isServerLeader())
563     {
564       CMessage msg ;
565       msg<<this->getId() ;
566       event.push(client->getServerLeader(),1,msg) ;
567       client->sendEvent(event) ;
568     }
569     else client->sendEvent(event) ;
570   }
571
572   //! Server side: Receive a message of client announcing a context close
573   void CContext::recvCloseDefinition(CEventServer& event)
574   {
575
576      CBufferIn* buffer=event.subEvents.begin()->buffer;
577      string id;
578      *buffer>>id ;
579      get(id)->closeDefinition();
580   }
581
582   //! Client side: Send a message to update calendar in each time step
583   void CContext::sendUpdateCalendar(int step)
584   {
585     if (!hasServer)
586     {
587       CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR) ;
588       if (client->isServerLeader())
589       {
590         CMessage msg ;
591         msg<<this->getId()<<step ;
592         event.push(client->getServerLeader(),1,msg) ;
593         client->sendEvent(event) ;
594       }
595       else client->sendEvent(event) ;
596     }
597   }
598
599   //! Server side: Receive a message of client annoucing calendar update
600   void CContext::recvUpdateCalendar(CEventServer& event)
601   {
602
603      CBufferIn* buffer=event.subEvents.begin()->buffer;
604      string id;
605      *buffer>>id ;
606      get(id)->recvUpdateCalendar(*buffer) ;
607   }
608
609   //! Server side: Receive a message of client annoucing calendar update
610   void CContext::recvUpdateCalendar(CBufferIn& buffer)
611   {
612      int step ;
613      buffer>>step ;
614      updateCalendar(step) ;
615   }
616
617   //! Client side: Send a message to create header part of netcdf file
618   void CContext::sendCreateFileHeader(void)
619   {
620     CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER) ;
621     if (client->isServerLeader())
622     {
623       CMessage msg ;
624       msg<<this->getId() ;
625       event.push(client->getServerLeader(),1,msg) ;
626       client->sendEvent(event) ;
627     }
628     else client->sendEvent(event) ;
629   }
630
631   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
632   void CContext::recvCreateFileHeader(CEventServer& event)
633   {
634      CBufferIn* buffer=event.subEvents.begin()->buffer;
635      string id;
636      *buffer>>id ;
637      get(id)->recvCreateFileHeader(*buffer) ;
638   }
639
640   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
641   void CContext::recvCreateFileHeader(CBufferIn& buffer)
642   {
643      createFileHeader() ;
644   }
645
646   //! Client side: Send a message to do some post processing on server
647   void CContext::sendPostProcessing()
648   {
649     if (!hasServer)
650     {
651       CEventClient event(getType(),EVENT_ID_POST_PROCESS) ;
652       if (client->isServerLeader())
653       {
654         CMessage msg ;
655         msg<<this->getId();
656         event.push(client->getServerLeader(),1,msg) ;
657         client->sendEvent(event) ;
658       }
659       else client->sendEvent(event) ;
660     }
661   }
662
663   //! Server side: Receive a message to do some post processing
664   void CContext::recvPostProcessing(CEventServer& event)
665   {
666      CBufferIn* buffer=event.subEvents.begin()->buffer;
667      string id;
668      *buffer>>id;
669      get(id)->recvPostProcessing(*buffer);
670   }
671
672   //! Server side: Receive a message to do some post processing
673   void CContext::recvPostProcessing(CBufferIn& buffer)
674   {
675      postProcessing();
676   }
677
678   /*!
679   \brief Do some simple post processings after parsing xml file
680      After the xml file (iodef.xml) is parsed, it is necessary to build all relations among
681   created object, e.g: inhertance among fields, domain, axis. After that, all fiels as well as their parents (reference fields),
682   which will be written out into netcdf files, are processed
683   */
684   void CContext::postProcessing()
685   {
686     if (isPostProcessed) return;
687
688     this->solveCalendar();
689
690     // Solve calendar for both side: client and server
691      this->solveCalendar();
692
693      // Find all inheritance in xml structure
694      this->solveAllInheritance();
695
696      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
697      this->findEnabledFiles();
698
699      // Find all enabled fields of each file
700      this->findAllEnabledFields();
701
702      // Search and rebuild all reference object of enabled fields
703      this->solveAllRefOfEnabledFields(false);
704      isPostProcessed = true;
705   }
706
707   std::map<int, StdSize>& CContext::getDataSize()
708   {
709     std::set<StdString> domainIds;
710
711     // Find all reference domain and axis of all active fields
712     int numEnabledFiles = this->enabledFiles.size();
713     for (int i = 0; i < numEnabledFiles; ++i)
714     {
715       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
716       int numEnabledFields = enabledFields.size();
717       for (int j = 0; j < numEnabledFields; ++j)
718       {
719         const std::pair<StdString, StdString>& prDomAxisId = enabledFields[j]->getDomainAxisIds();
720         const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataSize();
721         if (dataSize_.empty())
722         {
723           dataSize_ = mapSize;
724           domainIds.insert(prDomAxisId.first);
725         }
726         else
727         {
728           if (domainIds.find(prDomAxisId.first) == domainIds.end())
729           {
730             std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
731             for (; it != itE; ++it)
732             {
733               if (0 < dataSize_.count(it->first)) dataSize_[it->first] += it->second;
734               else dataSize_.insert(make_pair(it->first, it->second));
735             }
736           }
737
738         }
739
740       }
741     }
742
743     return dataSize_;
744   }
745
746   //! Client side: Send infomation of active files (files are enabled to write out)
747   void CContext::sendEnabledFiles()
748   {
749     int size = this->enabledFiles.size();
750
751     // In a context, each type has a root definition, e.g: axis, domain, field.
752     // Every object must be a child of one of these root definition. In this case
753     // all new file objects created on server must be children of the root "file_definition"
754     StdString fileDefRoot("file_definition");
755     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
756
757     for (int i = 0; i < size; ++i)
758     {
759       cfgrpPtr->sendCreateChild(this->enabledFiles[i]->getId());
760       this->enabledFiles[i]->sendAllAttributesToServer();
761       this->enabledFiles[i]->sendAddAllVariables();
762     }
763   }
764
765   //! Client side: Send information of active fields (ones are written onto files)
766   void CContext::sendEnabledFields()
767   {
768     int size = this->enabledFiles.size();
769     for (int i = 0; i < size; ++i)
770     {
771       this->enabledFiles[i]->sendEnabledFields();
772     }
773   }
774
775   //! Client side: Send information of reference grid of active fields
776   void CContext::sendRefGrid()
777   {
778     std::set<StdString> gridIds;
779     int sizeFile = this->enabledFiles.size();
780     CFile* filePtr(NULL);
781
782     // Firstly, find all reference grids of all active fields
783     for (int i = 0; i < sizeFile; ++i)
784     {
785       filePtr = this->enabledFiles[i];
786       std::vector<CField*> enabledFields = filePtr->getEnabledFields();
787       int sizeField = enabledFields.size();
788       for (int numField = 0; numField < sizeField; ++numField)
789       {
790         if (0 != enabledFields[numField]->getRelGrid())
791           gridIds.insert(CGrid::get(enabledFields[numField]->getRelGrid())->getId());
792       }
793     }
794
795     // Create all reference grids on server side
796     StdString gridDefRoot("grid_definition");
797     CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
798     std::set<StdString>::const_iterator it, itE = gridIds.end();
799     for (it = gridIds.begin(); it != itE; ++it)
800     {
801       gridPtr->sendCreateChild(*it);
802       CGrid::get(*it)->sendAllAttributesToServer();
803     }
804   }
805
806
807   //! Client side: Send information of reference domain and axis of active fields
808   void CContext::sendRefDomainsAxis()
809   {
810     std::set<StdString> domainIds;
811     std::set<StdString> axisIds;
812
813     // Find all reference domain and axis of all active fields
814     int numEnabledFiles = this->enabledFiles.size();
815     for (int i = 0; i < numEnabledFiles; ++i)
816     {
817       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
818       int numEnabledFields = enabledFields.size();
819       for (int j = 0; j < numEnabledFields; ++j)
820       {
821         const std::pair<StdString, StdString>& prDomAxisId = enabledFields[j]->getDomainAxisIds();
822         domainIds.insert(prDomAxisId.first);
823         axisIds.insert(prDomAxisId.second);
824       }
825     }
826
827     // Create all reference axis on server side
828     std::set<StdString>::iterator itDom, itAxis;
829     std::set<StdString>::const_iterator itE;
830
831     StdString axiDefRoot("axis_definition");
832     CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
833     itE = axisIds.end();
834     for (itAxis = axisIds.begin(); itAxis != itE; ++itAxis)
835     {
836       axisPtr->sendCreateChild(*itAxis);
837       CAxis::get(*itAxis)->sendAllAttributesToServer();
838     }
839
840     // Create all reference domains on server side
841     StdString domDefRoot("domain_definition");
842     CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
843     itE = domainIds.end();
844     for (itDom = domainIds.begin(); itDom != itE; ++itDom)
845     {
846       domPtr->sendCreateChild(*itDom);
847       CDomain::get(*itDom)->sendAllAttributesToServer();
848     }
849   }
850
851   //! Update calendar in each time step
852   void CContext::updateCalendar(int step)
853   {
854      info(50)<<"updateCalendar : before : "<<calendar->getCurrentDate()<<endl ;
855      calendar->update(step) ;
856      info(50)<<"updateCalendar : after : "<<calendar->getCurrentDate()<<endl ;
857   }
858
859   //! Server side: Create header of netcdf file
860   void CContext::createFileHeader(void )
861   {
862      vector<CFile*>::const_iterator it ;
863
864      for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
865      {
866         (*it)->initFile();
867      }
868   }
869
870   //! Get current context
871   CContext* CContext::getCurrent(void)
872   {
873     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get() ;
874   }
875
876   /*!
877   \brief Set context with an id be the current context
878   \param [in] id identity of context to be set to current
879   */
880   void CContext::setCurrent(const string& id)
881   {
882     CObjectFactory::SetCurrentContextId(id);
883     CGroupFactory::SetCurrentContextId(id);
884   }
885
886  /*!
887  \brief Create a context with specific id
888  \param [in] id identity of new context
889  \return pointer to the new context or already-existed one with identity id
890  */
891  CContext* CContext::create(const StdString& id)
892  {
893    CContext::setCurrent(id) ;
894
895    bool hasctxt = CContext::has(id);
896    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
897    getRoot() ;
898    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
899
900#define DECLARE_NODE(Name_, name_) \
901    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
902#define DECLARE_NODE_PAR(Name_, name_)
903#include "node_type.conf"
904
905    return (context);
906  }
907} // namespace xios
Note: See TracBrowser for help on using the repository browser.