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

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

Implementing buffer-size automatic detection in mode connected server-client (client is also server)

+) Rearrange some functions to make sure they work in both cases: connected and seperated
+) Make some cleans of code

Test
+) On Curie
+) Both modes, all tests pass

  • 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.6 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)
340     {
341       // After xml is parsed, there are some more works with post processing
342       postProcessing();
343//
344       setClientServerBuffer();
345     }
346
347     if (hasClient && !hasServer)
348     {
349       // After xml is parsed, there are some more works with post processing
350//       postProcessing();
351
352//       setClientServerBuffer();
353
354      // Send all attributes of current context to server
355      this->sendAllAttributesToServer();
356
357      // We have enough information to send to server
358      // First of all, send all enabled files
359       sendEnabledFiles();
360
361      // Then, send all enabled fields
362       sendEnabledFields();
363
364      // After that, send all grid (if any)
365       sendRefGrid();
366
367      // At last, we have all info of domain and axis, then send them
368       sendRefDomainsAxis();
369    }
370
371    // Now tell server that it can process all messages from client
372    if (hasClient && !hasServer) this->sendCloseDefinition();
373
374    // We have a xml tree on the server side and now, it should be also processed
375    if (hasClient && !hasServer) sendPostProcessing();
376
377    // There are some processings that should be done after all of above. For example: check mask or index
378//    if (hasClient && !hasServer)
379    if (hasClient)
380    {
381      this->solveAllRefOfEnabledFields(true);
382      this->buildAllExpressionOfEnabledFields();
383    }
384
385
386
387//      if (hasClient)
388//      {
389//        //solveCalendar();
390//
391//        // Résolution des héritages pour le context actuel.
392////        this->solveAllInheritance();
393//
394//
395////        //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
396////        this->findEnabledFiles();
397//
398//        this->processEnabledFiles() ;
399//
400//        this->solveAllGridRef();
401//      }
402
403
404
405
406//      solveCalendar();
407//
408//      // Résolution des héritages pour le context actuel.
409//      this->solveAllInheritance();
410//
411//      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
412//      this->findEnabledFiles();
413//
414//
415//      this->processEnabledFiles() ;
416
417/*
418      //Recherche des champs à sortir (enable à true + niveau de sortie correct)
419      // pour chaque fichier précédemment listé.
420      this->findAllEnabledFields();
421
422      // Résolution des références de grilles pour chacun des champs.
423      this->solveAllGridRef();
424
425      // Traitement des opérations.
426      this->solveAllOperation();
427
428      // Traitement des expressions.
429      this->solveAllExpression();
430*/
431      // Nettoyage de l'arborescence
432      if (hasClient && !hasServer) CleanTree(); // Only on client side??
433//      if (hasClient) CleanTree();
434      if (hasClient) sendCreateFileHeader() ;
435   }
436
437   void CContext::findAllEnabledFields(void)
438   {
439     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
440     (void)this->enabledFiles[i]->getEnabledFields();
441   }
442
443//    void CContext::processEnabledFiles(void)
444//   {
445//     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
446//     this->enabledFiles[i]->processEnabledFile();
447//   }
448
449
450   void CContext::solveAllRefOfEnabledFields(bool sendToServer)
451   {
452     int size = this->enabledFiles.size();
453     for (int i = 0; i < size; ++i)
454     {
455       this->enabledFiles[i]->solveAllRefOfEnabledFields(sendToServer);
456     }
457   }
458
459   void CContext::buildAllExpressionOfEnabledFields()
460   {
461     int size = this->enabledFiles.size();
462     for (int i = 0; i < size; ++i)
463     {
464       this->enabledFiles[i]->buildAllExpressionOfEnabledFields();
465     }
466   }
467
468//   void CContext::solveAllGridRef(void)
469//   {
470//     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
471//     this->enabledFiles[i]->solveEFGridRef();
472//   }
473//
474//   void CContext::solveAllOperation(void)
475//   {
476//      for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
477//      this->enabledFiles[i]->solveEFOperation();
478//   }
479//
480//   void CContext::solveAllExpression(void)
481//   {
482//      for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
483//      this->enabledFiles[i]->solveEFExpression();
484//   }
485
486   void CContext::solveAllInheritance(bool apply)
487   {
488     // Résolution des héritages descendants (càd des héritages de groupes)
489     // pour chacun des contextes.
490      solveDescInheritance(apply);
491
492     // Résolution des héritages par référence au niveau des fichiers.
493      const vector<CFile*> allFiles=CFile::getAll() ;
494
495     //if (hasClient && !hasServer)
496      if (hasClient)
497        for (unsigned int i = 0; i < allFiles.size(); i++)
498          allFiles[i]->solveFieldRefInheritance(apply);
499   }
500
501   void CContext::findEnabledFiles(void)
502   {
503      const std::vector<CFile*> allFiles = CFile::getAll();
504
505      for (unsigned int i = 0; i < allFiles.size(); i++)
506         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
507         {
508            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
509               enabledFiles.push_back(allFiles[i]);
510         }
511         else enabledFiles.push_back(allFiles[i]); // otherwise true by default
512
513
514      if (enabledFiles.size() == 0)
515         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
516               << getId() << "\" !");
517   }
518
519   void CContext::closeAllFile(void)
520   {
521     std::vector<CFile*>::const_iterator
522            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
523
524     for (; it != end; it++)
525     {
526       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
527       (*it)->close();
528     }
529   }
530
531   /*!
532   \brief Dispatch event received from client
533      Whenever a message is received in buffer of server, it will be processed depending on
534   its event type. A new event type should be added in the switch list to make sure
535   it processed on server side.
536   \param [in] event: Received message
537   */
538   bool CContext::dispatchEvent(CEventServer& event)
539   {
540
541      if (SuperClass::dispatchEvent(event)) return true ;
542      else
543      {
544        switch(event.type)
545        {
546           case EVENT_ID_CLOSE_DEFINITION :
547             recvCloseDefinition(event) ;
548             return true ;
549             break ;
550           case EVENT_ID_UPDATE_CALENDAR :
551             recvUpdateCalendar(event) ;
552             return true ;
553             break ;
554           case EVENT_ID_CREATE_FILE_HEADER :
555             recvCreateFileHeader(event) ;
556             return true ;
557             break ;
558           case EVENT_ID_POST_PROCESS:
559             recvPostProcessing(event) ;
560             return true ;
561             break ;
562           default :
563             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
564                    <<"Unknown Event") ;
565           return false ;
566         }
567      }
568   }
569
570   //! Client side: Send a message to server to make it close
571   void CContext::sendCloseDefinition(void)
572   {
573     CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION) ;
574     if (client->isServerLeader())
575     {
576       CMessage msg ;
577       msg<<this->getId() ;
578       event.push(client->getServerLeader(),1,msg) ;
579       client->sendEvent(event) ;
580     }
581     else client->sendEvent(event) ;
582   }
583
584   //! Server side: Receive a message of client announcing a context close
585   void CContext::recvCloseDefinition(CEventServer& event)
586   {
587
588      CBufferIn* buffer=event.subEvents.begin()->buffer;
589      string id;
590      *buffer>>id ;
591      get(id)->closeDefinition();
592   }
593
594   //! Client side: Send a message to update calendar in each time step
595   void CContext::sendUpdateCalendar(int step)
596   {
597     if (!hasServer)
598     {
599       CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR) ;
600       if (client->isServerLeader())
601       {
602         CMessage msg ;
603         msg<<this->getId()<<step ;
604         event.push(client->getServerLeader(),1,msg) ;
605         client->sendEvent(event) ;
606       }
607       else client->sendEvent(event) ;
608     }
609   }
610
611   //! Server side: Receive a message of client annoucing calendar update
612   void CContext::recvUpdateCalendar(CEventServer& event)
613   {
614
615      CBufferIn* buffer=event.subEvents.begin()->buffer;
616      string id;
617      *buffer>>id ;
618      get(id)->recvUpdateCalendar(*buffer) ;
619   }
620
621   //! Server side: Receive a message of client annoucing calendar update
622   void CContext::recvUpdateCalendar(CBufferIn& buffer)
623   {
624      int step ;
625      buffer>>step ;
626      updateCalendar(step) ;
627   }
628
629   //! Client side: Send a message to create header part of netcdf file
630   void CContext::sendCreateFileHeader(void)
631   {
632     CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER) ;
633     if (client->isServerLeader())
634     {
635       CMessage msg ;
636       msg<<this->getId() ;
637       event.push(client->getServerLeader(),1,msg) ;
638       client->sendEvent(event) ;
639     }
640     else client->sendEvent(event) ;
641   }
642
643   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
644   void CContext::recvCreateFileHeader(CEventServer& event)
645   {
646      CBufferIn* buffer=event.subEvents.begin()->buffer;
647      string id;
648      *buffer>>id ;
649      get(id)->recvCreateFileHeader(*buffer) ;
650   }
651
652   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
653   void CContext::recvCreateFileHeader(CBufferIn& buffer)
654   {
655      createFileHeader() ;
656   }
657
658   //! Client side: Send a message to do some post processing on server
659   void CContext::sendPostProcessing()
660   {
661     if (!hasServer)
662     {
663       CEventClient event(getType(),EVENT_ID_POST_PROCESS) ;
664       if (client->isServerLeader())
665       {
666         CMessage msg ;
667         msg<<this->getId();
668         event.push(client->getServerLeader(),1,msg) ;
669         client->sendEvent(event) ;
670       }
671       else client->sendEvent(event) ;
672     }
673   }
674
675   //! Server side: Receive a message to do some post processing
676   void CContext::recvPostProcessing(CEventServer& event)
677   {
678      CBufferIn* buffer=event.subEvents.begin()->buffer;
679      string id;
680      *buffer>>id;
681      get(id)->recvPostProcessing(*buffer);
682   }
683
684   //! Server side: Receive a message to do some post processing
685   void CContext::recvPostProcessing(CBufferIn& buffer)
686   {
687      postProcessing();
688   }
689
690   /*!
691   \brief Do some simple post processings after parsing xml file
692      After the xml file (iodef.xml) is parsed, it is necessary to build all relations among
693   created object, e.g: inhertance among fields, domain, axis. After that, all fiels as well as their parents (reference fields),
694   which will be written out into netcdf files, are processed
695   */
696   void CContext::postProcessing()
697   {
698     if (isPostProcessed) return;
699
700     // Solve calendar for both side: client and server
701      this->solveCalendar();
702
703      // Find all inheritance in xml structure
704      this->solveAllInheritance();
705
706      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
707      this->findEnabledFiles();
708
709      // Find all enabled fields of each file
710      this->findAllEnabledFields();
711
712      // Search and rebuild all reference object of enabled fields
713      this->solveAllRefOfEnabledFields(false);
714      isPostProcessed = true;
715   }
716
717   std::map<int, StdSize>& CContext::getDataSize()
718   {
719     std::set<StdString> domainIds;
720
721     // Find all reference domain and axis of all active fields
722     int numEnabledFiles = this->enabledFiles.size();
723     for (int i = 0; i < numEnabledFiles; ++i)
724     {
725       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
726       int numEnabledFields = enabledFields.size();
727       for (int j = 0; j < numEnabledFields; ++j)
728       {
729         const std::pair<StdString, StdString>& prDomAxisId = enabledFields[j]->getDomainAxisIds();
730         const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataSize();
731         if (dataSize_.empty())
732         {
733           dataSize_ = mapSize;
734           domainIds.insert(prDomAxisId.first);
735         }
736         else
737         {
738           if (domainIds.find(prDomAxisId.first) == domainIds.end())
739           {
740             std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
741             for (; it != itE; ++it)
742             {
743               if (0 < dataSize_.count(it->first)) dataSize_[it->first] += it->second;
744               else dataSize_.insert(make_pair(it->first, it->second));
745             }
746           }
747
748         }
749
750       }
751     }
752
753     return dataSize_;
754   }
755
756   //! Client side: Send infomation of active files (files are enabled to write out)
757   void CContext::sendEnabledFiles()
758   {
759     int size = this->enabledFiles.size();
760
761     // In a context, each type has a root definition, e.g: axis, domain, field.
762     // Every object must be a child of one of these root definition. In this case
763     // all new file objects created on server must be children of the root "file_definition"
764     StdString fileDefRoot("file_definition");
765     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
766
767     for (int i = 0; i < size; ++i)
768     {
769       cfgrpPtr->sendCreateChild(this->enabledFiles[i]->getId());
770       this->enabledFiles[i]->sendAllAttributesToServer();
771       this->enabledFiles[i]->sendAddAllVariables();
772     }
773   }
774
775   //! Client side: Send information of active fields (ones are written onto files)
776   void CContext::sendEnabledFields()
777   {
778     int size = this->enabledFiles.size();
779     for (int i = 0; i < size; ++i)
780     {
781       this->enabledFiles[i]->sendEnabledFields();
782     }
783   }
784
785   //! Client side: Send information of reference grid of active fields
786   void CContext::sendRefGrid()
787   {
788     std::set<StdString> gridIds;
789     int sizeFile = this->enabledFiles.size();
790     CFile* filePtr(NULL);
791
792     // Firstly, find all reference grids of all active fields
793     for (int i = 0; i < sizeFile; ++i)
794     {
795       filePtr = this->enabledFiles[i];
796       std::vector<CField*> enabledFields = filePtr->getEnabledFields();
797       int sizeField = enabledFields.size();
798       for (int numField = 0; numField < sizeField; ++numField)
799       {
800         if (0 != enabledFields[numField]->getRelGrid())
801           gridIds.insert(CGrid::get(enabledFields[numField]->getRelGrid())->getId());
802       }
803     }
804
805     // Create all reference grids on server side
806     StdString gridDefRoot("grid_definition");
807     CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
808     std::set<StdString>::const_iterator it, itE = gridIds.end();
809     for (it = gridIds.begin(); it != itE; ++it)
810     {
811       gridPtr->sendCreateChild(*it);
812       CGrid::get(*it)->sendAllAttributesToServer();
813     }
814   }
815
816
817   //! Client side: Send information of reference domain and axis of active fields
818   void CContext::sendRefDomainsAxis()
819   {
820     std::set<StdString> domainIds;
821     std::set<StdString> axisIds;
822
823     // Find all reference domain and axis of all active fields
824     int numEnabledFiles = this->enabledFiles.size();
825     for (int i = 0; i < numEnabledFiles; ++i)
826     {
827       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
828       int numEnabledFields = enabledFields.size();
829       for (int j = 0; j < numEnabledFields; ++j)
830       {
831         const std::pair<StdString, StdString>& prDomAxisId = enabledFields[j]->getDomainAxisIds();
832         domainIds.insert(prDomAxisId.first);
833         axisIds.insert(prDomAxisId.second);
834       }
835     }
836
837     // Create all reference axis on server side
838     std::set<StdString>::iterator itDom, itAxis;
839     std::set<StdString>::const_iterator itE;
840
841     StdString axiDefRoot("axis_definition");
842     CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
843     itE = axisIds.end();
844     for (itAxis = axisIds.begin(); itAxis != itE; ++itAxis)
845     {
846       axisPtr->sendCreateChild(*itAxis);
847       CAxis::get(*itAxis)->sendAllAttributesToServer();
848     }
849
850     // Create all reference domains on server side
851     StdString domDefRoot("domain_definition");
852     CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
853     itE = domainIds.end();
854     for (itDom = domainIds.begin(); itDom != itE; ++itDom)
855     {
856       domPtr->sendCreateChild(*itDom);
857       CDomain::get(*itDom)->sendAllAttributesToServer();
858     }
859   }
860
861   //! Update calendar in each time step
862   void CContext::updateCalendar(int step)
863   {
864      info(50)<<"updateCalendar : before : "<<calendar->getCurrentDate()<<endl ;
865      calendar->update(step) ;
866      info(50)<<"updateCalendar : after : "<<calendar->getCurrentDate()<<endl ;
867   }
868
869   //! Server side: Create header of netcdf file
870   void CContext::createFileHeader(void )
871   {
872      vector<CFile*>::const_iterator it ;
873
874      for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
875      {
876         (*it)->initFile();
877      }
878   }
879
880   //! Get current context
881   CContext* CContext::getCurrent(void)
882   {
883     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get() ;
884   }
885
886   /*!
887   \brief Set context with an id be the current context
888   \param [in] id identity of context to be set to current
889   */
890   void CContext::setCurrent(const string& id)
891   {
892     CObjectFactory::SetCurrentContextId(id);
893     CGroupFactory::SetCurrentContextId(id);
894   }
895
896  /*!
897  \brief Create a context with specific id
898  \param [in] id identity of new context
899  \return pointer to the new context or already-existed one with identity id
900  */
901  CContext* CContext::create(const StdString& id)
902  {
903    CContext::setCurrent(id) ;
904
905    bool hasctxt = CContext::has(id);
906    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
907    getRoot() ;
908    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
909
910#define DECLARE_NODE(Name_, name_) \
911    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
912#define DECLARE_NODE_PAR(Name_, name_)
913#include "node_type.conf"
914
915    return (context);
916  }
917} // namespace xios
Note: See TracBrowser for help on using the repository browser.