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

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

Start using the filter infrastructure to read and write fields.

Note that currently only the simple cases are working. References and all types of operations are disabled.

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