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

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

Add registry

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