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

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

Suppress access to CObjectFactory class and CTreeManager.

YM

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