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

Last change on this file since 585 was 584, checked in by mhnguyen, 9 years ago

Implementing new hash algorithm and fixing bug related to zoom

+) Replace boost hash with hash algorithm of Jenkins
+) Domain, if an attribute is non-empty for one client, it should also be non-empty for others inspite of zoom
+) Replace the way to find the number of client connecting to a server to make sure every server receive a message

Test
+) On Curie
+) test_client: passed and results are same like before
+) test_complete: passed, results are partially the same, the different part comes from added working operation

  • 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: 27.0 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   }
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    }
353
354
355    // Nettoyage de l'arborescence
356    if (hasClient && !hasServer) CleanTree(); // Only on client side??
357
358    if (hasClient) sendCreateFileHeader();
359   }
360
361   void CContext::findAllEnabledFields(void)
362   {
363     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
364     (void)this->enabledFiles[i]->getEnabledFields();
365   }
366
367   void CContext::solveAllRefOfEnabledFields(bool sendToServer)
368   {
369     int size = this->enabledFiles.size();
370     for (int i = 0; i < size; ++i)
371     {
372       this->enabledFiles[i]->solveAllRefOfEnabledFields(sendToServer);
373     }
374   }
375
376   void CContext::buildAllExpressionOfEnabledFields()
377   {
378     int size = this->enabledFiles.size();
379     for (int i = 0; i < size; ++i)
380     {
381       this->enabledFiles[i]->buildAllExpressionOfEnabledFields();
382     }
383   }
384
385   void CContext::solveAllInheritance(bool apply)
386   {
387     // Résolution des héritages descendants (càd des héritages de groupes)
388     // pour chacun des contextes.
389      solveDescInheritance(apply);
390
391     // Résolution des héritages par référence au niveau des fichiers.
392      const vector<CFile*> allFiles=CFile::getAll();
393      const vector<CGrid*> allGrids= CGrid::getAll();
394
395     //if (hasClient && !hasServer)
396      if (hasClient)
397      {
398        for (unsigned int i = 0; i < allFiles.size(); i++)
399          allFiles[i]->solveFieldRefInheritance(apply);
400      }
401
402      unsigned int vecSize = allGrids.size();
403      unsigned int i = 0;
404      for (i = 0; i < vecSize; ++i)
405        allGrids[i]->solveDomainAxisRefInheritance(apply);
406
407   }
408
409   void CContext::findEnabledFiles(void)
410   {
411      const std::vector<CFile*> allFiles = CFile::getAll();
412
413      for (unsigned int i = 0; i < allFiles.size(); i++)
414         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
415         {
416            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
417               enabledFiles.push_back(allFiles[i]);
418         }
419         else enabledFiles.push_back(allFiles[i]); // otherwise true by default
420
421
422      if (enabledFiles.size() == 0)
423         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
424               << getId() << "\" !");
425   }
426
427   void CContext::closeAllFile(void)
428   {
429     std::vector<CFile*>::const_iterator
430            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
431
432     for (; it != end; it++)
433     {
434       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
435       (*it)->close();
436     }
437   }
438
439   /*!
440   \brief Dispatch event received from client
441      Whenever a message is received in buffer of server, it will be processed depending on
442   its event type. A new event type should be added in the switch list to make sure
443   it processed on server side.
444   \param [in] event: Received message
445   */
446   bool CContext::dispatchEvent(CEventServer& event)
447   {
448
449      if (SuperClass::dispatchEvent(event)) return true;
450      else
451      {
452        switch(event.type)
453        {
454           case EVENT_ID_CLOSE_DEFINITION :
455             recvCloseDefinition(event);
456             return true;
457             break;
458           case EVENT_ID_UPDATE_CALENDAR:
459             recvUpdateCalendar(event);
460             return true;
461             break;
462           case EVENT_ID_CREATE_FILE_HEADER :
463             recvCreateFileHeader(event);
464             return true;
465             break;
466           case EVENT_ID_POST_PROCESS:
467             recvPostProcessing(event);
468             return true;
469             break;
470
471           default :
472             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
473                    <<"Unknown Event");
474           return false;
475         }
476      }
477   }
478
479   //! Client side: Send a message to server to make it close
480   void CContext::sendCloseDefinition(void)
481   {
482     CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
483     if (client->isServerLeader())
484     {
485       CMessage msg;
486       msg<<this->getIdServer();
487       event.push(client->getServerLeader(),1,msg);
488       client->sendEvent(event);
489     }
490     else client->sendEvent(event);
491   }
492
493   //! Server side: Receive a message of client announcing a context close
494   void CContext::recvCloseDefinition(CEventServer& event)
495   {
496
497      CBufferIn* buffer=event.subEvents.begin()->buffer;
498      string id;
499      *buffer>>id;
500      get(id)->closeDefinition();
501   }
502
503   //! Client side: Send a message to update calendar in each time step
504   void CContext::sendUpdateCalendar(int step)
505   {
506     if (!hasServer)
507     {
508       CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR);
509       if (client->isServerLeader())
510       {
511         CMessage msg;
512         msg<<this->getIdServer()<<step;
513         event.push(client->getServerLeader(),1,msg);
514         client->sendEvent(event);
515       }
516       else client->sendEvent(event);
517     }
518   }
519
520   //! Server side: Receive a message of client annoucing calendar update
521   void CContext::recvUpdateCalendar(CEventServer& event)
522   {
523
524      CBufferIn* buffer=event.subEvents.begin()->buffer;
525      string id;
526      *buffer>>id;
527      get(id)->recvUpdateCalendar(*buffer);
528   }
529
530   //! Server side: Receive a message of client annoucing calendar update
531   void CContext::recvUpdateCalendar(CBufferIn& buffer)
532   {
533      int step;
534      buffer>>step;
535      updateCalendar(step);
536   }
537
538   //! Client side: Send a message to create header part of netcdf file
539   void CContext::sendCreateFileHeader(void)
540   {
541     CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER);
542     if (client->isServerLeader())
543     {
544       CMessage msg;
545       msg<<this->getIdServer();
546       event.push(client->getServerLeader(),1,msg);
547       client->sendEvent(event);
548     }
549     else client->sendEvent(event);
550   }
551
552   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
553   void CContext::recvCreateFileHeader(CEventServer& event)
554   {
555      CBufferIn* buffer=event.subEvents.begin()->buffer;
556      string id;
557      *buffer>>id;
558      get(id)->recvCreateFileHeader(*buffer);
559   }
560
561   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
562   void CContext::recvCreateFileHeader(CBufferIn& buffer)
563   {
564      createFileHeader();
565   }
566
567   //! Client side: Send a message to do some post processing on server
568   void CContext::sendPostProcessing()
569   {
570     if (!hasServer)
571     {
572       CEventClient event(getType(),EVENT_ID_POST_PROCESS);
573       if (client->isServerLeader())
574       {
575         CMessage msg;
576         msg<<this->getIdServer();
577         event.push(client->getServerLeader(),1,msg);
578         client->sendEvent(event);
579       }
580       else client->sendEvent(event);
581     }
582   }
583
584   //! Server side: Receive a message to do some post processing
585   void CContext::recvPostProcessing(CEventServer& event)
586   {
587      CBufferIn* buffer=event.subEvents.begin()->buffer;
588      string id;
589      *buffer>>id;
590      get(id)->recvPostProcessing(*buffer);
591   }
592
593   //! Server side: Receive a message to do some post processing
594   void CContext::recvPostProcessing(CBufferIn& buffer)
595   {
596      CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar();
597      postProcessing();
598   }
599
600   const StdString& CContext::getIdServer()
601   {
602      if (hasClient)
603      {
604        idServer_ = this->getId();
605        idServer_ += "_server";
606        return idServer_;
607      }
608      if (hasServer) return (this->getId());
609   }
610
611   /*!
612   \brief Do some simple post processings after parsing xml file
613      After the xml file (iodef.xml) is parsed, it is necessary to build all relations among
614   created object, e.g: inhertance among fields, domain, axis. After that, all fiels as well as their parents (reference fields),
615   which will be written out into netcdf files, are processed
616   */
617   void CContext::postProcessing()
618   {
619     if (isPostProcessed) return;
620
621      // Make sure the calendar was correctly created
622      if (!calendar)
623        ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"")
624      else if (calendar->getTimeStep() == NoneDu)
625        ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"")
626      // Calendar first update to set the current date equals to the start date
627      calendar->update(0);
628
629      // Find all inheritance in xml structure
630      this->solveAllInheritance();
631
632      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
633      this->findEnabledFiles();
634
635      // Find all enabled fields of each file
636      this->findAllEnabledFields();
637
638      // Search and rebuild all reference object of enabled fields
639      this->solveAllRefOfEnabledFields(false);
640      isPostProcessed = true;
641   }
642
643   std::map<int, StdSize>& CContext::getDataSize()
644   {
645     // Set of grid used by enabled fields
646     std::set<StdString> usedGrid;
647
648     // Find all reference domain and axis of all active fields
649     int numEnabledFiles = this->enabledFiles.size();
650     for (int i = 0; i < numEnabledFiles; ++i)
651     {
652       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
653       int numEnabledFields = enabledFields.size();
654       for (int j = 0; j < numEnabledFields; ++j)
655       {
656//         const std::pair<StdString, StdString>& prDomAxisId = enabledFields[j]->getDomainAxisIds();
657         StdString currentGrid = enabledFields[j]->grid->getId();
658         const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataSize();
659         if (dataSize_.empty())
660         {
661           dataSize_ = mapSize;
662           usedGrid.insert(currentGrid);
663//           domainIds.insert(prDomAxisId.first);
664         }
665         else
666         {
667           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
668           if (usedGrid.find(currentGrid) == usedGrid.end())
669           {
670             for (; it != itE; ++it)
671             {
672               if (0 < dataSize_.count(it->first)) dataSize_[it->first] += it->second;
673               else dataSize_.insert(make_pair(it->first, it->second));
674             }
675           } else
676           {
677             for (; it != itE; ++it)
678             {
679               if (0 < dataSize_.count(it->first))
680                if (CXios::isOptPerformance) dataSize_[it->first] += it->second;
681                else
682                {
683                  if (dataSize_[it->first] < it->second) dataSize_[it->first] = it->second;
684                }
685               else dataSize_.insert(make_pair(it->first, it->second));
686             }
687           }
688         }
689       }
690     }
691
692     return dataSize_;
693   }
694
695   //! Client side: Send infomation of active files (files are enabled to write out)
696   void CContext::sendEnabledFiles()
697   {
698     int size = this->enabledFiles.size();
699
700     // In a context, each type has a root definition, e.g: axis, domain, field.
701     // Every object must be a child of one of these root definition. In this case
702     // all new file objects created on server must be children of the root "file_definition"
703     StdString fileDefRoot("file_definition");
704     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
705
706     for (int i = 0; i < size; ++i)
707     {
708       cfgrpPtr->sendCreateChild(this->enabledFiles[i]->getId());
709       this->enabledFiles[i]->sendAllAttributesToServer();
710       this->enabledFiles[i]->sendAddAllVariables();
711     }
712   }
713
714   //! Client side: Send information of active fields (ones are written onto files)
715   void CContext::sendEnabledFields()
716   {
717     int size = this->enabledFiles.size();
718     for (int i = 0; i < size; ++i)
719     {
720       this->enabledFiles[i]->sendEnabledFields();
721     }
722   }
723
724   //! Client side: Send information of reference grid of active fields
725   void CContext::sendRefGrid()
726   {
727     std::set<StdString> gridIds;
728     int sizeFile = this->enabledFiles.size();
729     CFile* filePtr(NULL);
730
731     // Firstly, find all reference grids of all active fields
732     for (int i = 0; i < sizeFile; ++i)
733     {
734       filePtr = this->enabledFiles[i];
735       std::vector<CField*> enabledFields = filePtr->getEnabledFields();
736       int sizeField = enabledFields.size();
737       for (int numField = 0; numField < sizeField; ++numField)
738       {
739         if (0 != enabledFields[numField]->getRelGrid())
740           gridIds.insert(CGrid::get(enabledFields[numField]->getRelGrid())->getId());
741       }
742     }
743
744     // Create all reference grids on server side
745     StdString gridDefRoot("grid_definition");
746     CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
747     std::set<StdString>::const_iterator it, itE = gridIds.end();
748     for (it = gridIds.begin(); it != itE; ++it)
749     {
750       gridPtr->sendCreateChild(*it);
751       CGrid::get(*it)->sendAllAttributesToServer();
752       CGrid::get(*it)->sendAllDomains();
753       CGrid::get(*it)->sendAllAxis();
754     }
755   }
756
757
758   //! Client side: Send information of reference domain and axis of active fields
759   void CContext::sendRefDomainsAxis()
760   {
761     std::set<StdString> domainIds;
762     std::set<StdString> axisIds;
763
764     // Find all reference domain and axis of all active fields
765     int numEnabledFiles = this->enabledFiles.size();
766     for (int i = 0; i < numEnabledFiles; ++i)
767     {
768       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
769       int numEnabledFields = enabledFields.size();
770       for (int j = 0; j < numEnabledFields; ++j)
771       {
772         const std::pair<StdString, StdString>& prDomAxisId = enabledFields[j]->getRefDomainAxisIds();
773         domainIds.insert(prDomAxisId.first);
774         axisIds.insert(prDomAxisId.second);
775       }
776     }
777
778     // Create all reference axis on server side
779     std::set<StdString>::iterator itDom, itAxis;
780     std::set<StdString>::const_iterator itE;
781
782     StdString axiDefRoot("axis_definition");
783     CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
784     itE = axisIds.end();
785     for (itAxis = axisIds.begin(); itAxis != itE; ++itAxis)
786     {
787       if (!itAxis->empty())
788       {
789         axisPtr->sendCreateChild(*itAxis);
790         CAxis::get(*itAxis)->sendAllAttributesToServer();
791       }
792     }
793
794     // Create all reference domains on server side
795     StdString domDefRoot("domain_definition");
796     CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
797     itE = domainIds.end();
798     for (itDom = domainIds.begin(); itDom != itE; ++itDom)
799     {
800       if (!itDom->empty()) {
801          domPtr->sendCreateChild(*itDom);
802          CDomain::get(*itDom)->sendAllAttributesToServer();
803       }
804     }
805   }
806
807   //! Update calendar in each time step
808   void CContext::updateCalendar(int step)
809   {
810      info(50)<<"updateCalendar : before : "<<calendar->getCurrentDate()<<endl;
811      calendar->update(step);
812      info(50)<<"updateCalendar : after : "<<calendar->getCurrentDate()<<endl;
813   }
814
815   //! Server side: Create header of netcdf file
816   void CContext::createFileHeader(void )
817   {
818      vector<CFile*>::const_iterator it;
819
820      for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
821      {
822         (*it)->initFile();
823      }
824   }
825
826   //! Get current context
827   CContext* CContext::getCurrent(void)
828   {
829     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get();
830   }
831
832   /*!
833   \brief Set context with an id be the current context
834   \param [in] id identity of context to be set to current
835   */
836   void CContext::setCurrent(const string& id)
837   {
838     CObjectFactory::SetCurrentContextId(id);
839     CGroupFactory::SetCurrentContextId(id);
840   }
841
842  /*!
843  \brief Create a context with specific id
844  \param [in] id identity of new context
845  \return pointer to the new context or already-existed one with identity id
846  */
847  CContext* CContext::create(const StdString& id)
848  {
849    CContext::setCurrent(id);
850
851    bool hasctxt = CContext::has(id);
852    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
853    getRoot();
854    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
855
856#define DECLARE_NODE(Name_, name_) \
857    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
858#define DECLARE_NODE_PAR(Name_, name_)
859#include "node_type.conf"
860
861    return (context);
862  }
863} // namespace xios
Note: See TracBrowser for help on using the repository browser.