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

Last change on this file since 593 was 593, checked in by rlacroix, 7 years ago

Add a new interface xios_recv_field to get local instant data from a field.

  • 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.1 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 "xios_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   }
76
77   //----------------------------------------------------------------
78   /*!
79   \brief Parse xml file and write information into context object
80   \param [in] node xmld node corresponding in xml file
81   */
82   void CContext::parse(xml::CXMLNode & node)
83   {
84      CContext::SuperClass::parse(node);
85
86      // PARSING POUR GESTION DES ENFANTS
87      xml::THashAttributes attributes = node.getAttributes();
88
89      if (attributes.end() != attributes.find("src"))
90      {
91         StdIFStream ifs ( attributes["src"].c_str() , StdIFStream::in );
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" );
95         if (!ifs.good())
96            ERROR("CContext::parse(xml::CXMLNode & node)",
97                  << "[ filename = " << attributes["src"] << " ] Bad xml stream !");
98         xml::CXMLParser::ParseInclude(ifs, attributes["src"], *this);
99      }
100
101      if (node.getElementName().compare(CContext::GetName()))
102         DEBUG("Le noeud is wrong defined but will be considered as a context !");
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"))
117            {
118              DEBUG(<< "Definition node has an id,"
119                    << "it will not be taking account !");
120            }
121
122#define DECLARE_NODE(Name_, name_)    \
123   if (name.compare(C##Name_##Definition::GetDefName()) == 0) \
124   { C##Name_##Definition::create(C##Name_##Definition::GetDefName()) -> parse(node); continue; }
125#define DECLARE_NODE_PAR(Name_, name_)
126#include "node_type.conf"
127
128            DEBUG(<< "The element \'"     << name
129                  << "\' in the context \'" << CContext::getCurrent()->getId()
130                  << "\' is not a definition !");
131
132         } while (node.goToNextElement());
133
134         node.goToParentElement(); // Retour au parent
135      }
136   }
137
138   //----------------------------------------------------------------
139   //! Show tree structure of context
140   void CContext::ShowTree(StdOStream & out)
141   {
142      StdString currentContextId = CContext::getCurrent() -> getId();
143      std::vector<CContext*> def_vector =
144         CContext::getRoot()->getChildList();
145      std::vector<CContext*>::iterator
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;
150
151      for (; it != end; it++)
152      {
153         CContext* context = *it;
154         CContext::setCurrent(context->getId());
155         out << *context << std::endl;
156      }
157
158      out << "</" << xml::CXMLNode::GetRootName() << " >" << std::endl;
159      CContext::setCurrent(currentContextId);
160   }
161
162
163   //----------------------------------------------------------------
164
165   //! Convert context object into string (to print)
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_)    \
180   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
181   oss << * C##Name_##Definition::get(C##Name_##Definition::GetDefName()) << std::endl;
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
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   */
200   void CContext::solveDescInheritance(bool apply, const CAttributeMap * const UNUSED(parent))
201   {
202#define DECLARE_NODE(Name_, name_)    \
203   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
204     C##Name_##Definition::get(C##Name_##Definition::GetDefName())->solveDescInheritance(apply);
205#define DECLARE_NODE_PAR(Name_, name_)
206#include "node_type.conf"
207   }
208
209   //----------------------------------------------------------------
210
211   //! Verify if all root definition in the context have child.
212   bool CContext::hasChild(void) const
213   {
214      return (
215#define DECLARE_NODE(Name_, name_)    \
216   C##Name_##Definition::has(C##Name_##Definition::GetDefName())   ||
217#define DECLARE_NODE_PAR(Name_, name_)
218#include "node_type.conf"
219      false);
220}
221
222   //----------------------------------------------------------------
223
224   void CContext::CleanTree(void)
225   {
226#define DECLARE_NODE(Name_, name_) C##Name_##Definition::ClearAllAttributes();
227#define DECLARE_NODE_PAR(Name_, name_)
228#include "node_type.conf"
229   }
230   ///---------------------------------------------------------------
231
232   //! Initialize client side
233   void CContext::initClient(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtServer)
234   {
235     hasClient=true;
236     client = new CContextClient(this,intraComm, interComm, cxtServer);
237   }
238
239   void CContext::setClientServerBuffer()
240   {
241     if (hasClient)
242     {
243       size_t bufferSizeMin = 10*sizeof(size_t)*1024;
244#define DECLARE_NODE(Name_, name_)    \
245   bufferSizeMin = (bufferSizeMin < sizeof(C##Name_##Definition)) ?  sizeof(C##Name_##Definition) : bufferSizeMin;
246#define DECLARE_NODE_PAR(Name_, name_)
247#include "node_type.conf"
248       std::map<int, StdSize> bufferSize = getDataSize();
249       if (bufferSize.empty())
250       {
251         if (client->isServerLeader())
252         {
253           bufferSize[client->getServerLeader()] = bufferSizeMin;
254         }
255         else
256          return;
257       }
258
259       std::map<int, StdSize>::iterator  it = bufferSize.begin(),
260                                        ite = bufferSize.end();
261       for (; it != ite; ++it)
262       it->second = (it->second < bufferSizeMin) ? bufferSizeMin : it->second;
263       client->setBufferSize(bufferSize);
264     }
265   }
266
267   //! Verify whether a context is initialized
268   bool CContext::isInitialized(void)
269   {
270     return hasClient;
271   }
272
273   //! Initialize server
274   void CContext::initServer(MPI_Comm intraComm,MPI_Comm interComm)
275   {
276     hasServer=true;
277     server = new CContextServer(this,intraComm,interComm);
278   }
279
280   //! Server side: Put server into a loop in order to listen message from client
281   bool CContext::eventLoop(void)
282   {
283     return server->eventLoop();
284   }
285
286   //! Terminate a context
287   void CContext::finalize(void)
288   {
289      if (hasClient && !hasServer)
290      {
291         client->finalize();
292      }
293      if (hasServer)
294      {
295        closeAllFile();
296      }
297   }
298
299   /*!
300   \brief Close all the context defintion and do processing data
301      After everything is well defined on client side, they will be processed and sent to server
302   From the version 2.0, sever and client work no more on the same database. Moreover, client(s) will send
303   all necessary information to server, from which each server can build its own database.
304   Because the role of server is to write out field data on a specific netcdf file,
305   the only information that it needs is the enabled files
306   and the active fields (fields will be written onto active files)
307   */
308   void CContext::closeDefinition(void)
309   {
310     // There is nothing client need to send to server
311     if (hasClient)
312     {
313       // After xml is parsed, there are some more works with post processing
314       postProcessing();
315
316       setClientServerBuffer();
317     }
318
319     if (hasClient && !hasServer)
320     {
321      // Send all attributes of current context to server
322      this->sendAllAttributesToServer();
323
324      // Send all attributes of current calendar
325      CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer();
326
327      // We have enough information to send to server
328      // First of all, send all enabled files
329       sendEnabledFiles();
330
331      // Then, send all enabled fields
332       sendEnabledFields();
333
334      // At last, we have all info of domain and axis, then send them
335       sendRefDomainsAxis();
336
337      // After that, send all grid (if any)
338       sendRefGrid();
339    }
340
341    // Now tell server that it can process all messages from client
342    if (hasClient && !hasServer) this->sendCloseDefinition();
343
344    // We have a xml tree on the server side and now, it should be also processed
345    if (hasClient && !hasServer) sendPostProcessing();
346
347    // There are some processings that should be done after all of above. For example: check mask or index
348    if (hasClient)
349    {
350      this->solveAllRefOfEnabledFields(true);
351      this->buildAllExpressionOfEnabledFields();
352      buildAllExpressionOfFieldsWithReadAccess();
353    }
354
355
356    // Nettoyage de l'arborescence
357    if (hasClient && !hasServer) CleanTree(); // Only on client side??
358
359    if (hasClient) sendCreateFileHeader();
360   }
361
362   void CContext::findAllEnabledFields(void)
363   {
364     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
365     (void)this->enabledFiles[i]->getEnabledFields();
366   }
367
368   void CContext::solveAllRefOfEnabledFields(bool sendToServer)
369   {
370     int size = this->enabledFiles.size();
371     for (int i = 0; i < size; ++i)
372     {
373       this->enabledFiles[i]->solveAllRefOfEnabledFields(sendToServer);
374     }
375   }
376
377   void CContext::buildAllExpressionOfEnabledFields()
378   {
379     int size = this->enabledFiles.size();
380     for (int i = 0; i < size; ++i)
381     {
382       this->enabledFiles[i]->buildAllExpressionOfEnabledFields();
383     }
384   }
385
386  void CContext::findFieldsWithReadAccess(void)
387  {
388    fieldsWithReadAccess.clear();
389    const vector<CField*> allFields = CField::getAll();
390    for (size_t i = 0; i < allFields.size(); ++i)
391    {
392      if (!allFields[i]->read_access.isEmpty() && allFields[i]->read_access.getValue())
393        fieldsWithReadAccess.push_back(allFields[i]);
394    }
395  }
396
397  void CContext::solveAllRefOfFieldsWithReadAccess()
398  {
399    for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
400    {
401      fieldsWithReadAccess[i]->solveAllReferenceEnabledField(false);
402      // Ensure that the instant data will be properly saved
403      fieldsWithReadAccess[i]->getInstantData();
404    }
405  }
406
407  void CContext::buildAllExpressionOfFieldsWithReadAccess()
408  {
409    for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
410      fieldsWithReadAccess[i]->buildAllExpressionEnabledField();
411  }
412
413   void CContext::solveAllInheritance(bool apply)
414   {
415     // Résolution des héritages descendants (càd des héritages de groupes)
416     // pour chacun des contextes.
417      solveDescInheritance(apply);
418
419     // Résolution des héritages par référence au niveau des fichiers.
420      const vector<CFile*> allFiles=CFile::getAll();
421      const vector<CGrid*> allGrids= CGrid::getAll();
422
423     //if (hasClient && !hasServer)
424      if (hasClient)
425      {
426        for (unsigned int i = 0; i < allFiles.size(); i++)
427          allFiles[i]->solveFieldRefInheritance(apply);
428      }
429
430      unsigned int vecSize = allGrids.size();
431      unsigned int i = 0;
432      for (i = 0; i < vecSize; ++i)
433        allGrids[i]->solveDomainAxisRefInheritance(apply);
434
435   }
436
437   void CContext::findEnabledFiles(void)
438   {
439      const std::vector<CFile*> allFiles = CFile::getAll();
440
441      for (unsigned int i = 0; i < allFiles.size(); i++)
442         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
443         {
444            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
445               enabledFiles.push_back(allFiles[i]);
446         }
447         else enabledFiles.push_back(allFiles[i]); // otherwise true by default
448
449
450      if (enabledFiles.size() == 0)
451         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
452               << getId() << "\" !");
453   }
454
455   void CContext::closeAllFile(void)
456   {
457     std::vector<CFile*>::const_iterator
458            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
459
460     for (; it != end; it++)
461     {
462       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
463       (*it)->close();
464     }
465   }
466
467   /*!
468   \brief Dispatch event received from client
469      Whenever a message is received in buffer of server, it will be processed depending on
470   its event type. A new event type should be added in the switch list to make sure
471   it processed on server side.
472   \param [in] event: Received message
473   */
474   bool CContext::dispatchEvent(CEventServer& event)
475   {
476
477      if (SuperClass::dispatchEvent(event)) return true;
478      else
479      {
480        switch(event.type)
481        {
482           case EVENT_ID_CLOSE_DEFINITION :
483             recvCloseDefinition(event);
484             return true;
485             break;
486           case EVENT_ID_UPDATE_CALENDAR:
487             recvUpdateCalendar(event);
488             return true;
489             break;
490           case EVENT_ID_CREATE_FILE_HEADER :
491             recvCreateFileHeader(event);
492             return true;
493             break;
494           case EVENT_ID_POST_PROCESS:
495             recvPostProcessing(event);
496             return true;
497             break;
498
499           default :
500             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
501                    <<"Unknown Event");
502           return false;
503         }
504      }
505   }
506
507   //! Client side: Send a message to server to make it close
508   void CContext::sendCloseDefinition(void)
509   {
510     CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
511     if (client->isServerLeader())
512     {
513       CMessage msg;
514       msg<<this->getIdServer();
515       event.push(client->getServerLeader(),1,msg);
516       client->sendEvent(event);
517     }
518     else client->sendEvent(event);
519   }
520
521   //! Server side: Receive a message of client announcing a context close
522   void CContext::recvCloseDefinition(CEventServer& event)
523   {
524
525      CBufferIn* buffer=event.subEvents.begin()->buffer;
526      string id;
527      *buffer>>id;
528      get(id)->closeDefinition();
529   }
530
531   //! Client side: Send a message to update calendar in each time step
532   void CContext::sendUpdateCalendar(int step)
533   {
534     if (!hasServer)
535     {
536       CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR);
537       if (client->isServerLeader())
538       {
539         CMessage msg;
540         msg<<this->getIdServer()<<step;
541         event.push(client->getServerLeader(),1,msg);
542         client->sendEvent(event);
543       }
544       else client->sendEvent(event);
545     }
546   }
547
548   //! Server side: Receive a message of client annoucing calendar update
549   void CContext::recvUpdateCalendar(CEventServer& event)
550   {
551
552      CBufferIn* buffer=event.subEvents.begin()->buffer;
553      string id;
554      *buffer>>id;
555      get(id)->recvUpdateCalendar(*buffer);
556   }
557
558   //! Server side: Receive a message of client annoucing calendar update
559   void CContext::recvUpdateCalendar(CBufferIn& buffer)
560   {
561      int step;
562      buffer>>step;
563      updateCalendar(step);
564   }
565
566   //! Client side: Send a message to create header part of netcdf file
567   void CContext::sendCreateFileHeader(void)
568   {
569     CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER);
570     if (client->isServerLeader())
571     {
572       CMessage msg;
573       msg<<this->getIdServer();
574       event.push(client->getServerLeader(),1,msg);
575       client->sendEvent(event);
576     }
577     else client->sendEvent(event);
578   }
579
580   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
581   void CContext::recvCreateFileHeader(CEventServer& event)
582   {
583      CBufferIn* buffer=event.subEvents.begin()->buffer;
584      string id;
585      *buffer>>id;
586      get(id)->recvCreateFileHeader(*buffer);
587   }
588
589   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
590   void CContext::recvCreateFileHeader(CBufferIn& buffer)
591   {
592      createFileHeader();
593   }
594
595   //! Client side: Send a message to do some post processing on server
596   void CContext::sendPostProcessing()
597   {
598     if (!hasServer)
599     {
600       CEventClient event(getType(),EVENT_ID_POST_PROCESS);
601       if (client->isServerLeader())
602       {
603         CMessage msg;
604         msg<<this->getIdServer();
605         event.push(client->getServerLeader(),1,msg);
606         client->sendEvent(event);
607       }
608       else client->sendEvent(event);
609     }
610   }
611
612   //! Server side: Receive a message to do some post processing
613   void CContext::recvPostProcessing(CEventServer& event)
614   {
615      CBufferIn* buffer=event.subEvents.begin()->buffer;
616      string id;
617      *buffer>>id;
618      get(id)->recvPostProcessing(*buffer);
619   }
620
621   //! Server side: Receive a message to do some post processing
622   void CContext::recvPostProcessing(CBufferIn& buffer)
623   {
624      CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar();
625      postProcessing();
626   }
627
628   const StdString& CContext::getIdServer()
629   {
630      if (hasClient)
631      {
632        idServer_ = this->getId();
633        idServer_ += "_server";
634        return idServer_;
635      }
636      if (hasServer) return (this->getId());
637   }
638
639   /*!
640   \brief Do some simple post processings after parsing xml file
641      After the xml file (iodef.xml) is parsed, it is necessary to build all relations among
642   created object, e.g: inhertance among fields, domain, axis. After that, all fiels as well as their parents (reference fields),
643   which will be written out into netcdf files, are processed
644   */
645   void CContext::postProcessing()
646   {
647     if (isPostProcessed) return;
648
649      // Make sure the calendar was correctly created
650      if (!calendar)
651        ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"")
652      else if (calendar->getTimeStep() == NoneDu)
653        ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"")
654      // Calendar first update to set the current date equals to the start date
655      calendar->update(0);
656
657      // Find all inheritance in xml structure
658      this->solveAllInheritance();
659
660      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
661      this->findEnabledFiles();
662
663      // Find all enabled fields of each file
664      this->findAllEnabledFields();
665
666      // Search and rebuild all reference object of enabled fields
667      this->solveAllRefOfEnabledFields(false);
668
669      // Find all fields with read access from the public API
670      findFieldsWithReadAccess();
671      // and solve the all reference for them
672      solveAllRefOfFieldsWithReadAccess();
673
674      isPostProcessed = true;
675   }
676
677   std::map<int, StdSize>& CContext::getDataSize()
678   {
679     // Set of grid used by enabled fields
680     std::set<StdString> usedGrid;
681
682     // Find all reference domain and axis of all active fields
683     int numEnabledFiles = this->enabledFiles.size();
684     for (int i = 0; i < numEnabledFiles; ++i)
685     {
686       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
687       int numEnabledFields = enabledFields.size();
688       for (int j = 0; j < numEnabledFields; ++j)
689       {
690//         const std::pair<StdString, StdString>& prDomAxisId = enabledFields[j]->getDomainAxisIds();
691         StdString currentGrid = enabledFields[j]->grid->getId();
692         const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataSize();
693         if (dataSize_.empty())
694         {
695           dataSize_ = mapSize;
696           usedGrid.insert(currentGrid);
697//           domainIds.insert(prDomAxisId.first);
698         }
699         else
700         {
701           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
702           if (usedGrid.find(currentGrid) == usedGrid.end())
703           {
704             for (; it != itE; ++it)
705             {
706               if (0 < dataSize_.count(it->first)) dataSize_[it->first] += it->second;
707               else dataSize_.insert(make_pair(it->first, it->second));
708             }
709           } else
710           {
711             for (; it != itE; ++it)
712             {
713               if (0 < dataSize_.count(it->first))
714                if (CXios::isOptPerformance) dataSize_[it->first] += it->second;
715                else
716                {
717                  if (dataSize_[it->first] < it->second) dataSize_[it->first] = it->second;
718                }
719               else dataSize_.insert(make_pair(it->first, it->second));
720             }
721           }
722         }
723       }
724     }
725
726     return dataSize_;
727   }
728
729   //! Client side: Send infomation of active files (files are enabled to write out)
730   void CContext::sendEnabledFiles()
731   {
732     int size = this->enabledFiles.size();
733
734     // In a context, each type has a root definition, e.g: axis, domain, field.
735     // Every object must be a child of one of these root definition. In this case
736     // all new file objects created on server must be children of the root "file_definition"
737     StdString fileDefRoot("file_definition");
738     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
739
740     for (int i = 0; i < size; ++i)
741     {
742       cfgrpPtr->sendCreateChild(this->enabledFiles[i]->getId());
743       this->enabledFiles[i]->sendAllAttributesToServer();
744       this->enabledFiles[i]->sendAddAllVariables();
745     }
746   }
747
748   //! Client side: Send information of active fields (ones are written onto files)
749   void CContext::sendEnabledFields()
750   {
751     int size = this->enabledFiles.size();
752     for (int i = 0; i < size; ++i)
753     {
754       this->enabledFiles[i]->sendEnabledFields();
755     }
756   }
757
758   //! Client side: Send information of reference grid of active fields
759   void CContext::sendRefGrid()
760   {
761     std::set<StdString> gridIds;
762     int sizeFile = this->enabledFiles.size();
763     CFile* filePtr(NULL);
764
765     // Firstly, find all reference grids of all active fields
766     for (int i = 0; i < sizeFile; ++i)
767     {
768       filePtr = this->enabledFiles[i];
769       std::vector<CField*> enabledFields = filePtr->getEnabledFields();
770       int sizeField = enabledFields.size();
771       for (int numField = 0; numField < sizeField; ++numField)
772       {
773         if (0 != enabledFields[numField]->getRelGrid())
774           gridIds.insert(CGrid::get(enabledFields[numField]->getRelGrid())->getId());
775       }
776     }
777
778     // Create all reference grids on server side
779     StdString gridDefRoot("grid_definition");
780     CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
781     std::set<StdString>::const_iterator it, itE = gridIds.end();
782     for (it = gridIds.begin(); it != itE; ++it)
783     {
784       gridPtr->sendCreateChild(*it);
785       CGrid::get(*it)->sendAllAttributesToServer();
786       CGrid::get(*it)->sendAllDomains();
787       CGrid::get(*it)->sendAllAxis();
788     }
789   }
790
791
792   //! Client side: Send information of reference domain and axis of active fields
793   void CContext::sendRefDomainsAxis()
794   {
795     std::set<StdString> domainIds;
796     std::set<StdString> axisIds;
797
798     // Find all reference domain and axis of all active fields
799     int numEnabledFiles = this->enabledFiles.size();
800     for (int i = 0; i < numEnabledFiles; ++i)
801     {
802       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
803       int numEnabledFields = enabledFields.size();
804       for (int j = 0; j < numEnabledFields; ++j)
805       {
806         const std::pair<StdString, StdString>& prDomAxisId = enabledFields[j]->getRefDomainAxisIds();
807         domainIds.insert(prDomAxisId.first);
808         axisIds.insert(prDomAxisId.second);
809       }
810     }
811
812     // Create all reference axis on server side
813     std::set<StdString>::iterator itDom, itAxis;
814     std::set<StdString>::const_iterator itE;
815
816     StdString axiDefRoot("axis_definition");
817     CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
818     itE = axisIds.end();
819     for (itAxis = axisIds.begin(); itAxis != itE; ++itAxis)
820     {
821       if (!itAxis->empty())
822       {
823         axisPtr->sendCreateChild(*itAxis);
824         CAxis::get(*itAxis)->sendAllAttributesToServer();
825       }
826     }
827
828     // Create all reference domains on server side
829     StdString domDefRoot("domain_definition");
830     CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
831     itE = domainIds.end();
832     for (itDom = domainIds.begin(); itDom != itE; ++itDom)
833     {
834       if (!itDom->empty()) {
835          domPtr->sendCreateChild(*itDom);
836          CDomain::get(*itDom)->sendAllAttributesToServer();
837       }
838     }
839   }
840
841   //! Update calendar in each time step
842   void CContext::updateCalendar(int step)
843   {
844      info(50)<<"updateCalendar : before : "<<calendar->getCurrentDate()<<endl;
845      calendar->update(step);
846      info(50)<<"updateCalendar : after : "<<calendar->getCurrentDate()<<endl;
847   }
848
849   //! Server side: Create header of netcdf file
850   void CContext::createFileHeader(void )
851   {
852      vector<CFile*>::const_iterator it;
853
854      for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
855      {
856         (*it)->initFile();
857      }
858   }
859
860   //! Get current context
861   CContext* CContext::getCurrent(void)
862   {
863     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get();
864   }
865
866   /*!
867   \brief Set context with an id be the current context
868   \param [in] id identity of context to be set to current
869   */
870   void CContext::setCurrent(const string& id)
871   {
872     CObjectFactory::SetCurrentContextId(id);
873     CGroupFactory::SetCurrentContextId(id);
874   }
875
876  /*!
877  \brief Create a context with specific id
878  \param [in] id identity of new context
879  \return pointer to the new context or already-existed one with identity id
880  */
881  CContext* CContext::create(const StdString& id)
882  {
883    CContext::setCurrent(id);
884
885    bool hasctxt = CContext::has(id);
886    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
887    getRoot();
888    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
889
890#define DECLARE_NODE(Name_, name_) \
891    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
892#define DECLARE_NODE_PAR(Name_, name_)
893#include "node_type.conf"
894
895    return (context);
896  }
897} // namespace xios
Note: See TracBrowser for help on using the repository browser.