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

Last change on this file since 537 was 537, checked in by rlacroix, 8 years ago

Add a new attribute type for durations and use it for the context's timestep.

Note that the "xios_time" type and the "xios_set_timestep" procedure have been removed from the Fortran interface. Instead, the "xios_duration" type and the "xios_get_context_attr"/"xios_set_context_attr" procedures should now be used to get/set the timestep.

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