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

Last change on this file since 343 was 343, checked in by ymipsl, 12 years ago

remove "date" namespace

ym

File size: 17.8 KB
Line 
1#include "context.hpp"
2#include "tree_manager.hpp"
3
4#include "attribute_template_impl.hpp"
5#include "object_template_impl.hpp"
6#include "group_template_impl.hpp"
7
8#include "calendar_type.hpp"
9#include "duration.hpp"
10
11#include "context_client.hpp"
12#include "context_server.hpp"
13#include "nc4_data_output.hpp"
14
15namespace xios {
16namespace tree {
17   
18   /// ////////////////////// Définitions ////////////////////// ///
19
20   CContext::CContext(void)
21      : CObjectTemplate<CContext>(), CContextAttributes()
22      , calendar(),hasClient(false),hasServer(false)
23   { /* Ne rien faire de plus */ }
24
25   CContext::CContext(const StdString & id)
26      : CObjectTemplate<CContext>(id), CContextAttributes()
27      , calendar(),hasClient(false),hasServer(false)
28   { /* Ne rien faire de plus */ }
29
30   CContext::~CContext(void)
31   { 
32     if (hasClient) delete client ;
33     if (hasServer) delete server ;
34   }
35
36   //----------------------------------------------------------------
37
38   StdString CContext::GetName(void)   { return (StdString("context")); }
39   StdString CContext::GetDefName(void){ return (CContext::GetName()); }
40   ENodeType CContext::GetType(void)   { return (eContext); }
41
42   //----------------------------------------------------------------
43
44   boost::shared_ptr<CContextGroup> CContext::GetContextGroup(void)
45   { 
46      static boost::shared_ptr<CContextGroup> group_context
47                          (new CContextGroup(xml::CXMLNode::GetRootName()));
48      return (group_context); 
49   }
50   
51   //----------------------------------------------------------------
52   void CContext::setDataTreatment(boost::shared_ptr<data::CDataTreatment> ndatat)
53   {
54      this->datat = ndatat;
55   }
56
57   //----------------------------------------------------------------
58   boost::shared_ptr<data::CDataTreatment> CContext::getDataTreatment(void) const
59   {
60      return (this->datat);
61   }
62
63   //----------------------------------------------------------------
64
65   boost::shared_ptr<CCalendar> CContext::getCalendar(void) const
66   {
67      return (this->calendar);
68   }
69   
70   //----------------------------------------------------------------
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
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 de définir un calendrier (un attribut est manquant).");
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            << "Le calendrier n'est pas définie dans le code !");
107   }
108   
109   //----------------------------------------------------------------
110
111   void CContext::parse(xml::CXMLNode & node)
112   {
113      CContext::SuperClass::parse(node);
114
115      // PARSING POUR GESTION DES ENFANTS
116      xml::THashAttributes attributes = node.getAttributes();
117
118      if (attributes.end() != attributes.find("src"))
119      {
120         StdIFStream ifs ( attributes["src"].c_str() , StdIFStream::in );
121         if (!ifs.good())
122            ERROR("CContext::parse(xml::CXMLNode & node)",
123                  << "[ filename = " << attributes["src"] << " ] Bad xml stream !");
124         xml::CXMLParser::ParseInclude(ifs, *this);
125      }
126
127      if (node.getElementName().compare(CContext::GetName()))
128         DEBUG("Le noeud est mal nommé mais sera traité comme un contexte !");
129
130      if (!(node.goToChildElement()))
131      {
132         DEBUG("Le context ne contient pas d'enfant !");
133      }
134      else
135      {
136         do { // Parcours des contextes pour traitement.
137
138            StdString name = node.getElementName();
139            attributes.clear();
140            attributes = node.getAttributes();
141
142            if (attributes.end() != attributes.find("id"))
143            { DEBUG(<< "Le noeud de définition possÚde un identifiant,"
144                    << " ce dernier ne sera pas pris en compte lors du traitement !"); }
145
146#define DECLARE_NODE(Name_, name_)    \
147   if (name.compare(C##Name_##Definition::GetDefName()) == 0) \
148   { CObjectFactory::CreateObject<C##Name_##Definition>(C##Name_##Definition::GetDefName()) -> parse(node); \
149   continue; }
150#define DECLARE_NODE_PAR(Name_, name_)
151#include "node_type.conf"
152
153            DEBUG(<< "L'élément nommé \'"     << name
154                  << "\' dans le contexte \'" << CObjectFactory::GetCurrentContextId()
155                  << "\' ne représente pas une définition !");
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 =
168         CObjectFactory::GetCurrentContextId();
169      std::vector<boost::shared_ptr<CContext> > def_vector =
170         CContext::GetContextGroup()->getChildList();
171      std::vector<boost::shared_ptr<CContext> >::iterator
172         it = def_vector.begin(), end = def_vector.end();
173
174      out << "<? xml version=\"1.0\" ?>" << std::endl;
175      out << "<"  << xml::CXMLNode::GetRootName() << " >" << std::endl;
176     
177      for (; it != end; it++)
178      {
179         boost::shared_ptr<CContext> context = *it;         
180         CTreeManager::SetCurrentContextId(context->getId());         
181         out << *context << std::endl;
182      }
183     
184      out << "</" << xml::CXMLNode::GetRootName() << " >" << std::endl;
185      CTreeManager::SetCurrentContextId(currentContextId); 
186   }
187   
188   //----------------------------------------------------------------
189   
190   void CContext::toBinary(StdOStream & os) const
191   {
192      SuperClass::toBinary(os);
193       
194#define DECLARE_NODE(Name_, name_)                                         \
195   {                                                                       \
196      ENodeType renum = C##Name_##Definition::GetType();                   \
197      bool val = CObjectFactory::HasObject<C##Name_##Definition>           \
198                     (C##Name_##Definition::GetDefName());                 \
199      os.write (reinterpret_cast<const char*>(&renum), sizeof(ENodeType)); \
200      os.write (reinterpret_cast<const char*>(&val), sizeof(bool));        \
201      if (val) CObjectFactory::GetObject<C##Name_##Definition>             \
202                     (C##Name_##Definition::GetDefName())->toBinary(os);   \
203   }   
204#define DECLARE_NODE_PAR(Name_, name_)
205#include "node_type.conf"
206   }
207   
208   //----------------------------------------------------------------
209   
210   void CContext::fromBinary(StdIStream & is)
211   {
212      SuperClass::fromBinary(is);
213#define DECLARE_NODE(Name_, name_)                                         \
214   {                                                                       \
215      bool val = false;                                                    \
216      ENodeType renum = Unknown;                                           \
217      is.read (reinterpret_cast<char*>(&renum), sizeof(ENodeType));        \
218      is.read (reinterpret_cast<char*>(&val), sizeof(bool));               \
219      if (renum != C##Name_##Definition::GetType())                        \
220         ERROR("CContext::fromBinary(StdIStream & is)",                    \
221               << "[ renum = " << renum << "] Bad type !");                \
222      if (val) CObjectFactory::CreateObject<C##Name_##Definition>          \
223                   (C##Name_##Definition::GetDefName()) -> fromBinary(is); \
224   }   
225#define DECLARE_NODE_PAR(Name_, name_)
226#include "node_type.conf"
227     
228   }
229   
230   
231   //----------------------------------------------------------------
232
233   StdString CContext::toString(void) const
234   {
235      StdOStringStream oss;
236      oss << "<" << CContext::GetName()
237          << " id=\"" << this->getId() << "\" "
238          << SuperClassAttribute::toString() << ">" << std::endl;
239      if (!this->hasChild())
240      {
241         //oss << "<!-- No definition -->" << std::endl; // fait planter l'incrémentation
242      }
243      else
244      {
245
246#define DECLARE_NODE(Name_, name_)    \
247   if (CObjectFactory::HasObject<C##Name_##Definition>(C##Name_##Definition::GetDefName())) \
248   oss << *CObjectFactory::GetObject<C##Name_##Definition>(C##Name_##Definition::GetDefName()) << std::endl;
249#define DECLARE_NODE_PAR(Name_, name_)
250#include "node_type.conf"
251
252      }
253
254      oss << "</" << CContext::GetName() << " >";
255
256      return (oss.str());
257   }
258
259   //----------------------------------------------------------------
260
261   void CContext::solveDescInheritance(const CAttributeMap * const UNUSED(parent))
262   {
263#define DECLARE_NODE(Name_, name_)    \
264   if (CObjectFactory::HasObject<C##Name_##Definition>(C##Name_##Definition::GetDefName())) \
265   CObjectFactory::GetObject<C##Name_##Definition>(C##Name_##Definition::GetDefName())->solveDescInheritance();
266#define DECLARE_NODE_PAR(Name_, name_)
267#include "node_type.conf"
268   }
269
270   //----------------------------------------------------------------
271
272   bool CContext::hasChild(void) const
273   {
274      return (
275#define DECLARE_NODE(Name_, name_)    \
276   CObjectFactory::HasObject<C##Name_##Definition>  (C##Name_##Definition::GetDefName())   ||
277#define DECLARE_NODE_PAR(Name_, name_)
278#include "node_type.conf"
279      false);
280}
281
282   //----------------------------------------------------------------
283
284   void CContext::solveFieldRefInheritance(void)
285   {
286      if (!this->hasId()) return;
287      std::vector<boost::shared_ptr<CField> > allField
288               = CObjectTemplate<CField>::GetAllVectobject(this->getId());
289      std::vector<boost::shared_ptr<CField> >::iterator
290         it = allField.begin(), end = allField.end();
291           
292      for (; it != end; it++)
293      {
294         boost::shared_ptr<CField> field = *it;
295         field->solveRefInheritance();
296      }
297   }
298
299   //----------------------------------------------------------------
300
301   void CContext::CleanTree(void)
302   {
303#define DECLARE_NODE(Name_, name_) C##Name_##Group::ClearAllAttributes();
304#define DECLARE_NODE_PAR(Name_, name_)
305#include "node_type.conf"
306   }
307   ///---------------------------------------------------------------
308   
309   void CContext::initClient(MPI_Comm intraComm, MPI_Comm interComm)
310   {
311     hasClient=true ;
312     client = new CContextClient(this,intraComm, interComm) ;
313   } 
314
315   void CContext::initServer(MPI_Comm intraComm,MPI_Comm interComm)
316   {
317     hasServer=true ;
318     server = new CContextServer(this,intraComm,interComm) ;
319   } 
320
321   bool CContext::eventLoop(void)
322   {
323     return server->eventLoop() ;
324   } 
325   
326   void CContext::finalize(void)
327   {
328      if (hasClient && !hasServer)
329      {
330         client->finalize() ;
331      }
332      if (hasServer)
333      {
334        closeAllFile() ;
335      }
336   }
337       
338       
339 
340   
341   void CContext::closeDefinition(void)
342   {
343      if (hasClient && !hasServer) sendCloseDefinition() ;
344     
345      solveCalendar();         
346         
347      // Résolution des héritages pour le context actuel.
348      this->solveAllInheritance();
349
350      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
351      this->findEnabledFiles();
352
353      //Recherche des champs à sortir (enable à true + niveau de sortie correct)
354      // pour chaque fichier précédemment listé.
355      this->findAllEnabledFields();
356
357      // Résolution des références de grilles pour chacun des champs.
358      this->solveAllGridRef();
359
360      // Traitement des opérations.
361      this->solveAllOperation();
362
363      // Nettoyage de l'arborescence
364      CleanTree();
365      if (hasClient) sendCreateFileHeader() ;
366   }
367   
368   void CContext::findAllEnabledFields(void)
369   {
370     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
371     (void)this->enabledFiles[i]->getEnabledFields();
372   }
373
374   void CContext::solveAllGridRef(void)
375   {
376     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
377     this->enabledFiles[i]->solveEFGridRef();
378   }
379
380   void CContext::solveAllOperation(void)
381   {
382      for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
383      this->enabledFiles[i]->solveEFOperation();
384   }
385
386   void CContext::solveAllInheritance(void)
387   {
388     // Résolution des héritages descendants (càd des héritages de groupes)
389     // pour chacun des contextes.
390      solveDescInheritance();
391
392     // Résolution des héritages par référence au niveau des fichiers.
393      const std::vector<boost::shared_ptr<CFile> > & allFiles
394             = CObjectFactory::GetObjectVector<CFile>();
395
396      for (unsigned int i = 0; i < allFiles.size(); i++)
397         allFiles[i]->solveFieldRefInheritance();
398   }
399
400   void CContext::findEnabledFiles(void)
401   {
402      const std::vector<boost::shared_ptr<CFile> > & allFiles
403          = CObjectFactory::GetObjectVector<CFile>();
404
405      for (unsigned int i = 0; i < allFiles.size(); i++)
406         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
407            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
408               enabledFiles.push_back(allFiles[i]);
409
410      if (enabledFiles.size() == 0)
411         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
412               << getId() << "\" !");
413   }
414
415   void CContext::closeAllFile(void)
416   {
417     std::vector<boost::shared_ptr<CFile> >::const_iterator
418            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
419         
420     for (; it != end; it++)
421     {
422       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
423       (*it)->close();
424     }
425   }
426   
427   bool CContext::dispatchEvent(CEventServer& event)
428   {
429     
430      if (SuperClass::dispatchEvent(event)) return true ;
431      else
432      {
433        switch(event.type)
434        {
435           case EVENT_ID_CLOSE_DEFINITION :
436             recvCloseDefinition(event) ;
437             return true ;
438             break ;
439           case EVENT_ID_UPDATE_CALENDAR :
440             recvUpdateCalendar(event) ;
441             return true ;
442             break ;
443           case EVENT_ID_CREATE_FILE_HEADER :
444             recvCreateFileHeader(event) ;
445             return true ;
446             break ;
447           default :
448             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
449                    <<"Unknown Event") ;
450           return false ;
451         }
452      }
453   }
454   
455   void CContext::sendCloseDefinition(void)
456   {
457
458     CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION) ;   
459     if (client->isServerLeader())
460     {
461       CMessage msg ;
462       msg<<this->getId() ;
463       event.push(client->getServerLeader(),1,msg) ;
464       client->sendEvent(event) ;
465     }
466     else client->sendEvent(event) ;
467   }
468   
469   void CContext::recvCloseDefinition(CEventServer& event)
470   {
471     
472      CBufferIn* buffer=event.subEvents.begin()->buffer;
473      string id;
474      *buffer>>id ;
475      get(id)->closeDefinition() ;
476   }
477   
478   void CContext::sendUpdateCalendar(int step)
479   {
480     if (!hasServer)
481     {
482       CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR) ;   
483       if (client->isServerLeader())
484       {
485         CMessage msg ;
486         msg<<this->getId()<<step ;
487         event.push(client->getServerLeader(),1,msg) ;
488         client->sendEvent(event) ;
489       }
490       else client->sendEvent(event) ;
491     }
492   }
493   
494   void CContext::recvUpdateCalendar(CEventServer& event)
495   {
496     
497      CBufferIn* buffer=event.subEvents.begin()->buffer;
498      string id;
499      *buffer>>id ;
500      get(id)->recvUpdateCalendar(*buffer) ;
501   }
502   
503   void CContext::recvUpdateCalendar(CBufferIn& buffer)
504   {
505      int step ;
506      buffer>>step ;
507      updateCalendar(step) ;
508   }
509   
510   void CContext::sendCreateFileHeader(void)
511   {
512
513     CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER) ;   
514     if (client->isServerLeader())
515     {
516       CMessage msg ;
517       msg<<this->getId() ;
518       event.push(client->getServerLeader(),1,msg) ;
519       client->sendEvent(event) ;
520     }
521     else client->sendEvent(event) ;
522   }
523   
524   void CContext::recvCreateFileHeader(CEventServer& event)
525   {
526     
527      CBufferIn* buffer=event.subEvents.begin()->buffer;
528      string id;
529      *buffer>>id ;
530      get(id)->recvCreateFileHeader(*buffer) ;
531   }
532   
533   void CContext::recvCreateFileHeader(CBufferIn& buffer)
534   {
535      createFileHeader() ;
536   }
537   
538   void CContext::updateCalendar(int step)
539   {
540      info(50)<<"updateCalendar : before : "<<calendar->getCurrentDate()<<endl ;
541      calendar->update(step) ;
542      info(50)<<"updateCalendar : after : "<<calendar->getCurrentDate()<<endl ;
543   }
544 
545   void CContext::createFileHeader(void )
546   {
547      vector<shared_ptr<CFile> >::const_iterator it ;
548         
549      for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
550      {
551         (*it)->initFile();
552      }
553   } 
554   
555   shared_ptr<CContext> CContext::current(void)
556   {
557     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()) ;
558   }
559   
560} // namespace tree
561} // namespace xios
Note: See TracBrowser for help on using the repository browser.