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

Last change on this file since 549 was 549, checked in by rlacroix, 9 years ago

Revised calendar functionalities:

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