source: XIOS/dev/dev_olga/src/node/context.cpp @ 1144

Last change on this file since 1144 was 1144, checked in by mhnguyen, 7 years ago

Cleaning up some redundant codes

  • 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: 52.6 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
17#include "server.hpp"
18
19namespace xios {
20
21  shared_ptr<CContextGroup> CContext::root;
22
23   /// ////////////////////// Définitions ////////////////////// ///
24
25   CContext::CContext(void)
26      : CObjectTemplate<CContext>(), CContextAttributes()
27      , calendar(), hasClient(false), hasServer(false)
28      , isPostProcessed(false), finalized(false)
29      , idServer_(), client(0), server(0)
30      , allProcessed(false), countChildCtx_(0)
31   { /* Ne rien faire de plus */ }
32
33   CContext::CContext(const StdString & id)
34      : CObjectTemplate<CContext>(id), CContextAttributes()
35      , calendar(), hasClient(false), hasServer(false)
36      , isPostProcessed(false), finalized(false)
37      , idServer_(), client(0), server(0)
38      , allProcessed(false), countChildCtx_(0)
39   { /* Ne rien faire de plus */ }
40
41   CContext::~CContext(void)
42   {
43     delete client;
44     delete server;
45     for (std::vector<CContextClient*>::iterator it = clientPrimServer.begin(); it != clientPrimServer.end(); it++)  delete *it;
46     for (std::vector<CContextServer*>::iterator it = serverPrimServer.begin(); it != serverPrimServer.end(); it++)  delete *it;
47
48   }
49
50   //----------------------------------------------------------------
51   //! Get name of context
52   StdString CContext::GetName(void)   { return (StdString("context")); }
53   StdString CContext::GetDefName(void){ return (CContext::GetName()); }
54   ENodeType CContext::GetType(void)   { return (eContext); }
55
56   //----------------------------------------------------------------
57
58   /*!
59   \brief Get context group (context root)
60   \return Context root
61   */
62   CContextGroup* CContext::getRoot(void)
63   {
64      if (root.get()==NULL) root=shared_ptr<CContextGroup>(new CContextGroup(xml::CXMLNode::GetRootName()));
65      return root.get();
66   }
67
68   //----------------------------------------------------------------
69
70   /*!
71   \brief Get calendar of a context
72   \return Calendar
73   */
74   boost::shared_ptr<CCalendar> CContext::getCalendar(void) const
75   {
76      return (this->calendar);
77   }
78
79   //----------------------------------------------------------------
80
81   /*!
82   \brief Set a context with a calendar
83   \param[in] newCalendar new calendar
84   */
85   void CContext::setCalendar(boost::shared_ptr<CCalendar> newCalendar)
86   {
87      this->calendar = newCalendar;
88   }
89
90   //----------------------------------------------------------------
91   /*!
92   \brief Parse xml file and write information into context object
93   \param [in] node xmld node corresponding in xml file
94   */
95   void CContext::parse(xml::CXMLNode & node)
96   {
97      CContext::SuperClass::parse(node);
98
99      // PARSING POUR GESTION DES ENFANTS
100      xml::THashAttributes attributes = node.getAttributes();
101
102      if (attributes.end() != attributes.find("src"))
103      {
104         StdIFStream ifs ( attributes["src"].c_str() , StdIFStream::in );
105         if ( (ifs.rdstate() & std::ifstream::failbit ) != 0 )
106            ERROR("void CContext::parse(xml::CXMLNode & node)",
107                  <<endl<< "Can not open <"<<attributes["src"].c_str()<<"> file" );
108         if (!ifs.good())
109            ERROR("CContext::parse(xml::CXMLNode & node)",
110                  << "[ filename = " << attributes["src"] << " ] Bad xml stream !");
111         xml::CXMLParser::ParseInclude(ifs, attributes["src"], *this);
112      }
113
114      if (node.getElementName().compare(CContext::GetName()))
115         DEBUG("Le noeud is wrong defined but will be considered as a context !");
116
117      if (!(node.goToChildElement()))
118      {
119         DEBUG("Le context ne contient pas d'enfant !");
120      }
121      else
122      {
123         do { // Parcours des contextes pour traitement.
124
125            StdString name = node.getElementName();
126            attributes.clear();
127            attributes = node.getAttributes();
128
129            if (attributes.end() != attributes.find("id"))
130            {
131              DEBUG(<< "Definition node has an id,"
132                    << "it will not be taking account !");
133            }
134
135#define DECLARE_NODE(Name_, name_)    \
136   if (name.compare(C##Name_##Definition::GetDefName()) == 0) \
137   { C##Name_##Definition::create(C##Name_##Definition::GetDefName()) -> parse(node); continue; }
138#define DECLARE_NODE_PAR(Name_, name_)
139#include "node_type.conf"
140
141            DEBUG(<< "The element \'"     << name
142                  << "\' in the context \'" << CContext::getCurrent()->getId()
143                  << "\' is not a definition !");
144
145         } while (node.goToNextElement());
146
147         node.goToParentElement(); // Retour au parent
148      }
149   }
150
151   //----------------------------------------------------------------
152   //! Show tree structure of context
153   void CContext::ShowTree(StdOStream & out)
154   {
155      StdString currentContextId = CContext::getCurrent() -> getId();
156      std::vector<CContext*> def_vector =
157         CContext::getRoot()->getChildList();
158      std::vector<CContext*>::iterator
159         it = def_vector.begin(), end = def_vector.end();
160
161      out << "<? xml version=\"1.0\" ?>" << std::endl;
162      out << "<"  << xml::CXMLNode::GetRootName() << " >" << std::endl;
163
164      for (; it != end; it++)
165      {
166         CContext* context = *it;
167         CContext::setCurrent(context->getId());
168         out << *context << std::endl;
169      }
170
171      out << "</" << xml::CXMLNode::GetRootName() << " >" << std::endl;
172      CContext::setCurrent(currentContextId);
173   }
174
175
176   //----------------------------------------------------------------
177
178   //! Convert context object into string (to print)
179   StdString CContext::toString(void) const
180   {
181      StdOStringStream oss;
182      oss << "<" << CContext::GetName()
183          << " id=\"" << this->getId() << "\" "
184          << SuperClassAttribute::toString() << ">" << std::endl;
185      if (!this->hasChild())
186      {
187         //oss << "<!-- No definition -->" << std::endl; // fait planter l'incrémentation
188      }
189      else
190      {
191
192#define DECLARE_NODE(Name_, name_)    \
193   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
194   oss << * C##Name_##Definition::get(C##Name_##Definition::GetDefName()) << std::endl;
195#define DECLARE_NODE_PAR(Name_, name_)
196#include "node_type.conf"
197
198      }
199
200      oss << "</" << CContext::GetName() << " >";
201
202      return (oss.str());
203   }
204
205   //----------------------------------------------------------------
206
207   /*!
208   \brief Find all inheritace among objects in a context.
209   \param [in] apply (true) write attributes of parent into ones of child if they are empty
210                     (false) write attributes of parent into a new container of child
211   \param [in] parent unused
212   */
213   void CContext::solveDescInheritance(bool apply, const CAttributeMap * const UNUSED(parent))
214   {
215#define DECLARE_NODE(Name_, name_)    \
216   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
217     C##Name_##Definition::get(C##Name_##Definition::GetDefName())->solveDescInheritance(apply);
218#define DECLARE_NODE_PAR(Name_, name_)
219#include "node_type.conf"
220   }
221
222   //----------------------------------------------------------------
223
224   //! Verify if all root definition in the context have child.
225   bool CContext::hasChild(void) const
226   {
227      return (
228#define DECLARE_NODE(Name_, name_)    \
229   C##Name_##Definition::has(C##Name_##Definition::GetDefName())   ||
230#define DECLARE_NODE_PAR(Name_, name_)
231#include "node_type.conf"
232      false);
233}
234
235   //----------------------------------------------------------------
236
237   void CContext::CleanTree(void)
238   {
239#define DECLARE_NODE(Name_, name_) C##Name_##Definition::ClearAllAttributes();
240#define DECLARE_NODE_PAR(Name_, name_)
241#include "node_type.conf"
242   }
243   ///---------------------------------------------------------------
244
245   //! Initialize client side
246   void CContext::initClient(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtServer /*= 0*/)
247   {
248
249     hasClient = true;
250     MPI_Comm intraCommServer, interCommServer;
251
252     if (CServer::serverLevel != 1)
253      // initClient is called by client
254     {
255       client = new CContextClient(this, intraComm, interComm, cxtServer);
256       if (cxtServer) // Attached mode
257       {
258         intraCommServer = intraComm;
259         interCommServer = interComm;
260       }
261       else
262       {
263         MPI_Comm_dup(intraComm, &intraCommServer);
264         comms.push_back(intraCommServer);
265         MPI_Comm_dup(interComm, &interCommServer);
266         comms.push_back(interCommServer);
267       }
268       registryIn=new CRegistry(intraComm);
269       registryIn->setPath(getId()) ;
270       if (client->clientRank==0) registryIn->fromFile("xios_registry.bin") ;
271       registryIn->bcastRegistry() ;
272       registryOut=new CRegistry(intraComm) ;
273       registryOut->setPath(getId()) ;
274
275       server = new CContextServer(this, intraCommServer, interCommServer);
276     }
277     else
278     // initClient is called by primary server
279     {
280       clientPrimServer.push_back(new CContextClient(this, intraComm, interComm));
281       MPI_Comm_dup(intraComm, &intraCommServer);
282       comms.push_back(intraCommServer);
283       MPI_Comm_dup(interComm, &interCommServer);
284       comms.push_back(interCommServer);
285       serverPrimServer.push_back(new CContextServer(this, intraCommServer, interCommServer));
286     }
287   }
288
289   void CContext::setClientServerBuffer()
290   {
291     size_t minBufferSize = CXios::minBufferSize;
292#define DECLARE_NODE(Name_, name_)    \
293     if (minBufferSize < sizeof(C##Name_##Definition)) minBufferSize = sizeof(C##Name_##Definition);
294#define DECLARE_NODE_PAR(Name_, name_)
295#include "node_type.conf"
296#undef DECLARE_NODE
297#undef DECLARE_NODE_PAR
298
299     std::map<int, StdSize> maxEventSize;
300     std::map<int, StdSize> bufferSize = getAttributesBufferSize(maxEventSize);
301     std::map<int, StdSize> dataBufferSize = getDataBufferSize(maxEventSize);
302
303     std::map<int, StdSize>::iterator it, ite = dataBufferSize.end();
304     for (it = dataBufferSize.begin(); it != ite; ++it)
305       if (it->second > bufferSize[it->first]) bufferSize[it->first] = it->second;
306
307     ite = bufferSize.end();
308     for (it = bufferSize.begin(); it != ite; ++it)
309     {
310       it->second *= CXios::bufferSizeFactor;
311       if (it->second < minBufferSize) it->second = minBufferSize;
312     }
313
314     // We consider that the minimum buffer size is also the minimum event size
315     ite = maxEventSize.end();
316     for (it = maxEventSize.begin(); it != ite; ++it)
317       if (it->second < minBufferSize) it->second = minBufferSize;
318
319     if (client->isServerLeader())
320     {
321       const std::list<int>& ranks = client->getRanksServerLeader();
322       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
323         if (!bufferSize.count(*itRank)) bufferSize[*itRank] = maxEventSize[*itRank] = minBufferSize;
324     }
325     client->setBufferSize(bufferSize, maxEventSize);
326
327     // If it is primary server pool, also set buffer for clientPrimServer.
328     if (hasClient && hasServer)
329     {
330       for (int i = 0; i < clientPrimServer.size(); ++i)
331       {
332         if (clientPrimServer[i]->isServerLeader())
333         {
334           const std::list<int>& ranks = clientPrimServer[i]->getRanksServerLeader();
335           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
336             if (!bufferSize.count(*itRank)) bufferSize[*itRank] = maxEventSize[*itRank] = minBufferSize;
337         }
338         clientPrimServer[i]->setBufferSize(bufferSize, maxEventSize);
339       }
340     }
341   }
342
343   //! Verify whether a context is initialized
344   bool CContext::isInitialized(void)
345   {
346     return hasClient;
347   }
348
349   void CContext::initServer(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtClient /*= 0*/)
350   {
351     hasServer=true;
352     server = new CContextServer(this,intraComm,interComm);
353
354     registryIn=new CRegistry(intraComm);
355     registryIn->setPath(getId()) ;
356     if (server->intraCommRank==0) registryIn->fromFile("xios_registry.bin") ;
357     registryIn->bcastRegistry() ;
358     registryOut=new CRegistry(intraComm) ;
359     registryOut->setPath(getId()) ;
360
361     MPI_Comm intraCommClient, interCommClient;
362     if (cxtClient) // Attached mode
363     {
364       intraCommClient = intraComm;
365       interCommClient = interComm;
366     }
367     else
368     {
369       MPI_Comm_dup(intraComm, &intraCommClient);
370       comms.push_back(intraCommClient);
371       MPI_Comm_dup(interComm, &interCommClient);
372       comms.push_back(interCommClient);
373     }
374     client = new CContextClient(this,intraCommClient,interCommClient,cxtClient);
375   }
376
377   //! Try to send the buffers and receive possible answers
378  bool CContext::checkBuffersAndListen(void)
379  {
380    bool clientReady, serverFinished;
381
382    // Only classical servers are non-blocking
383    if (CServer::serverLevel == 0)
384    {
385      client->checkBuffers();
386      bool hasTmpBufferedEvent = client->hasTemporarilyBufferedEvent();
387      if (hasTmpBufferedEvent)
388        hasTmpBufferedEvent = !client->sendTemporarilyBufferedEvent();
389      // Don't process events if there is a temporarily buffered event
390      return server->eventLoop(!hasTmpBufferedEvent);
391    }
392    else if (CServer::serverLevel == 1)
393    {
394      if (!finalized)
395        client->checkBuffers();
396      bool serverFinished = true;
397      if (!finalized)
398        serverFinished = server->eventLoop();
399      bool serverPrimFinished = true;
400      for (int i = 0; i < clientPrimServer.size(); ++i)
401      {
402        if (!finalized)
403          clientPrimServer[i]->checkBuffers();
404        if (!finalized)
405          serverPrimFinished *= serverPrimServer[i]->eventLoop();
406      }
407      return ( serverFinished && serverPrimFinished);
408    }
409
410    else if (CServer::serverLevel == 2)
411    {
412      client->checkBuffers();
413      return server->eventLoop();
414    }
415  }
416
417   //! Terminate a context
418   void CContext::finalize(void)
419   {
420     // Send registry upon calling the function the first time
421     if (countChildCtx_ == 0)
422       if (hasClient) sendRegistry() ;
423
424     // Client:
425     // (1) blocking send context finalize to its server
426     // (2) blocking receive context finalize from its server
427     // (3) send post finalize to its server
428     if (CXios::isClient)
429     {
430       // Make sure that client (model) enters the loop only once
431       if (countChildCtx_ < 1)
432       {
433         ++countChildCtx_;
434
435         client->finalize();
436         while (client->havePendingRequests())
437            client->checkBuffers();
438
439         while (!server->hasFinished())
440           server->eventLoop();
441
442         if (CXios::isServer) // Mode attache
443           postFinalize();
444         else                  // Mode server
445           client->postFinalize();
446
447       }
448     }
449     // Server: non-blocking send context finalize
450     else if (CXios::isServer)
451     {
452       // First context finalize message received from a model => send context finalize to its child contexts (if any)
453       if (countChildCtx_ == 0)
454         for (int i = 0; i < clientPrimServer.size(); ++i)
455           clientPrimServer[i]->finalize();
456
457       // (Last) context finalized message received
458       // Close files, gather registries, send context finalize to its parent context
459       if (countChildCtx_ == clientPrimServer.size())
460         client->finalize();
461
462       ++countChildCtx_;
463     }
464   }
465
466   /*!
467   * \fn void CContext::postFinalize(void)
468   * Close files, gather registries, and make deallocations.
469   * Function is called when a context is finalized (it has nothing to receive and nothing to send).
470   */
471   void CContext::postFinalize(void)
472   {
473     finalized = true;
474
475     // Primary server: blocking send post finalize to secondary servers
476     for (int i = 0; i < clientPrimServer.size(); ++i)
477       clientPrimServer[i]->postFinalize();
478     bool buffersReleased;
479     do
480     {
481       buffersReleased = true;
482       for (int i = 0; i < clientPrimServer.size(); ++i)
483       {
484         clientPrimServer[i]->checkBuffers();
485         buffersReleased *= !clientPrimServer[i]->havePendingRequests();
486       }
487     } while (!buffersReleased);
488
489     info(20)<<"Context <"<<getId()<<"> is finalized."<<endl;
490
491     //     if (hasServer && !hasClient)
492     {
493       closeAllFile();
494       registryOut->hierarchicalGatherRegistry() ;
495       if (server->intraCommRank==0) CXios::globalRegistry->mergeRegistry(*registryOut) ;
496     }
497
498     //! Deallocate client buffers
499     client->releaseBuffers();
500     for (int i = 0; i < clientPrimServer.size(); ++i)
501       clientPrimServer[i]->releaseBuffers();
502
503     //! Free internally allocated communicators
504     for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it)
505       MPI_Comm_free(&(*it));
506     comms.clear();
507
508   }
509
510   //! Free internally allocated communicators
511   void CContext::freeComms(void)
512   {
513     for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it)
514       MPI_Comm_free(&(*it));
515     comms.clear();
516   }
517
518   //! Deallocate buffers allocated by clientContexts
519   void CContext::releaseClientBuffers(void)
520   {
521     client->releaseBuffers();
522     for (int i = 0; i < clientPrimServer.size(); ++i)
523       clientPrimServer[i]->releaseBuffers();
524   }
525
526   void CContext::postProcessingGlobalAttributes()
527   {
528     if (allProcessed) return; 
529     
530     // After xml is parsed, there are some more works with post processing
531     postProcessing();
532
533     // Check grid and calculate its distribution
534     checkGridEnabledFields();   
535
536     setClientServerBuffer();
537
538     if (hasClient)
539     {
540      // Send all attributes of current context to server
541      this->sendAllAttributesToServer();
542
543      // Send all attributes of current calendar
544      CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer();
545
546      // We have enough information to send to server
547      // First of all, send all enabled files
548      sendEnabledFiles();
549
550      // Then, send all enabled fields
551      sendEnabledFields();
552
553      // At last, we have all info of domain and axis, then send them
554       sendRefDomainsAxis();
555
556       // After that, send all grid (if any)
557       sendRefGrid();
558
559       // We have a xml tree on the server side and now, it should be also processed
560       sendPostProcessing();
561
562       sendGridEnabledFields();       
563     }
564     allProcessed = true;
565   }
566
567   void CContext::sendPostProcessingGlobalAttributes()
568   {
569      // Use correct context client to send message
570     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
571    int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
572     for (int i = 0; i < nbSrvPools; ++i)
573     {
574       CContextClient* contextClientTmp = (0 != clientPrimServer.size()) ? clientPrimServer[i] : client;
575       CEventClient event(getType(),EVENT_ID_POST_PROCESS_GLOBAL_ATTRIBUTES);
576
577       if (contextClientTmp->isServerLeader())
578       {
579         CMessage msg;
580         if (hasServer)
581           msg<<this->getIdServer(i);
582         else
583           msg<<this->getIdServer();
584         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
585         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
586           event.push(*itRank,1,msg);
587         contextClientTmp->sendEvent(event);
588       }
589       else contextClientTmp->sendEvent(event);
590     }
591   }
592
593   void CContext::recvPostProcessingGlobalAttributes(CEventServer& event)
594   {
595      CBufferIn* buffer=event.subEvents.begin()->buffer;
596      string id;
597      *buffer>>id;
598      get(id)->recvPostProcessingGlobalAttributes(*buffer);
599   }
600
601   void CContext::recvPostProcessingGlobalAttributes(CBufferIn& buffer)
602   {     
603      postProcessingGlobalAttributes();
604   }
605
606   /*!
607   \brief Close all the context defintion and do processing data
608      After everything is well defined on client side, they will be processed and sent to server
609   From the version 2.0, sever and client work no more on the same database. Moreover, client(s) will send
610   all necessary information to server, from which each server can build its own database.
611   Because the role of server is to write out field data on a specific netcdf file,
612   the only information that it needs is the enabled files
613   and the active fields (fields will be written onto active files)
614   */
615   void CContext::closeDefinition(void)
616   {
617    postProcessingGlobalAttributes();
618
619    if (hasClient) sendPostProcessingGlobalAttributes();
620
621    // There are some processings that should be done after all of above. For example: check mask or index
622    this->buildFilterGraphOfEnabledFields();
623   
624     if (hasClient && !hasServer)
625    {
626      buildFilterGraphOfFieldsWithReadAccess();
627    }
628   
629    checkGridEnabledFields();   
630
631    if (hasClient) this->sendProcessingGridOfEnabledFields();
632    if (hasClient) this->sendCloseDefinition();
633
634    // Nettoyage de l'arborescence
635    if (hasClient) CleanTree(); // Only on client side??
636
637    if (hasClient)
638    {
639      sendCreateFileHeader();
640      if (!hasServer) startPrefetchingOfEnabledReadModeFiles();
641    }
642   }
643
644   void CContext::findAllEnabledFields(void)
645   {
646     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
647     (void)this->enabledFiles[i]->getEnabledFields();
648   }
649
650   void CContext::findAllEnabledFieldsInReadModeFiles(void)
651   {
652     for (unsigned int i = 0; i < this->enabledReadModeFiles.size(); ++i)
653     (void)this->enabledReadModeFiles[i]->getEnabledFields();
654   }
655
656   void CContext::readAttributesOfEnabledFieldsInReadModeFiles()
657   {
658      for (unsigned int i = 0; i < this->enabledReadModeFiles.size(); ++i)
659        (void)this->enabledReadModeFiles[i]->readAttributesOfEnabledFieldsInReadMode();
660   }
661
662   void CContext::sendGridEnabledFields()
663   {
664     int size = this->enabledFiles.size();
665     for (int i = 0; i < size; ++i)
666     {       
667       this->enabledFiles[i]->sendGridOfEnabledFields();
668     }
669   }
670
671   void CContext::checkGridEnabledFields()
672   {
673     int size = this->enabledFiles.size();
674     for (int i = 0; i < size; ++i)
675     {
676       this->enabledFiles[i]->checkGridOfEnabledFields();       
677     }
678   }
679
680   void CContext::solveOnlyRefOfEnabledFields(bool sendToServer)
681   {
682     int size = this->enabledFiles.size();
683     for (int i = 0; i < size; ++i)
684     {
685       this->enabledFiles[i]->solveOnlyRefOfEnabledFields(sendToServer);
686     }
687
688     for (int i = 0; i < size; ++i)
689     {
690       this->enabledFiles[i]->generateNewTransformationGridDest();
691     }
692
693   }
694
695   void CContext::solveAllRefOfEnabledFieldsAndTransform(bool sendToServer)
696   {
697     int size = this->enabledFiles.size();
698     for (int i = 0; i < size; ++i)
699     {
700       this->enabledFiles[i]->solveAllRefOfEnabledFieldsAndTransform(sendToServer);
701     }
702   }
703
704   void CContext::buildFilterGraphOfEnabledFields()
705   {
706     int size = this->enabledFiles.size();
707     for (int i = 0; i < size; ++i)
708     {
709       this->enabledFiles[i]->buildFilterGraphOfEnabledFields(garbageCollector);
710     }
711   }
712
713   void CContext::startPrefetchingOfEnabledReadModeFiles()
714   {
715     int size = enabledReadModeFiles.size();
716     for (int i = 0; i < size; ++i)
717     {
718        enabledReadModeFiles[i]->prefetchEnabledReadModeFields();
719     }
720   }
721
722   void CContext::checkPrefetchingOfEnabledReadModeFiles()
723   {
724     int size = enabledReadModeFiles.size();
725     for (int i = 0; i < size; ++i)
726     {
727        enabledReadModeFiles[i]->prefetchEnabledReadModeFieldsIfNeeded();
728     }
729   }
730
731  void CContext::findFieldsWithReadAccess(void)
732  {
733    fieldsWithReadAccess.clear();
734    const vector<CField*> allFields = CField::getAll();
735    for (size_t i = 0; i < allFields.size(); ++i)
736    {
737      CField* field = allFields[i];
738
739      if (field->file && !field->file->mode.isEmpty() && field->file->mode == CFile::mode_attr::read)
740        field->read_access = true;
741      else if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled))
742        fieldsWithReadAccess.push_back(field);
743    }
744  }
745
746  void CContext::solveAllRefOfFieldsWithReadAccess()
747  {
748    for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
749      fieldsWithReadAccess[i]->solveAllReferenceEnabledField(false);
750  }
751
752  void CContext::buildFilterGraphOfFieldsWithReadAccess()
753  {
754    for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
755      fieldsWithReadAccess[i]->buildFilterGraph(garbageCollector, true);
756  }
757
758   void CContext::solveAllInheritance(bool apply)
759   {
760     // Résolution des héritages descendants (càd des héritages de groupes)
761     // pour chacun des contextes.
762      solveDescInheritance(apply);
763
764     // Résolution des héritages par référence au niveau des fichiers.
765      const vector<CFile*> allFiles=CFile::getAll();
766      const vector<CGrid*> allGrids= CGrid::getAll();
767
768      if (hasClient && !hasServer)
769      //if (hasClient)
770      {
771        for (unsigned int i = 0; i < allFiles.size(); i++)
772          allFiles[i]->solveFieldRefInheritance(apply);
773      }
774
775      unsigned int vecSize = allGrids.size();
776      unsigned int i = 0;
777      for (i = 0; i < vecSize; ++i)
778        allGrids[i]->solveDomainAxisRefInheritance(apply);
779
780   }
781
782   void CContext::findEnabledFiles(void)
783   {
784      const std::vector<CFile*> allFiles = CFile::getAll();
785
786      for (unsigned int i = 0; i < allFiles.size(); i++)
787         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
788         {
789            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
790               enabledFiles.push_back(allFiles[i]);
791         }
792         else enabledFiles.push_back(allFiles[i]); // otherwise true by default
793
794
795      if (enabledFiles.size() == 0)
796         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
797               << getId() << "\" !");
798
799      // Assigning contextClient to each enabled file
800      if (hasClient)
801      {
802        for (int i = 0; i < enabledFiles.size(); ++i)
803        {
804          if (hasServer)
805          {
806            int srvId = i % clientPrimServer.size();
807            enabledFiles[i]->setContextClient(clientPrimServer[srvId]);
808          }
809          else
810            enabledFiles[i]->setContextClient(client);
811        }
812      }
813   }
814
815   void CContext::findEnabledReadModeFiles(void)
816   {
817     int size = this->enabledFiles.size();
818     for (int i = 0; i < size; ++i)
819     {
820       if (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::read)
821        enabledReadModeFiles.push_back(enabledFiles[i]);
822     }
823   }
824
825   void CContext::closeAllFile(void)
826   {
827     std::vector<CFile*>::const_iterator
828            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
829
830     for (; it != end; it++)
831     {
832       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
833       (*it)->close();
834     }
835   }
836
837   /*!
838   \brief Dispatch event received from client
839      Whenever a message is received in buffer of server, it will be processed depending on
840   its event type. A new event type should be added in the switch list to make sure
841   it processed on server side.
842   \param [in] event: Received message
843   */
844   bool CContext::dispatchEvent(CEventServer& event)
845   {
846
847      if (SuperClass::dispatchEvent(event)) return true;
848      else
849      {
850        switch(event.type)
851        {
852           case EVENT_ID_CLOSE_DEFINITION :
853             recvCloseDefinition(event);
854             return true;
855             break;
856           case EVENT_ID_UPDATE_CALENDAR:
857             recvUpdateCalendar(event);
858             return true;
859             break;
860           case EVENT_ID_CREATE_FILE_HEADER :
861             recvCreateFileHeader(event);
862             return true;
863             break;
864           case EVENT_ID_POST_PROCESS:
865             recvPostProcessing(event);
866             return true;
867            case EVENT_ID_SEND_REGISTRY:
868             recvRegistry(event);
869             return true;
870             break;
871            case EVENT_ID_POST_PROCESS_GLOBAL_ATTRIBUTES:
872             recvPostProcessingGlobalAttributes(event);
873             return true;
874             break;
875            case EVENT_ID_PROCESS_GRID_ENABLED_FIELDS:
876             recvProcessingGridOfEnabledFields(event);
877             return true;
878             break;
879           default :
880             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
881                    <<"Unknown Event");
882           return false;
883         }
884      }
885   }
886
887   //! Client side: Send a message to server to make it close
888   void CContext::sendCloseDefinition(void)
889   {
890     // Use correct context client to send message
891     int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
892     for (int i = 0; i < nbSrvPools; ++i)
893     {
894       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
895       CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
896       if (contextClientTmp->isServerLeader())
897       {
898         CMessage msg;
899         if (hasServer)
900           msg<<this->getIdServer(i);
901         else
902           msg<<this->getIdServer();
903         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
904         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
905           event.push(*itRank,1,msg);
906         contextClientTmp->sendEvent(event);
907       }
908       else contextClientTmp->sendEvent(event);
909     }
910   }
911
912   //! Server side: Receive a message of client announcing a context close
913   void CContext::recvCloseDefinition(CEventServer& event)
914   {
915      CBufferIn* buffer=event.subEvents.begin()->buffer;
916      string id;
917      *buffer>>id;
918      get(id)->closeDefinition();
919   }
920
921   //! Client side: Send a message to update calendar in each time step
922   void CContext::sendUpdateCalendar(int step)
923   {
924     // Use correct context client to send message
925    int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
926     for (int i = 0; i < nbSrvPools; ++i)
927     {
928       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
929       CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR);
930
931         if (contextClientTmp->isServerLeader())
932         {
933           CMessage msg;
934           if (hasServer)
935             msg<<this->getIdServer(i)<<step;
936           else
937             msg<<this->getIdServer()<<step;
938           const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
939           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
940             event.push(*itRank,1,msg);
941           contextClientTmp->sendEvent(event);
942         }
943         else contextClientTmp->sendEvent(event);
944     }
945   }
946
947   //! Server side: Receive a message of client annoucing calendar update
948   void CContext::recvUpdateCalendar(CEventServer& event)
949   {
950      CBufferIn* buffer=event.subEvents.begin()->buffer;
951      string id;
952      *buffer>>id;
953      get(id)->recvUpdateCalendar(*buffer);
954   }
955
956   //! Server side: Receive a message of client annoucing calendar update
957   void CContext::recvUpdateCalendar(CBufferIn& buffer)
958   {
959      int step;
960      buffer>>step;
961      updateCalendar(step);
962      if (hasClient && hasServer)
963      {       
964        sendUpdateCalendar(step);
965      }
966   }
967
968   //! Client side: Send a message to create header part of netcdf file
969   void CContext::sendCreateFileHeader(void)
970   {
971     // Use correct context client to send message
972     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
973     int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
974     for (int i = 0; i < nbSrvPools; ++i)
975     {
976       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
977       CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER);
978
979       if (contextClientTmp->isServerLeader())
980       {
981         CMessage msg;
982         if (hasServer)
983           msg<<this->getIdServer(i);
984         else
985           msg<<this->getIdServer();
986         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
987         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
988           event.push(*itRank,1,msg) ;
989         contextClientTmp->sendEvent(event);
990       }
991       else contextClientTmp->sendEvent(event);
992     }
993   }
994
995   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
996   void CContext::recvCreateFileHeader(CEventServer& event)
997   {
998      CBufferIn* buffer=event.subEvents.begin()->buffer;
999      string id;
1000      *buffer>>id;
1001      get(id)->recvCreateFileHeader(*buffer);
1002   }
1003
1004   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
1005   void CContext::recvCreateFileHeader(CBufferIn& buffer)
1006   {
1007      if (!hasClient && hasServer) 
1008        createFileHeader();
1009   }
1010
1011   //! Client side: Send a message to do some post processing on server
1012   void CContext::sendProcessingGridOfEnabledFields()
1013   {
1014      // Use correct context client to send message
1015     int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
1016     for (int i = 0; i < nbSrvPools; ++i)
1017     {
1018       CContextClient* contextClientTmp = (0 != clientPrimServer.size()) ? clientPrimServer[i] : client;
1019       CEventClient event(getType(),EVENT_ID_PROCESS_GRID_ENABLED_FIELDS);
1020
1021       if (contextClientTmp->isServerLeader())
1022       {
1023         CMessage msg;
1024         if (hasServer)
1025           msg<<this->getIdServer(i);
1026         else
1027           msg<<this->getIdServer();
1028         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1029         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1030           event.push(*itRank,1,msg);
1031         contextClientTmp->sendEvent(event);
1032       }
1033       else contextClientTmp->sendEvent(event);
1034     }
1035   }
1036
1037   //! Server side: Receive a message to do some post processing
1038   void CContext::recvProcessingGridOfEnabledFields(CEventServer& event)
1039   {
1040      CBufferIn* buffer=event.subEvents.begin()->buffer;
1041      string id;
1042      *buffer>>id;     
1043   }
1044
1045   //! Client side: Send a message to do some post processing on server
1046   void CContext::sendPostProcessing()
1047   {
1048      // Use correct context client to send message
1049     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
1050     int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
1051     for (int i = 0; i < nbSrvPools; ++i)
1052     {
1053       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
1054       CEventClient event(getType(),EVENT_ID_POST_PROCESS);
1055       if (contextClientTmp->isServerLeader())
1056       {
1057         CMessage msg;
1058         if (hasServer)
1059           msg<<this->getIdServer(i);
1060         else
1061           msg<<this->getIdServer();
1062         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1063         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1064         event.push(*itRank,1,msg);
1065         contextClientTmp->sendEvent(event);
1066       }
1067       else contextClientTmp->sendEvent(event);
1068     }
1069   }
1070
1071   //! Server side: Receive a message to do some post processing
1072   void CContext::recvPostProcessing(CEventServer& event)
1073   {
1074      CBufferIn* buffer=event.subEvents.begin()->buffer;
1075      string id;
1076      *buffer>>id;
1077      get(id)->recvPostProcessing(*buffer);
1078   }
1079
1080   //! Server side: Receive a message to do some post processing
1081   void CContext::recvPostProcessing(CBufferIn& buffer)
1082   {
1083      CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar();
1084      postProcessing();
1085   }
1086
1087   const StdString& CContext::getIdServer()
1088   {
1089      if (hasClient)
1090      {
1091        idServer_ = this->getId();
1092        idServer_ += "_server";
1093        return idServer_;
1094      }
1095      if (hasServer) return (this->getId());
1096   }
1097
1098   const StdString& CContext::getIdServer(const int i)
1099   {
1100     idServer_ = this->getId();
1101     idServer_ += "_server_";
1102     idServer_ += boost::lexical_cast<string>(i);
1103     return idServer_;
1104   }
1105
1106
1107   /*!
1108   \brief Do some simple post processings after parsing xml file
1109      After the xml file (iodef.xml) is parsed, it is necessary to build all relations among
1110   created object, e.g: inhertance among fields, domain, axis. After that, all fiels as well as their parents (reference fields),
1111   which will be written out into netcdf files, are processed
1112   */
1113   void CContext::postProcessing()
1114   {
1115     if (isPostProcessed) return;
1116
1117      // Make sure the calendar was correctly created
1118      if (!calendar)
1119        ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"")
1120      else if (calendar->getTimeStep() == NoneDu)
1121        ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"")
1122      // Calendar first update to set the current date equals to the start date
1123      calendar->update(0);
1124
1125      // Find all inheritance in xml structure
1126      this->solveAllInheritance();
1127
1128//      ShowTree(info(10));
1129
1130      // Check if some axis, domains or grids are eligible to for compressed indexed output.
1131      // Warning: This must be done after solving the inheritance and before the rest of post-processing
1132      checkAxisDomainsGridsEligibilityForCompressedOutput();     
1133
1134      // Check if some automatic time series should be generated
1135      // Warning: This must be done after solving the inheritance and before the rest of post-processing     
1136
1137      // The timeseries should only be prepared in client
1138      if (hasClient && !hasServer) prepareTimeseries();
1139
1140      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
1141      this->findEnabledFiles();
1142     
1143      // For now, only read files with client and only one level server
1144      if (hasClient && !hasServer) this->findEnabledReadModeFiles();
1145
1146      // Find all enabled fields of each file
1147      this->findAllEnabledFields();
1148      // For now, only read files with client and only one level server
1149      if (hasClient && !hasServer) this->findAllEnabledFieldsInReadModeFiles();
1150
1151
1152      if (hasClient && !hasServer)
1153      {
1154       // Try to read attributes of fields in file then fill in corresponding grid (or domain, axis)
1155       this->readAttributesOfEnabledFieldsInReadModeFiles();
1156      }
1157
1158      // Only search and rebuild all reference objects of enable fields, don't transform
1159      this->solveOnlyRefOfEnabledFields(false);
1160
1161      // Search and rebuild all reference object of enabled fields, and transform
1162      this->solveAllRefOfEnabledFieldsAndTransform(false);
1163
1164      // Find all fields with read access from the public API
1165      if (hasClient && !hasServer) findFieldsWithReadAccess();
1166      // and solve the all reference for them
1167      if (hasClient && !hasServer) solveAllRefOfFieldsWithReadAccess();
1168
1169      isPostProcessed = true;
1170   }
1171
1172   /*!
1173    * Compute the required buffer size to send the attributes (mostly those grid related).
1174    *
1175    * \param maxEventSize [in/out] the size of the bigger event for each connected server
1176    */
1177   std::map<int, StdSize> CContext::getAttributesBufferSize(std::map<int, StdSize>& maxEventSize)
1178   {
1179     std::map<int, StdSize> attributesSize;
1180
1181     if (hasClient)
1182     {
1183       size_t numEnabledFiles = this->enabledFiles.size();
1184       for (size_t i = 0; i < numEnabledFiles; ++i)
1185       {
1186         CFile* file = this->enabledFiles[i];
1187
1188         std::vector<CField*> enabledFields = file->getEnabledFields();
1189         size_t numEnabledFields = enabledFields.size();
1190         for (size_t j = 0; j < numEnabledFields; ++j)
1191         {
1192           const std::map<int, StdSize> mapSize = enabledFields[j]->getGridAttributesBufferSize();
1193           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
1194           for (; it != itE; ++it)
1195           {
1196             // If attributesSize[it->first] does not exist, it will be zero-initialized
1197             // so we can use it safely without checking for its existance
1198             if (attributesSize[it->first] < it->second)
1199               attributesSize[it->first] = it->second;
1200
1201             if (maxEventSize[it->first] < it->second)
1202               maxEventSize[it->first] = it->second;
1203           }
1204         }
1205       }
1206     }
1207
1208     return attributesSize;
1209   }
1210
1211   /*!
1212    * Compute the required buffer size to send the fields data.
1213    *
1214    * \param maxEventSize [in/out] the size of the bigger event for each connected server
1215    */
1216   std::map<int, StdSize> CContext::getDataBufferSize(std::map<int, StdSize>& maxEventSize)
1217   {
1218     CFile::mode_attr::t_enum mode = hasClient ? CFile::mode_attr::write : CFile::mode_attr::read;
1219
1220     std::map<int, StdSize> dataSize;
1221
1222     // Find all reference domain and axis of all active fields
1223     size_t numEnabledFiles = this->enabledFiles.size();
1224     for (size_t i = 0; i < numEnabledFiles; ++i)
1225     {
1226       CFile* file = this->enabledFiles[i];
1227       CFile::mode_attr::t_enum fileMode = file->mode.isEmpty() ? CFile::mode_attr::write : file->mode.getValue();
1228
1229       if (fileMode == mode)
1230       {
1231         std::vector<CField*> enabledFields = file->getEnabledFields();
1232         size_t numEnabledFields = enabledFields.size();
1233         for (size_t j = 0; j < numEnabledFields; ++j)
1234         {
1235           const std::vector<std::map<int, StdSize> > mapSize = enabledFields[j]->getGridDataBufferSize();
1236           for (size_t c = 0; c < mapSize.size(); ++c)
1237           {
1238             std::map<int, StdSize>::const_iterator it = mapSize[c].begin(), itE = mapSize[c].end();
1239             for (; it != itE; ++it)
1240             {
1241               // If dataSize[it->first] does not exist, it will be zero-initialized
1242               // so we can use it safely without checking for its existance
1243               if (CXios::isOptPerformance)
1244                 dataSize[it->first] += it->second;
1245               else if (dataSize[it->first] < it->second)
1246                 dataSize[it->first] = it->second;
1247
1248               if (maxEventSize[it->first] < it->second)
1249                 maxEventSize[it->first] = it->second;
1250             }
1251           }
1252         }
1253       }
1254     }
1255
1256     return dataSize;
1257   }
1258
1259   //! Client side: Send infomation of active files (files are enabled to write out)
1260   void CContext::sendEnabledFiles()
1261   {
1262     int size = this->enabledFiles.size();
1263
1264     // In a context, each type has a root definition, e.g: axis, domain, field.
1265     // Every object must be a child of one of these root definition. In this case
1266     // all new file objects created on server must be children of the root "file_definition"
1267     StdString fileDefRoot("file_definition");
1268     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
1269     for (int i = 0; i < size; ++i)
1270     {
1271       cfgrpPtr->sendCreateChild(this->enabledFiles[i]->getId(),enabledFiles[i]->getContextClient());
1272       this->enabledFiles[i]->sendAllAttributesToServer(enabledFiles[i]->getContextClient());
1273       this->enabledFiles[i]->sendAddAllVariables(enabledFiles[i]->getContextClient());
1274     }
1275   }
1276
1277   //! Client side: Send information of active fields (ones are written onto files)
1278   void CContext::sendEnabledFields()
1279   {
1280     int size = this->enabledFiles.size();
1281     for (int i = 0; i < size; ++i)
1282     {
1283       this->enabledFiles[i]->sendEnabledFields(enabledFiles[i]->getContextClient());
1284     }
1285   }
1286
1287   //! Client side: Check if the defined axis, domains and grids are eligible for compressed indexed output
1288   void CContext::checkAxisDomainsGridsEligibilityForCompressedOutput()
1289   {
1290     if (!hasClient) return;
1291
1292     const vector<CAxis*> allAxis = CAxis::getAll();
1293     for (vector<CAxis*>::const_iterator it = allAxis.begin(); it != allAxis.end(); it++)
1294       (*it)->checkEligibilityForCompressedOutput();
1295
1296     const vector<CDomain*> allDomains = CDomain::getAll();
1297     for (vector<CDomain*>::const_iterator it = allDomains.begin(); it != allDomains.end(); it++)
1298       (*it)->checkEligibilityForCompressedOutput();
1299
1300     const vector<CGrid*> allGrids = CGrid::getAll();
1301     for (vector<CGrid*>::const_iterator it = allGrids.begin(); it != allGrids.end(); it++)
1302       (*it)->checkEligibilityForCompressedOutput();
1303   }
1304
1305   //! Client side: Prepare the timeseries by adding the necessary files
1306   void CContext::prepareTimeseries()
1307   {
1308     if (!hasClient) return;
1309
1310     const std::vector<CFile*> allFiles = CFile::getAll();
1311     for (size_t i = 0; i < allFiles.size(); i++)
1312     {
1313       CFile* file = allFiles[i];
1314
1315       if (!file->timeseries.isEmpty() && file->timeseries != CFile::timeseries_attr::none)
1316       {
1317         StdString tsPrefix = !file->ts_prefix.isEmpty() ? file->ts_prefix : file->getFileOutputName();
1318
1319         const std::vector<CField*> allFields = file->getAllFields();
1320         for (size_t j = 0; j < allFields.size(); j++)
1321         {
1322           CField* field = allFields[j];
1323
1324           if (!field->ts_enabled.isEmpty() && field->ts_enabled)
1325           {
1326             CFile* tsFile = CFile::create();
1327             tsFile->duplicateAttributes(file);
1328             tsFile->setVirtualVariableGroup(file->getVirtualVariableGroup());
1329
1330             tsFile->name = tsPrefix + "_";
1331             if (!field->name.isEmpty())
1332               tsFile->name.get() += field->name;
1333             else if (field->hasDirectFieldReference()) // We cannot use getBaseFieldReference() just yet
1334               tsFile->name.get() += field->field_ref;
1335             else
1336               tsFile->name.get() += field->getId();
1337
1338             if (!field->ts_split_freq.isEmpty())
1339               tsFile->split_freq = field->ts_split_freq;
1340
1341             CField* tsField = tsFile->addField();
1342             tsField->field_ref = field->getId();
1343             tsField->setVirtualVariableGroup(field->getVirtualVariableGroup());
1344
1345             tsFile->solveFieldRefInheritance(true);
1346
1347             if (file->timeseries == CFile::timeseries_attr::exclusive)
1348               field->enabled = false;
1349           }
1350         }
1351
1352         // Finally disable the original file is need be
1353         if (file->timeseries == CFile::timeseries_attr::only)
1354          file->enabled = false;
1355       }
1356     }
1357   }
1358
1359   //! Client side: Send information of reference grid of active fields
1360   void CContext::sendRefGrid()
1361   {
1362     std::set<StdString> gridIds;
1363     int sizeFile = this->enabledFiles.size();
1364     CFile* filePtr(NULL);
1365
1366     // Firstly, find all reference grids of all active fields
1367     for (int i = 0; i < sizeFile; ++i)
1368     {
1369       filePtr = this->enabledFiles[i];
1370       std::vector<CField*> enabledFields = filePtr->getEnabledFields();
1371       int sizeField = enabledFields.size();
1372       for (int numField = 0; numField < sizeField; ++numField)
1373       {
1374         if (0 != enabledFields[numField]->getRelGrid())
1375           gridIds.insert(CGrid::get(enabledFields[numField]->getRelGrid())->getId());
1376       }
1377     }
1378
1379     // Create all reference grids on server side
1380     StdString gridDefRoot("grid_definition");
1381     CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
1382     std::set<StdString>::const_iterator it, itE = gridIds.end();
1383     for (it = gridIds.begin(); it != itE; ++it)
1384     {
1385       gridPtr->sendCreateChild(*it);
1386       CGrid::get(*it)->sendAllAttributesToServer();
1387       CGrid::get(*it)->sendAllDomains();
1388       CGrid::get(*it)->sendAllAxis();
1389       CGrid::get(*it)->sendAllScalars();
1390     }
1391   }
1392
1393
1394   //! Client side: Send information of reference domain and axis of active fields
1395   void CContext::sendRefDomainsAxis()
1396   {
1397     std::set<StdString> domainIds, axisIds, scalarIds;
1398
1399     // Find all reference domain and axis of all active fields
1400     int numEnabledFiles = this->enabledFiles.size();
1401     for (int i = 0; i < numEnabledFiles; ++i)
1402     {
1403       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
1404       int numEnabledFields = enabledFields.size();
1405       for (int j = 0; j < numEnabledFields; ++j)
1406       {
1407         const std::vector<StdString>& prDomAxisScalarId = enabledFields[j]->getRefDomainAxisIds();
1408         if ("" != prDomAxisScalarId[0]) domainIds.insert(prDomAxisScalarId[0]);
1409         if ("" != prDomAxisScalarId[1]) axisIds.insert(prDomAxisScalarId[1]);
1410         if ("" != prDomAxisScalarId[2]) scalarIds.insert(prDomAxisScalarId[2]);
1411       }
1412     }
1413
1414     // Create all reference axis on server side
1415     std::set<StdString>::iterator itDom, itAxis, itScalar;
1416     std::set<StdString>::const_iterator itE;
1417
1418     StdString scalarDefRoot("scalar_definition");
1419     CScalarGroup* scalarPtr = CScalarGroup::get(scalarDefRoot);
1420     itE = scalarIds.end();
1421     for (itScalar = scalarIds.begin(); itScalar != itE; ++itScalar)
1422     {
1423       if (!itScalar->empty())
1424       {
1425         scalarPtr->sendCreateChild(*itScalar);
1426         CScalar::get(*itScalar)->sendAllAttributesToServer();
1427       }
1428     }
1429
1430     StdString axiDefRoot("axis_definition");
1431     CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
1432     itE = axisIds.end();
1433     for (itAxis = axisIds.begin(); itAxis != itE; ++itAxis)
1434     {
1435       if (!itAxis->empty())
1436       {
1437         axisPtr->sendCreateChild(*itAxis);
1438         CAxis::get(*itAxis)->sendAllAttributesToServer();
1439       }
1440     }
1441
1442     // Create all reference domains on server side
1443     StdString domDefRoot("domain_definition");
1444     CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
1445     itE = domainIds.end();
1446     for (itDom = domainIds.begin(); itDom != itE; ++itDom)
1447     {
1448       if (!itDom->empty()) {
1449          domPtr->sendCreateChild(*itDom);
1450          CDomain::get(*itDom)->sendAllAttributesToServer();
1451       }
1452     }
1453   }
1454
1455   //! Update calendar in each time step
1456   void CContext::updateCalendar(int step)
1457   {
1458      info(50) <<"Context "<< this->getId() <<" updateCalendar : before : " << calendar->getCurrentDate() << endl;
1459      calendar->update(step);
1460      info(50) <<"Context "<< this->getId() << " updateCalendar : after : " << calendar->getCurrentDate() << endl;
1461
1462      if (hasClient)
1463      {
1464        checkPrefetchingOfEnabledReadModeFiles();
1465        garbageCollector.invalidate(calendar->getCurrentDate());
1466      }
1467   }
1468
1469   //! Server side: Create header of netcdf file
1470   void CContext::createFileHeader(void )
1471   {
1472      vector<CFile*>::const_iterator it;
1473
1474      for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
1475      {
1476         (*it)->initFile();
1477      }
1478   }
1479
1480   //! Get current context
1481   CContext* CContext::getCurrent(void)
1482   {
1483     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get();
1484   }
1485
1486   /*!
1487   \brief Set context with an id be the current context
1488   \param [in] id identity of context to be set to current
1489   */
1490   void CContext::setCurrent(const string& id)
1491   {
1492     CObjectFactory::SetCurrentContextId(id);
1493     CGroupFactory::SetCurrentContextId(id);
1494   }
1495
1496  /*!
1497  \brief Create a context with specific id
1498  \param [in] id identity of new context
1499  \return pointer to the new context or already-existed one with identity id
1500  */
1501  CContext* CContext::create(const StdString& id)
1502  {
1503    CContext::setCurrent(id);
1504
1505    bool hasctxt = CContext::has(id);
1506    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
1507    getRoot();
1508    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
1509
1510#define DECLARE_NODE(Name_, name_) \
1511    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
1512#define DECLARE_NODE_PAR(Name_, name_)
1513#include "node_type.conf"
1514
1515    return (context);
1516  }
1517
1518
1519     //! Server side: Receive a message to do some post processing
1520  void CContext::recvRegistry(CEventServer& event)
1521  {
1522    CBufferIn* buffer=event.subEvents.begin()->buffer;
1523    string id;
1524    *buffer>>id;
1525    get(id)->recvRegistry(*buffer);
1526  }
1527
1528  void CContext::recvRegistry(CBufferIn& buffer)
1529  {
1530    if (server->intraCommRank==0)
1531    {
1532      CRegistry registry(server->intraComm) ;
1533      registry.fromBuffer(buffer) ;
1534      registryOut->mergeRegistry(registry) ;
1535    }
1536  }
1537
1538  void CContext::sendRegistry(void)
1539  {   
1540    registryOut->hierarchicalGatherRegistry() ;
1541
1542    // Use correct context client to send message
1543    int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
1544    for (int i = 0; i < nbSrvPools; ++i)
1545    {
1546      CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
1547      CEventClient event(CContext::GetType(), CContext::EVENT_ID_SEND_REGISTRY);
1548        if (contextClientTmp->isServerLeader())
1549        {
1550           CMessage msg ;
1551           if (hasServer)
1552             msg<<this->getIdServer(i);
1553           else
1554             msg<<this->getIdServer();
1555           if (contextClientTmp->clientRank==0) msg<<*registryOut ;
1556           const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1557           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1558             event.push(*itRank,1,msg);
1559           contextClientTmp->sendEvent(event);
1560         }
1561         else contextClientTmp->sendEvent(event);
1562    }
1563  }
1564
1565  /*!
1566  * \fn bool CContext::isFinalized(void)
1567  * Context is finalized if it received context post finalize event.
1568  */
1569  bool CContext::isFinalized(void)
1570  {
1571    return finalized;
1572  }
1573
1574} // namespace xios
Note: See TracBrowser for help on using the repository browser.