source: XIOS/branchs/xios-1.0/src/node/context.cpp @ 535

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

Backport r534 to XIOS 1.0: Add an error message when the timestep was not configured by the user.

Previously no error message was displayed but the output file(s) was not written.

Also improve the error message when the calendar type or the start date is missing.

  • 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: 16.8 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)
26   { /* Ne rien faire de plus */ }
27
28   CContext::CContext(const StdString & id)
29      : CObjectTemplate<CContext>(id), CContextAttributes()
30      , calendar(),hasClient(false),hasServer(false)
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
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   CContextGroup* CContext::getRoot(void)
48   { 
49      if (root.get()==NULL) root=shared_ptr<CContextGroup>(new CContextGroup(xml::CXMLNode::GetRootName())) ;
50      return root.get(); 
51   }
52   
53
54   //----------------------------------------------------------------
55
56   boost::shared_ptr<CCalendar> CContext::getCalendar(void) const
57   {
58      return (this->calendar);
59   }
60   
61   //----------------------------------------------------------------
62   
63   void CContext::setCalendar(boost::shared_ptr<CCalendar> newCalendar)
64   {
65      this->calendar = newCalendar;
66      calendar_type.setValue(this->calendar->getId());
67      start_date.setValue(this->calendar->getInitDate().toString());
68   }
69   
70   //----------------------------------------------------------------
71
72   void CContext::solveCalendar(void)
73   {
74      if (this->calendar.get() != NULL) return;
75      if (calendar_type.isEmpty())
76         ERROR(" CContext::solveCalendar(void)",
77               << "[ context id = " << this->getId() << " ] "
78               << "Impossible to define a calendar: the calendar type is missing.");
79      if (start_date.isEmpty())
80         ERROR(" CContext::solveCalendar(void)",
81               << "[ context id = " << this->getId() << " ] "
82               << "Impossible to define a calendar: the start date is missing.");
83      if (timestep.isEmpty())
84         ERROR(" CContext::solveCalendar(void)",
85               << "[ context id = " << this->getId() << " ] "
86               << "Impossible to define a calendar: the timestep is missing.");
87
88#define DECLARE_CALENDAR(MType  , mtype)                              \
89   if (calendar_type.getValue().compare(#mtype) == 0)                 \
90   {                                                                  \
91      if (time_origin.isEmpty())                                       \
92        this->calendar =  boost::shared_ptr<CCalendar>          \
93           (new C##MType##Calendar(start_date.getValue()));     \
94      else this->calendar =  boost::shared_ptr<CCalendar>       \
95           (new C##MType##Calendar(start_date.getValue(),time_origin.getValue()));     \
96      this->calendar->setTimeStep                                     \
97          (CDuration::FromString(this->timestep.getValue()));   \
98      return;                                                         \
99   }
100#include "calendar_type.conf"
101
102      ERROR("CContext::solveCalendar(void)",
103            << "[ calendar_type = " << calendar_type.getValue() << " ] "
104            << "The calendar is not defined !");
105   }
106   
107   //----------------------------------------------------------------
108
109   void CContext::parse(xml::CXMLNode & node)
110   {
111      CContext::SuperClass::parse(node);
112
113      // PARSING POUR GESTION DES ENFANTS
114      xml::THashAttributes attributes = node.getAttributes();
115
116      if (attributes.end() != attributes.find("src"))
117      {
118         StdIFStream ifs ( attributes["src"].c_str() , StdIFStream::in );
119         if ( (ifs.rdstate() & std::ifstream::failbit ) != 0 )
120            ERROR("void CContext::parse(xml::CXMLNode & node)",
121                  <<endl<< "Can not open <"<<attributes["src"].c_str()<<"> file" );
122         if (!ifs.good())
123            ERROR("CContext::parse(xml::CXMLNode & node)",
124                  << "[ filename = " << attributes["src"] << " ] Bad xml stream !");
125         xml::CXMLParser::ParseInclude(ifs, attributes["src"], *this);
126      }
127
128      if (node.getElementName().compare(CContext::GetName()))
129         DEBUG("Le noeud is wrong defined but will be considered as a context !");
130
131      if (!(node.goToChildElement()))
132      {
133         DEBUG("Le context ne contient pas d'enfant !");
134      }
135      else
136      {
137         do { // Parcours des contextes pour traitement.
138
139            StdString name = node.getElementName();
140            attributes.clear();
141            attributes = node.getAttributes();
142
143            if (attributes.end() != attributes.find("id"))
144            { DEBUG(<< "Definition node has an id,"
145                    << "it will not be taking account !"); }
146
147#define DECLARE_NODE(Name_, name_)    \
148   if (name.compare(C##Name_##Definition::GetDefName()) == 0) \
149   { C##Name_##Definition::create(C##Name_##Definition::GetDefName()) -> parse(node) ; continue; }
150#define DECLARE_NODE_PAR(Name_, name_)
151#include "node_type.conf"
152
153            DEBUG(<< "The element \'"     << name
154                  << "\' in the context \'" << CContext::getCurrent()->getId()
155                  << "\' is not a definition !");
156
157         } while (node.goToNextElement());
158
159         node.goToParentElement(); // Retour au parent
160      }
161   }
162
163   //----------------------------------------------------------------
164
165   void CContext::ShowTree(StdOStream & out)
166   {
167      StdString currentContextId = CContext::getCurrent() -> getId() ;
168      std::vector<CContext*> def_vector =
169         CContext::getRoot()->getChildList();
170      std::vector<CContext*>::iterator
171         it = def_vector.begin(), end = def_vector.end();
172
173      out << "<? xml version=\"1.0\" ?>" << std::endl;
174      out << "<"  << xml::CXMLNode::GetRootName() << " >" << std::endl;
175     
176      for (; it != end; it++)
177      {
178         CContext* context = *it;         
179         CContext::setCurrent(context->getId());         
180         out << *context << std::endl;
181      }
182     
183      out << "</" << xml::CXMLNode::GetRootName() << " >" << std::endl;
184      CContext::setCurrent(currentContextId); 
185   }
186   
187
188   //----------------------------------------------------------------
189
190   StdString CContext::toString(void) const
191   {
192      StdOStringStream oss;
193      oss << "<" << CContext::GetName()
194          << " id=\"" << this->getId() << "\" "
195          << SuperClassAttribute::toString() << ">" << std::endl;
196      if (!this->hasChild())
197      {
198         //oss << "<!-- No definition -->" << std::endl; // fait planter l'incrémentation
199      }
200      else
201      {
202
203#define DECLARE_NODE(Name_, name_)    \
204   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
205   oss << * C##Name_##Definition::get(C##Name_##Definition::GetDefName()) << std::endl;
206#define DECLARE_NODE_PAR(Name_, name_)
207#include "node_type.conf"
208
209      }
210
211      oss << "</" << CContext::GetName() << " >";
212
213      return (oss.str());
214   }
215
216   //----------------------------------------------------------------
217
218   void CContext::solveDescInheritance(bool apply, const CAttributeMap * const UNUSED(parent))
219   {
220#define DECLARE_NODE(Name_, name_)    \
221   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
222     C##Name_##Definition::get(C##Name_##Definition::GetDefName())->solveDescInheritance(apply);
223#define DECLARE_NODE_PAR(Name_, name_)
224#include "node_type.conf"
225   }
226
227   //----------------------------------------------------------------
228
229   bool CContext::hasChild(void) const
230   {
231      return (
232#define DECLARE_NODE(Name_, name_)    \
233   C##Name_##Definition::has(C##Name_##Definition::GetDefName())   ||
234#define DECLARE_NODE_PAR(Name_, name_)
235#include "node_type.conf"
236      false);
237}
238
239   //----------------------------------------------------------------
240
241   void CContext::solveFieldRefInheritance(bool apply)
242   {
243      if (!this->hasId()) return;
244      vector<CField*> allField = CField::getAll() ;
245//              = CObjectTemplate<CField>::GetAllVectobject(this->getId());
246      std::vector<CField*>::iterator
247         it = allField.begin(), end = allField.end();
248           
249      for (; it != end; it++)
250      {
251         CField* field = *it;
252         field->solveRefInheritance(apply);
253      }
254   }
255
256   //----------------------------------------------------------------
257
258   void CContext::CleanTree(void)
259   {
260#define DECLARE_NODE(Name_, name_) C##Name_##Group::ClearAllAttributes();
261#define DECLARE_NODE_PAR(Name_, name_)
262#include "node_type.conf"
263   }
264   ///---------------------------------------------------------------
265   
266   void CContext::initClient(MPI_Comm intraComm, MPI_Comm interComm)
267   {
268     hasClient=true ;
269     client = new CContextClient(this,intraComm, interComm) ;
270   } 
271
272   bool CContext::isInitialized(void)
273   {
274     return hasClient ;
275   }
276   
277   void CContext::initServer(MPI_Comm intraComm,MPI_Comm interComm)
278   {
279     hasServer=true ;
280     server = new CContextServer(this,intraComm,interComm) ;
281   } 
282
283   bool CContext::eventLoop(void)
284   {
285     return server->eventLoop() ;
286   } 
287   
288   void CContext::finalize(void)
289   {
290      if (hasClient && !hasServer)
291      {
292         client->finalize() ;
293      }
294      if (hasServer)
295      {
296        closeAllFile() ;
297      }
298   }
299       
300       
301 
302   
303   void CContext::closeDefinition(void)
304   {
305      if (hasClient && !hasServer) sendCloseDefinition() ;
306     
307      solveCalendar();         
308         
309      // Résolution des héritages pour le context actuel.
310      this->solveAllInheritance();
311
312      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
313      this->findEnabledFiles();
314
315       
316      this->processEnabledFiles() ;
317
318/*       
319      //Recherche des champs à sortir (enable à true + niveau de sortie correct)
320      // pour chaque fichier précédemment listé.
321      this->findAllEnabledFields();
322
323      // Résolution des références de grilles pour chacun des champs.
324      this->solveAllGridRef();
325
326      // Traitement des opérations.
327      this->solveAllOperation();
328
329      // Traitement des expressions.
330      this->solveAllExpression();
331*/
332      // Nettoyage de l'arborescence
333      CleanTree();
334      if (hasClient) sendCreateFileHeader() ;
335   }
336   
337   void CContext::findAllEnabledFields(void)
338   {
339     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
340     (void)this->enabledFiles[i]->getEnabledFields();
341   }
342   
343    void CContext::processEnabledFiles(void)
344   {
345     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
346     this->enabledFiles[i]->processEnabledFile();
347   }
348 
349
350   void CContext::solveAllGridRef(void)
351   {
352     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
353     this->enabledFiles[i]->solveEFGridRef();
354   }
355
356   void CContext::solveAllOperation(void)
357   {
358      for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
359      this->enabledFiles[i]->solveEFOperation();
360   }
361
362   void CContext::solveAllExpression(void)
363   {
364      for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
365      this->enabledFiles[i]->solveEFExpression();
366   }
367   
368   void CContext::solveAllInheritance(bool apply)
369   {
370     // Résolution des héritages descendants (càd des héritages de groupes)
371     // pour chacun des contextes.
372      solveDescInheritance(apply);
373
374     // Résolution des héritages par référence au niveau des fichiers.
375      const vector<CFile*> allFiles=CFile::getAll() ;
376
377      for (unsigned int i = 0; i < allFiles.size(); i++)
378         allFiles[i]->solveFieldRefInheritance(apply);
379   }
380
381   void CContext::findEnabledFiles(void)
382   {
383      const std::vector<CFile*> allFiles = CFile::getAll();
384
385      for (unsigned int i = 0; i < allFiles.size(); i++)
386         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
387         {
388            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
389               enabledFiles.push_back(allFiles[i]);
390         }
391         else enabledFiles.push_back(allFiles[i]); // otherwise true by default
392               
393
394      if (enabledFiles.size() == 0)
395         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
396               << getId() << "\" !");
397   }
398
399   void CContext::closeAllFile(void)
400   {
401     std::vector<CFile*>::const_iterator
402            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
403         
404     for (; it != end; it++)
405     {
406       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
407       (*it)->close();
408     }
409   }
410   
411   bool CContext::dispatchEvent(CEventServer& event)
412   {
413     
414      if (SuperClass::dispatchEvent(event)) return true ;
415      else
416      {
417        switch(event.type)
418        {
419           case EVENT_ID_CLOSE_DEFINITION :
420             recvCloseDefinition(event) ;
421             return true ;
422             break ;
423           case EVENT_ID_UPDATE_CALENDAR :
424             recvUpdateCalendar(event) ;
425             return true ;
426             break ;
427           case EVENT_ID_CREATE_FILE_HEADER :
428             recvCreateFileHeader(event) ;
429             return true ;
430             break ;
431           default :
432             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
433                    <<"Unknown Event") ;
434           return false ;
435         }
436      }
437   }
438   
439   void CContext::sendCloseDefinition(void)
440   {
441
442     CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION) ;   
443     if (client->isServerLeader())
444     {
445       CMessage msg ;
446       msg<<this->getId() ;
447       event.push(client->getServerLeader(),1,msg) ;
448       client->sendEvent(event) ;
449     }
450     else client->sendEvent(event) ;
451   }
452   
453   void CContext::recvCloseDefinition(CEventServer& event)
454   {
455     
456      CBufferIn* buffer=event.subEvents.begin()->buffer;
457      string id;
458      *buffer>>id ;
459      get(id)->closeDefinition() ;
460   }
461   
462   void CContext::sendUpdateCalendar(int step)
463   {
464     if (!hasServer)
465     {
466       CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR) ;   
467       if (client->isServerLeader())
468       {
469         CMessage msg ;
470         msg<<this->getId()<<step ;
471         event.push(client->getServerLeader(),1,msg) ;
472         client->sendEvent(event) ;
473       }
474       else client->sendEvent(event) ;
475     }
476   }
477   
478   void CContext::recvUpdateCalendar(CEventServer& event)
479   {
480     
481      CBufferIn* buffer=event.subEvents.begin()->buffer;
482      string id;
483      *buffer>>id ;
484      get(id)->recvUpdateCalendar(*buffer) ;
485   }
486   
487   void CContext::recvUpdateCalendar(CBufferIn& buffer)
488   {
489      int step ;
490      buffer>>step ;
491      updateCalendar(step) ;
492   }
493   
494   void CContext::sendCreateFileHeader(void)
495   {
496
497     CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER) ;   
498     if (client->isServerLeader())
499     {
500       CMessage msg ;
501       msg<<this->getId() ;
502       event.push(client->getServerLeader(),1,msg) ;
503       client->sendEvent(event) ;
504     }
505     else client->sendEvent(event) ;
506   }
507   
508   void CContext::recvCreateFileHeader(CEventServer& event)
509   {
510     
511      CBufferIn* buffer=event.subEvents.begin()->buffer;
512      string id;
513      *buffer>>id ;
514      get(id)->recvCreateFileHeader(*buffer) ;
515   }
516   
517   void CContext::recvCreateFileHeader(CBufferIn& buffer)
518   {
519      createFileHeader() ;
520   }
521   
522   void CContext::updateCalendar(int step)
523   {
524      info(50)<<"updateCalendar : before : "<<calendar->getCurrentDate()<<endl ;
525      calendar->update(step) ;
526      info(50)<<"updateCalendar : after : "<<calendar->getCurrentDate()<<endl ;
527   }
528 
529   void CContext::createFileHeader(void )
530   {
531      vector<CFile*>::const_iterator it ;
532         
533      for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
534      {
535         (*it)->initFile();
536      }
537   } 
538   
539   CContext* CContext::getCurrent(void)
540   {
541     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get() ;
542   }
543   
544   void CContext::setCurrent(const string& id)
545   {
546     CObjectFactory::SetCurrentContextId(id);
547     CGroupFactory::SetCurrentContextId(id);
548   }
549   
550  CContext* CContext::create(const StdString& id)
551  {
552    CContext::setCurrent(id) ;
553 
554    bool hasctxt = CContext::has(id);
555    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
556    getRoot() ;
557    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
558
559#define DECLARE_NODE(Name_, name_) \
560    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
561#define DECLARE_NODE_PAR(Name_, name_)
562#include "node_type.conf"
563
564    return (context);
565  }
566} // namespace xios
Note: See TracBrowser for help on using the repository browser.