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

Last change on this file since 639 was 639, checked in by rlacroix, 6 years ago

Add a basic garbage collector to ensure no packets linger in the filter graph.

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