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

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

Removing obsolete files and some cleaning...

YM

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