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

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

Expose the calendar operations through the Fortran interface.

  • Add arithmetic operations on the xios_duration and xios_date types:
    • xios_duration + xios_duration = xios_duration
    • xios_duration - xios_duration = xios_duration
    • scalar * xios_duration = xios_duration * scalar = xios_duration
    • - xios_duration = xios_duration
    • xios_date + xios_duration = xios_date
    • xios_date - xios_duration = xios_date
    • xios_date - xios_date = xios_duration
  • Add comparison operations on the xios_duration and xios_date types:
    • xios_duration: ==, /=
    • xios_date: ==, /=, <, <=, >, >=
  • Add a new function "xios_date_convert_to_seconds" to convert a date into the number of seconds since the time origin of the calendar
  • Define some constant durations "xios_second", "xios_minute", "xios_hour", "xios_day", "xios_month", "xios_year" et "xios_timestep" to ease the definition of new durations (for example, 10h is just 10 * xios_hour)
  • Add a new function "xios_set_calendar" so that one can manually create the calendar attached to the current context and thus use the calendar operations before calling "xios_close_context_definition". This function can accept optional parameters so that the calendar attributes (calendar_type, start_date, time_origin and timestep) can be easily overwritten. Note that you cannot define a new calendar after one was already created (either because "xios_set_calendar" or "xios_close_context_definition" was used)
  • Readd the function "xios_set_timestep" as a simplified alias of "xios_set_context_attr(context, timestep)" for the current context
  • 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: 31.6 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), isPostProcessed(false), dataSize_(), idServer_()
