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

Last change on this file since 532 was 532, checked in by rlacroix, 9 years ago

Add a new attribute type for dates and use it for the context's start_date and time_origin.

The "xios_date" type should now be used to get/set date attributes through the Fortran interface. This avoids using strings to manipulate dates.

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