26   { /* Ne rien faire de plus */ }
27
28   CContext::CContext(const StdString & id)
29      : CObjectTemplate<CContext>(id), CContextAttributes()
30      , calendar(),hasClient(false),hasServer(false), isPostProcessed(false), dataSize_(), idServer_()
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   //! Get name of context
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   \brief Get context group (context root)
48   \return Context root
49   */
50   CContextGroup* CContext::getRoot(void)
51   {
52      if (root.get()==NULL) root=shared_ptr<CContextGroup>(new CContextGroup(xml::CXMLNode::GetRootName())) ;
53      return root.get();
54   }
55
56
57   //----------------------------------------------------------------
58   /*!
59   \brief Get calendar of a context
60   \return Calendar
61   */
62   boost::shared_ptr<CCalendar> CContext::getCalendar(void) const
63   {
64      return (this->calendar);
65   }
66
67   //----------------------------------------------------------------
68   /*!
69   \brief Set a context with a calendar
70   \param[in] newCalendar new calendar
71   */
72   void CContext::setCalendar(boost::shared_ptr<CCalendar> newCalendar)
73   {
74      this->calendar = newCalendar;
75      calendar_type.fromString(this->calendar->getId());
76      start_date.setValue(this->calendar->getInitDate());
77   }
78
79   //----------------------------------------------------------------
80   //! Process all information of calendar
81   void CContext::solveCalendar(void)
82   {
83      if (calendar_type.isEmpty())
84         ERROR(" CContext::solveCalendar(void)",
85               << "[ context id = " << this->getId() << " ] "
86               << "Impossible to define a calendar: the calendar type is missing.");
87      if (start_date.isEmpty())
88         ERROR(" CContext::solveCalendar(void)",
89               << "[ context id = " << this->getId() << " ] "
90               << "Impossible to define a calendar: the start date is missing.");
91      if (timestep.isEmpty())
92         ERROR(" CContext::solveCalendar(void)",
93               << "[ context id = " << this->getId() << " ] "
94               << "Impossible to define a calendar: the timestep is missing.");
95
96      if (this->calendar)
97      {
98        if (this->calendar->getId() != calendar_type.getStringValue()
99              || this->calendar->getInitDate() != start_date.getValue()
100              || (time_origin.isEmpty() && this->calendar->getTimeOrigin() != start_date.getValue())
101              || (!time_origin.isEmpty() && this->calendar->getTimeOrigin() != time_origin.getValue())
102              || this->calendar->getTimeStep() != timestep.getValue())
103          ERROR(" CContext::solveCalendar(void)",
104                << "[ context id = " << this->getId() << " ] "
105                << "Impossible to define a calendar again with new parameters.");
106        return;
107      }
108
109#define DECLARE_CALENDAR(MType, eType)                                             \
110  if (calendar_type.getValue() == eType)                                           \
111  {                                                                                \
112    if (time_origin.isEmpty())                                                     \
113      this->calendar = boost::shared_ptr<CCalendar>                                \
114          (new C##MType##Calendar(start_date.getValue()));                         \
115    else this->calendar = boost::shared_ptr<CCalendar>                             \
116          (new C##MType##Calendar(start_date.getValue(), time_origin.getValue())); \
117                                                                                   \
118    if (!start_date.getValue().setRelCalendar(*this->calendar))                    \
119      ERROR("CContext::solveCalendar(void)",                                       \
120            "start_date: Bad format or date not conform to the calendar");         \
121    if (!time_origin.getValue().setRelCalendar(*this->calendar))                   \
122      ERROR("CContext::solveCalendar(void)",                                       \
123            "time_origin: Bad format or date not conform to the calendar");        \
124                                                                                   \
125    this->calendar->setTimeStep(this->timestep.getValue());                        \
126                                                                                   \
127    return;                                                                        \
128  }
129#include "calendar_type.conf"
130#undef DECLARE_CALENDAR
131
132      ERROR("CContext::solveCalendar(void)",
133            << "[ calendar_type = " << calendar_type.getStringValue() << " ] "
134            << "The calendar is not properly handled!");
135   }
136
137   //----------------------------------------------------------------
138   /*!
139   \brief Parse xml file and write information into context object
140   \param [in] node xmld node corresponding in xml file
141   */
142   void CContext::parse(xml::CXMLNode & node)
143   {
144      CContext::SuperClass::parse(node);
145
146      // PARSING POUR GESTION DES ENFANTS
147      xml::THashAttributes attributes = node.getAttributes();
148
149      if (attributes.end() != attributes.find("src"))
150      {
151         StdIFStream ifs ( attributes["src"].c_str() , StdIFStream::in );
152         if ( (ifs.rdstate() & std::ifstream::failbit ) != 0 )
153            ERROR("void CContext::parse(xml::CXMLNode & node)",
154                  <<endl<< "Can not open <"<<attributes["src"].c_str()<<"> file" );
155         if (!ifs.good())
156            ERROR("CContext::parse(xml::CXMLNode & node)",
157                  << "[ filename = " << attributes["src"] << " ] Bad xml stream !");
158         xml::CXMLParser::ParseInclude(ifs, attributes["src"], *this);
159      }
160
161      if (node.getElementName().compare(CContext::GetName()))
162         DEBUG("Le noeud is wrong defined but will be considered as a context !");
163
164      if (!(node.goToChildElement()))
165      {
166         DEBUG("Le context ne contient pas d'enfant !");
167      }
168      else
169      {
170         do { // Parcours des contextes pour traitement.
171
172            StdString name = node.getElementName();
173            attributes.clear();
174            attributes = node.getAttributes();
175
176            if (attributes.end() != attributes.find("id"))
177            {
178              DEBUG(<< "Definition node has an id,"
179                    << "it will not be taking account !");
180            }
181
182#define DECLARE_NODE(Name_, name_)    \
183   if (name.compare(C##Name_##Definition::GetDefName()) == 0) \
184   { C##Name_##Definition::create(C##Name_##Definition::GetDefName()) -> parse(node) ; continue; }
185#define DECLARE_NODE_PAR(Name_, name_)
186#include "node_type.conf"
187
188            DEBUG(<< "The element \'"     << name
189                  << "\' in the context \'" << CContext::getCurrent()->getId()
190                  << "\' is not a definition !");
191
192         } while (node.goToNextElement());
193
194         node.goToParentElement(); // Retour au parent
195      }
196   }
197
198   //----------------------------------------------------------------
199   //! Show tree structure of context
200   void CContext::ShowTree(StdOStream & out)
201   {
202      StdString currentContextId = CContext::getCurrent() -> getId() ;
203      std::vector<CContext*> def_vector =
204         CContext::getRoot()->getChildList();
205      std::vector<CContext*>::iterator
206         it = def_vector.begin(), end = def_vector.end();
207
208      out << "<? xml version=\"1.0\" ?>" << std::endl;
209      out << "<"  << xml::CXMLNode::GetRootName() << " >" << std::endl;
210
211      for (; it != end; it++)
212      {
213         CContext* context = *it;
214         CContext::setCurrent(context->getId());
215         out << *context << std::endl;
216      }
217
218      out << "</" << xml::CXMLNode::GetRootName() << " >" << std::endl;
219      CContext::setCurrent(currentContextId);
220   }
221
222
223   //----------------------------------------------------------------
224
225   //! Convert context object into string (to print)
226   StdString CContext::toString(void) const
227   {
228      StdOStringStream oss;
229      oss << "<" << CContext::GetName()
230          << " id=\"" << this->getId() << "\" "
231          << SuperClassAttribute::toString() << ">" << std::endl;
232      if (!this->hasChild())
233      {
234         //oss << "<!-- No definition -->" << std::endl; // fait planter l'incrémentation
235      }
236      else
237      {
238
239#define DECLARE_NODE(Name_, name_)    \
240   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
241   oss << * C##Name_##Definition::get(C##Name_##Definition::GetDefName()) << std::endl;
242#define DECLARE_NODE_PAR(Name_, name_)
243#include "node_type.conf"
244
245      }
246
247      oss << "</" << CContext::GetName() << " >";
248
249      return (oss.str());
250   }
251
252   //----------------------------------------------------------------
253
254   /*!
255   \brief Find all inheritace among objects in a context.
256   \param [in] apply (true) write attributes of parent into ones of child if they are empty
257                     (false) write attributes of parent into a new container of child
258   \param [in] parent unused
259   */
260   void CContext::solveDescInheritance(bool apply, const CAttributeMap * const UNUSED(parent))
261   {
262#define DECLARE_NODE(Name_, name_)    \
263   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
264     C##Name_##Definition::get(C##Name_##Definition::GetDefName())->solveDescInheritance(apply);
265#define DECLARE_NODE_PAR(Name_, name_)
266#include "node_type.conf"
267   }
268
269   //----------------------------------------------------------------
270
271   //! Verify if all root definition in the context have child.
272   bool CContext::hasChild(void) const
273   {
274      return (
275#define DECLARE_NODE(Name_, name_)    \
276   C##Name_##Definition::has(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(bool apply)
285//   {
286//      if (!this->hasId()) return;
287//      vector<CField*> allField = CField::getAll() ;
288////              = CObjectTemplate<CField>::GetAllVectobject(this->getId());
289//      std::vector<CField*>::iterator
290//         it = allField.begin(), end = allField.end();
291//
292//      for (; it != end; it++)
293//      {
294//         CField* field = *it;
295//         field->solveRefInheritance(apply);
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   //! Initialize client side
310   void CContext::initClient(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtServer)
311   {
312     hasClient=true ;
313     client = new CContextClient(this,intraComm, interComm, cxtServer) ;
314   }
315
316   void CContext::setClientServerBuffer()
317   {
318     if (hasClient)
319     {
320       client->setBufferSize(getDataSize());
321     }
322   }
323
324   //! Verify whether a context is initialized
325   bool CContext::isInitialized(void)
326   {
327     return hasClient ;
328   }
329
330   //! Initialize server
331   void CContext::initServer(MPI_Comm intraComm,MPI_Comm interComm)
332   {
333     hasServer=true ;
334     server = new CContextServer(this,intraComm,interComm) ;
335   }
336
337   //! Server side: Put server into a loop in order to listen message from client
338   bool CContext::eventLoop(void)
339   {
340     return server->eventLoop() ;
341   }
342
343   //! Terminate a context
344   void CContext::finalize(void)
345   {
346      if (hasClient && !hasServer)
347      {
348         client->finalize() ;
349      }
350      if (hasServer)
351      {
352        closeAllFile() ;
353      }
354   }
355
356   /*!
357   \brief Close all the context defintion and do processing data
358      After everything is well defined on client side, they will be processed and sent to server
359   From the version 2.0, sever and client work no more on the same database. Moreover, client(s) will send
360   all necessary information to server, from which each server can build its own database.
361   Because the role of server is to write out field data on a specific netcdf file,
362   the only information that it needs is the enabled files
363   and the active fields (fields will be written onto active files)
364   */
365   void CContext::closeDefinition(void)
366   {
367
368     if (hasClient)
369     {
370//       std::cout << "Current context " << *this << std::endl;
371       // After xml is parsed, there are some more works with post processing
372       postProcessing();
373//
374       setClientServerBuffer();
375     }
376
377     if (hasClient && !hasServer)
378     {
379       // After xml is parsed, there are some more works with post processing
380//       postProcessing();
381
382//       setClientServerBuffer();
383
384      // Send all attributes of current context to server
385      this->sendAllAttributesToServer();
386
387      // We have enough information to send to server
388      // First of all, send all enabled files
389       sendEnabledFiles();
390
391      // Then, send all enabled fields
392       sendEnabledFields();
393
394      // At last, we have all info of domain and axis, then send them
395       sendRefDomainsAxis();
396
397      // After that, send all grid (if any)
398       sendRefGrid();
399
400
401    }
402
403    // Now tell server that it can process all messages from client
404    if (hasClient && !hasServer) this->sendCloseDefinition();
405
406    // We have a xml tree on the server side and now, it should be also processed
407    if (hasClient && !hasServer) sendPostProcessing();
408
409    // There are some processings that should be done after all of above. For example: check mask or index
410//    if (hasClient && !hasServer)
411    if (hasClient)
412    {
413      this->solveAllRefOfEnabledFields(true);
414      this->buildAllExpressionOfEnabledFields();
415    }
416
417
418
419//      if (hasClient)
420//      {
421//        //solveCalendar();
422//
423//        // Résolution des héritages pour le context actuel.
424////        this->solveAllInheritance();
425//
426//
427////        //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
428////        this->findEnabledFiles();
429//
430//        this->processEnabledFiles() ;
431//
432//        this->solveAllGridRef();
433//      }
434
435
436
437
438//      solveCalendar();
439//
440//      // Résolution des héritages pour le context actuel.
441//      this->solveAllInheritance();
442//
443//      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
444//      this->findEnabledFiles();
445//
446//
447//      this->processEnabledFiles() ;
448
449/*
450      //Recherche des champs à sortir (enable à true + niveau de sortie correct)
451      // pour chaque fichier précédemment listé.
452      this->findAllEnabledFields();
453
454      // Résolution des références de grilles pour chacun des champs.
455      this->solveAllGridRef();
456
457      // Traitement des opérations.
458      this->solveAllOperation();
459
460      // Traitement des expressions.
461      this->solveAllExpression();
462*/
463      // Nettoyage de l'arborescence
464      if (hasClient && !hasServer) CleanTree(); // Only on client side??
465//      if (hasClient) CleanTree();
466      if (hasClient) sendCreateFileHeader() ;
467   }
468
469   void CContext::findAllEnabledFields(void)
470   {
471     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
472     (void)this->enabledFiles[i]->getEnabledFields();
473   }
474
475//    void CContext::processEnabledFiles(void)
476//   {
477//     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
478//     this->enabledFiles[i]->processEnabledFile();
479//   }
480
481
482   void CContext::solveAllRefOfEnabledFields(bool sendToServer)
483   {
484     int size = this->enabledFiles.size();
485     for (int i = 0; i < size; ++i)
486     {
487       this->enabledFiles[i]->solveAllRefOfEnabledFields(sendToServer);
488     }
489   }
490
491   void CContext::buildAllExpressionOfEnabledFields()
492   {
493     int size = this->enabledFiles.size();
494     for (int i = 0; i < size; ++i)
495     {
496       this->enabledFiles[i]->buildAllExpressionOfEnabledFields();
497     }
498   }
499
500//   void CContext::solveAllGridRef(void)
501//   {
502//     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
503//     this->enabledFiles[i]->solveEFGridRef();
504//   }
505//
506//   void CContext::solveAllOperation(void)
507//   {
508//      for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
509//      this->enabledFiles[i]->solveEFOperation();
510//   }
511//
512//   void CContext::solveAllExpression(void)
513//   {
514//      for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
515//      this->enabledFiles[i]->solveEFExpression();
516//   }
517
518   void CContext::solveAllInheritance(bool apply)
519   {
520     // Résolution des héritages descendants (càd des héritages de groupes)
521     // pour chacun des contextes.
522      solveDescInheritance(apply);
523
524     // Résolution des héritages par référence au niveau des fichiers.
525      const vector<CFile*> allFiles=CFile::getAll() ;
526      const vector<CGrid*> allGrids= CGrid::getAll();
527
528     //if (hasClient && !hasServer)
529      if (hasClient)
530      {
531        for (unsigned int i = 0; i < allFiles.size(); i++)
532          allFiles[i]->solveFieldRefInheritance(apply);
533      }
534
535      unsigned int vecSize = allGrids.size();
536      unsigned int i = 0;
537      for (i = 0; i < vecSize; ++i)
538        allGrids[i]->solveDomainAxisRefInheritance(apply);
539
540   }
541
542   void CContext::findEnabledFiles(void)
543   {
544      const std::vector<CFile*> allFiles = CFile::getAll();
545
546      for (unsigned int i = 0; i < allFiles.size(); i++)
547         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
548         {
549            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
550               enabledFiles.push_back(allFiles[i]);
551         }
552         else enabledFiles.push_back(allFiles[i]); // otherwise true by default
553
554
555      if (enabledFiles.size() == 0)
556         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
557               << getId() << "\" !");
558   }
559
560   void CContext::closeAllFile(void)
561   {
562     std::vector<CFile*>::const_iterator
563            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
564
565     for (; it != end; it++)
566     {
567       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
568       (*it)->close();
569     }
570   }
571
572   /*!
573   \brief Dispatch event received from client
574      Whenever a message is received in buffer of server, it will be processed depending on
575   its event type. A new event type should be added in the switch list to make sure
576   it processed on server side.
577   \param [in] event: Received message
578   */
579   bool CContext::dispatchEvent(CEventServer& event)
580   {
581
582      if (SuperClass::dispatchEvent(event)) return true ;
583      else
584      {
585        switch(event.type)
586        {
587           case EVENT_ID_CLOSE_DEFINITION :
588             recvCloseDefinition(event) ;
589             return true ;
590             break ;
591           case EVENT_ID_UPDATE_CALENDAR :
592             recvUpdateCalendar(event) ;
593             return true ;
594             break ;
595           case EVENT_ID_CREATE_FILE_HEADER :
596             recvCreateFileHeader(event) ;
597             return true ;
598             break ;
599           case EVENT_ID_POST_PROCESS:
600             recvPostProcessing(event) ;
601             return true ;
602             break ;
603           default :
604             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
605                    <<"Unknown Event") ;
606           return false ;
607         }
608      }
609   }
610
611   //! Client side: Send a message to server to make it close
612   void CContext::sendCloseDefinition(void)
613   {
614     CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION) ;
615     if (client->isServerLeader())
616     {
617       CMessage msg ;
618       msg<<this->getIdServer() ;
619       event.push(client->getServerLeader(),1,msg) ;
620       client->sendEvent(event) ;
621     }
622     else client->sendEvent(event) ;
623   }
624
625   //! Server side: Receive a message of client announcing a context close
626   void CContext::recvCloseDefinition(CEventServer& event)
627   {
628
629      CBufferIn* buffer=event.subEvents.begin()->buffer;
630      string id;
631      *buffer>>id ;
632      get(id)->closeDefinition();
633   }
634
635   //! Client side: Send a message to update calendar in each time step
636   void CContext::sendUpdateCalendar(int step)
637   {
638     if (!hasServer)
639     {
640       CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR) ;
641       if (client->isServerLeader())
642       {
643         CMessage msg ;
644         msg<<this->getIdServer()<<step ;
645         event.push(client->getServerLeader(),1,msg) ;
646         client->sendEvent(event) ;
647       }
648       else client->sendEvent(event) ;
649     }
650   }
651
652   //! Server side: Receive a message of client annoucing calendar update
653   void CContext::recvUpdateCalendar(CEventServer& event)
654   {
655
656      CBufferIn* buffer=event.subEvents.begin()->buffer;
657      string id;
658      *buffer>>id ;
659      get(id)->recvUpdateCalendar(*buffer) ;
660   }
661
662   //! Server side: Receive a message of client annoucing calendar update
663   void CContext::recvUpdateCalendar(CBufferIn& buffer)
664   {
665      int step ;
666      buffer>>step ;
667      updateCalendar(step) ;
668   }
669
670   //! Client side: Send a message to create header part of netcdf file
671   void CContext::sendCreateFileHeader(void)
672   {
673     CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER) ;
674     if (client->isServerLeader())
675     {
676       CMessage msg ;
677       msg<<this->getIdServer() ;
678       event.push(client->getServerLeader(),1,msg) ;
679       client->sendEvent(event) ;
680     }
681     else client->sendEvent(event) ;
682   }
683
684   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
685   void CContext::recvCreateFileHeader(CEventServer& event)
686   {
687      CBufferIn* buffer=event.subEvents.begin()->buffer;
688      string id;
689      *buffer>>id ;
690      get(id)->recvCreateFileHeader(*buffer) ;
691   }
692
693   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
694   void CContext::recvCreateFileHeader(CBufferIn& buffer)
695   {
696      createFileHeader() ;
697   }
698
699   //! Client side: Send a message to do some post processing on server
700   void CContext::sendPostProcessing()
701   {
702     if (!hasServer)
703     {
704       CEventClient event(getType(),EVENT_ID_POST_PROCESS) ;
705       if (client->isServerLeader())
706       {
707         CMessage msg ;
708         msg<<this->getIdServer();
709         event.push(client->getServerLeader(),1,msg) ;
710         client->sendEvent(event) ;
711       }
712       else client->sendEvent(event) ;
713     }
714   }
715
716   //! Server side: Receive a message to do some post processing
717   void CContext::recvPostProcessing(CEventServer& event)
718   {
719      CBufferIn* buffer=event.subEvents.begin()->buffer;
720      string id;
721      *buffer>>id;
722      get(id)->recvPostProcessing(*buffer);
723   }
724
725   //! Server side: Receive a message to do some post processing
726   void CContext::recvPostProcessing(CBufferIn& buffer)
727   {
728      postProcessing();
729//      std::cout << "server context " << *this << std::endl;
730   }
731
732   const StdString& CContext::getIdServer()
733   {
734      if (hasClient)
735      {
736        idServer_ = this->getId();
737        idServer_ += "_server";
738        return idServer_;
739      }
740      if (hasServer) return (this->getId());
741   }
742
743   /*!
744   \brief Do some simple post processings after parsing xml file
745      After the xml file (iodef.xml) is parsed, it is necessary to build all relations among
746   created object, e.g: inhertance among fields, domain, axis. After that, all fiels as well as their parents (reference fields),
747   which will be written out into netcdf files, are processed
748   */
749   void CContext::postProcessing()
750   {
751     if (isPostProcessed) return;
752
753     // Solve calendar for both side: client and server
754      this->solveCalendar();
755
756      // Find all inheritance in xml structure
757      this->solveAllInheritance();
758
759      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
760      this->findEnabledFiles();
761
762      // Find all enabled fields of each file
763      this->findAllEnabledFields();
764
765      // Search and rebuild all reference object of enabled fields
766      this->solveAllRefOfEnabledFields(false);
767      isPostProcessed = true;
768   }
769
770   std::map<int, StdSize>& CContext::getDataSize()
771   {
772     std::set<StdString> domainIds;
773
774     // Find all reference domain and axis of all active fields
775     int numEnabledFiles = this->enabledFiles.size();
776     for (int i = 0; i < numEnabledFiles; ++i)
777     {
778       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
779       int numEnabledFields = enabledFields.size();
780       for (int j = 0; j < numEnabledFields; ++j)
781       {
782         const std::pair<StdString, StdString>& prDomAxisId = enabledFields[j]->getDomainAxisIds();
783         const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataSize();
784         if (dataSize_.empty())
785         {
786           dataSize_ = mapSize;
787           domainIds.insert(prDomAxisId.first);
788         }
789         else
790         {
791           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
792           if (domainIds.find(prDomAxisId.first) == domainIds.end())
793           {
794             for (; it != itE; ++it)
795             {
796               if (0 < dataSize_.count(it->first)) dataSize_[it->first] += it->second;
797               else dataSize_.insert(make_pair(it->first, it->second));
798             }
799           } else
800           {
801             for (; it != itE; ++it)
802             {
803               if (0 < dataSize_.count(it->first))
804                if (CXios::isOptPerformance) dataSize_[it->first] += it->second;
805                else
806                {
807                  if (dataSize_[it->first] < it->second) dataSize_[it->first] = it->second;
808                }
809               else dataSize_.insert(make_pair(it->first, it->second));
810             }
811           }
812         }
813       }
814     }
815
816     return dataSize_;
817   }
818
819   //! Client side: Send infomation of active files (files are enabled to write out)
820   void CContext::sendEnabledFiles()
821   {
822     int size = this->enabledFiles.size();
823
824     // In a context, each type has a root definition, e.g: axis, domain, field.
825     // Every object must be a child of one of these root definition. In this case
826     // all new file objects created on server must be children of the root "file_definition"
827     StdString fileDefRoot("file_definition");
828     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
829
830     for (int i = 0; i < size; ++i)
831     {
832       cfgrpPtr->sendCreateChild(this->enabledFiles[i]->getId());
833       this->enabledFiles[i]->sendAllAttributesToServer();
834       this->enabledFiles[i]->sendAddAllVariables();
835     }
836   }
837
838   //! Client side: Send information of active fields (ones are written onto files)
839   void CContext::sendEnabledFields()
840   {
841     int size = this->enabledFiles.size();
842     for (int i = 0; i < size; ++i)
843     {
844       this->enabledFiles[i]->sendEnabledFields();
845     }
846   }
847
848   //! Client side: Send information of reference grid of active fields
849   void CContext::sendRefGrid()
850   {
851     std::set<StdString> gridIds;
852     int sizeFile = this->enabledFiles.size();
853     CFile* filePtr(NULL);
854
855     // Firstly, find all reference grids of all active fields
856     for (int i = 0; i < sizeFile; ++i)
857     {
858       filePtr = this->enabledFiles[i];
859       std::vector<CField*> enabledFields = filePtr->getEnabledFields();
860       int sizeField = enabledFields.size();
861       for (int numField = 0; numField < sizeField; ++numField)
862       {
863         if (0 != enabledFields[numField]->getRelGrid())
864           gridIds.insert(CGrid::get(enabledFields[numField]->getRelGrid())->getId());
865       }
866     }
867
868     // Create all reference grids on server side
869     StdString gridDefRoot("grid_definition");
870     CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
871     std::set<StdString>::const_iterator it, itE = gridIds.end();
872     for (it = gridIds.begin(); it != itE; ++it)
873     {
874       gridPtr->sendCreateChild(*it);
875       CGrid::get(*it)->sendAllAttributesToServer();
876       CGrid::get(*it)->sendAllDomains();
877       CGrid::get(*it)->sendAllAxis();
878     }
879   }
880
881
882   //! Client side: Send information of reference domain and axis of active fields
883   void CContext::sendRefDomainsAxis()
884   {
885     std::set<StdString> domainIds;
886     std::set<StdString> axisIds;
887
888     // Find all reference domain and axis of all active fields
889     int numEnabledFiles = this->enabledFiles.size();
890     for (int i = 0; i < numEnabledFiles; ++i)
891     {
892       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
893       int numEnabledFields = enabledFields.size();
894       for (int j = 0; j < numEnabledFields; ++j)
895       {
896         const std::pair<StdString, StdString>& prDomAxisId = enabledFields[j]->getDomainAxisIds();
897         domainIds.insert(prDomAxisId.first);
898         axisIds.insert(prDomAxisId.second);
899       }
900     }
901
902     // Create all reference axis on server side
903     std::set<StdString>::iterator itDom, itAxis;
904     std::set<StdString>::const_iterator itE;
905
906     StdString axiDefRoot("axis_definition");
907     CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
908     itE = axisIds.end();
909     for (itAxis = axisIds.begin(); itAxis != itE; ++itAxis)
910     {
911       if (!itAxis->empty())
912       {
913         axisPtr->sendCreateChild(*itAxis);
914         CAxis::get(*itAxis)->sendAllAttributesToServer();
915       }
916     }
917
918     // Create all reference domains on server side
919     StdString domDefRoot("domain_definition");
920     CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
921     itE = domainIds.end();
922     for (itDom = domainIds.begin(); itDom != itE; ++itDom)
923     {
924       if (!itDom->empty()) {
925          domPtr->sendCreateChild(*itDom);
926          CDomain::get(*itDom)->sendAllAttributesToServer();
927       }
928     }
929   }
930
931   //! Update calendar in each time step
932   void CContext::updateCalendar(int step)
933   {
934      info(50)<<"updateCalendar : before : "<<calendar->getCurrentDate()<<endl ;
935      calendar->update(step) ;
936      info(50)<<"updateCalendar : after : "<<calendar->getCurrentDate()<<endl ;
937   }
938
939   //! Server side: Create header of netcdf file
940   void CContext::createFileHeader(void )
941   {
942      vector<CFile*>::const_iterator it ;
943
944      for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
945      {
946         (*it)->initFile();
947      }
948   }
949
950   //! Get current context
951   CContext* CContext::getCurrent(void)
952   {
953     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get() ;
954   }
955
956   /*!
957   \brief Set context with an id be the current context
958   \param [in] id identity of context to be set to current
959   */
960   void CContext::setCurrent(const string& id)
961   {
962     CObjectFactory::SetCurrentContextId(id);
963     CGroupFactory::SetCurrentContextId(id);
964   }
965
966  /*!
967  \brief Create a context with specific id
968  \param [in] id identity of new context
969  \return pointer to the new context or already-existed one with identity id
970  */
971  CContext* CContext::create(const StdString& id)
972  {
973    CContext::setCurrent(id) ;
974
975    bool hasctxt = CContext::has(id);
976    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
977    getRoot() ;
978    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
979
980#define DECLARE_NODE(Name_, name_) \
981    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
982#define DECLARE_NODE_PAR(Name_, name_)
983#include "node_type.conf"
984
985    return (context);
986  }
987} // namespace xios
Note: See TracBrowser for help on using the repository browser.