XIOS  1.0
Xml I/O Server
 Tout Classes Espaces de nommage Fichiers Fonctions Variables Définitions de type Énumérations Valeurs énumérées Amis Macros
context.cpp
Aller à la documentation de ce fichier.
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 #include "timer.hpp"
17 #include "memtrack.hpp"
18 #include <limits>
19 #include <fstream>
20 #include "server.hpp"
22 
23 namespace xios {
24 
25  std::shared_ptr<CContextGroup> CContext::root;
26 
28 
30  : CObjectTemplate<CContext>(), CContextAttributes()
31  , calendar(), hasClient(false), hasServer(false)
32  , isPostProcessed(false), finalized(false)
33  , idServer_(), client(0), server(0)
34  , allProcessed(false), countChildCtx_(0)
35 
36  { /* Ne rien faire de plus */ }
37 
39  : CObjectTemplate<CContext>(id), CContextAttributes()
40  , calendar(), hasClient(false), hasServer(false)
41  , isPostProcessed(false), finalized(false)
42  , idServer_(), client(0), server(0)
43  , allProcessed(false), countChildCtx_(0)
44  { /* Ne rien faire de plus */ }
45 
47  {
48  delete client;
49  delete server;
50  for (std::vector<CContextClient*>::iterator it = clientPrimServer.begin(); it != clientPrimServer.end(); it++) delete *it;
51  for (std::vector<CContextServer*>::iterator it = serverPrimServer.begin(); it != serverPrimServer.end(); it++) delete *it;
52 
53  }
54 
55  //----------------------------------------------------------------
57  StdString CContext::GetName(void) { return (StdString("context")); }
59  ENodeType CContext::GetType(void) { return (eContext); }
60 
61  //----------------------------------------------------------------
62 
67  CContextGroup* CContext::getRoot(void)
68  TRY
69  {
70  if (root.get()==NULL) root=std::shared_ptr<CContextGroup>(new CContextGroup(xml::CXMLNode::GetRootName()));
71  return root.get();
72  }
73  CATCH
74 
75  //----------------------------------------------------------------
76 
81  std::shared_ptr<CCalendar> CContext::getCalendar(void) const
82  TRY
83  {
84  return (this->calendar);
85  }
86  CATCH
87 
88  //----------------------------------------------------------------
89 
94  void CContext::setCalendar(std::shared_ptr<CCalendar> newCalendar)
95  TRY
96  {
97  this->calendar = newCalendar;
98  }
100 
101  //----------------------------------------------------------------
107  TRY
108  {
110 
111  // PARSING POUR GESTION DES ENFANTS
112  xml::THashAttributes attributes = node.getAttributes();
113 
114  if (attributes.end() != attributes.find("src"))
115  {
116  StdIFStream ifs ( attributes["src"].c_str() , StdIFStream::in );
117  if ( (ifs.rdstate() & std::ifstream::failbit ) != 0 )
118  ERROR("void CContext::parse(xml::CXMLNode & node)",
119  <<endl<< "Can not open <"<<attributes["src"].c_str()<<"> file" );
120  if (!ifs.good())
121  ERROR("CContext::parse(xml::CXMLNode & node)",
122  << "[ filename = " << attributes["src"] << " ] Bad xml stream !");
123  xml::CXMLParser::ParseInclude(ifs, attributes["src"], *this);
124  }
125 
126  if (node.getElementName().compare(CContext::GetName()))
127  DEBUG("Le noeud is wrong defined but will be considered as a context !");
128 
129  if (!(node.goToChildElement()))
130  {
131  DEBUG("Le context ne contient pas d'enfant !");
132  }
133  else
134  {
135  do { // Parcours des contextes pour traitement.
136 
137  StdString name = node.getElementName();
138  attributes.clear();
139  attributes = node.getAttributes();
140 
141  if (attributes.end() != attributes.find("id"))
142  {
143  DEBUG(<< "Definition node has an id,"
144  << "it will not be taking account !");
145  }
146 
147 #define DECLARE_NODE(Name_, name_) \
148  if (name.compare(C##Name_##Definition::GetDefName()) == 0) \
149  { C##Name_##Definition::create(C##Name_##Definition::GetDefName()) -> parse(node); continue; }
150 #define DECLARE_NODE_PAR(Name_, name_)
151 #include "node_type.conf"
152 
153  DEBUG(<< "The element \'" << name
154  << "\' in the context \'" << CContext::getCurrent()->getId()
155  << "\' is not a definition !");
156 
157  } while (node.goToNextElement());
158 
159  node.goToParentElement(); // Retour au parent
160  }
161  }
163 
164  //----------------------------------------------------------------
167  TRY
168  {
169  StdString currentContextId = CContext::getCurrent() -> getId();
170  std::vector<CContext*> def_vector =
171  CContext::getRoot()->getChildList();
172  std::vector<CContext*>::iterator
173  it = def_vector.begin(), end = def_vector.end();
174 
175  out << "<? xml version=\"1.0\" ?>" << std::endl;
176  out << "<" << xml::CXMLNode::GetRootName() << " >" << std::endl;
177 
178  for (; it != end; it++)
179  {
180  CContext* context = *it;
181  CContext::setCurrent(context->getId());
182  out << *context << std::endl;
183  }
184 
185  out << "</" << xml::CXMLNode::GetRootName() << " >" << std::endl;
186  CContext::setCurrent(currentContextId);
187  }
188  CATCH
189 
190  //----------------------------------------------------------------
191 
194  TRY
195  {
196  StdOStringStream oss;
197  oss << "<" << CContext::GetName()
198  << " id=\"" << this->getId() << "\" "
199  << SuperClassAttribute::toString() << ">" << std::endl;
200  if (!this->hasChild())
201  {
202  //oss << "<!-- No definition -->" << std::endl; // fait planter l'incrémentation
203  }
204  else
205  {
206 
207 #define DECLARE_NODE(Name_, name_) \
208  if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
209  oss << * C##Name_##Definition::get(C##Name_##Definition::GetDefName()) << std::endl;
210 #define DECLARE_NODE_PAR(Name_, name_)
211 #include "node_type.conf"
212 
213  }
214  oss << "</" << CContext::GetName() << " >";
215  return (oss.str());
216  }
217  CATCH
218 
219  //----------------------------------------------------------------
220 
227  void CContext::solveDescInheritance(bool apply, const CAttributeMap * const UNUSED(parent))
228  TRY
229  {
230 #define DECLARE_NODE(Name_, name_) \
231  if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
232  C##Name_##Definition::get(C##Name_##Definition::GetDefName())->solveDescInheritance(apply);
233 #define DECLARE_NODE_PAR(Name_, name_)
234 #include "node_type.conf"
235  }
237 
238  //----------------------------------------------------------------
239 
241  bool CContext::hasChild(void) const
242  TRY
243  {
244  return (
245 #define DECLARE_NODE(Name_, name_) \
246  C##Name_##Definition::has(C##Name_##Definition::GetDefName()) ||
247 #define DECLARE_NODE_PAR(Name_, name_)
248 #include "node_type.conf"
249  false);
250 }
251  CATCH
252 
253  //----------------------------------------------------------------
254 
256  TRY
257  {
258 #define DECLARE_NODE(Name_, name_) C##Name_##Definition::ClearAllAttributes();
259 #define DECLARE_NODE_PAR(Name_, name_)
260 #include "node_type.conf"
261  }
262  CATCH
263 
265 
267  void CContext::initClient(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtServer /*= 0*/)
268  TRY
269  {
270 
271  hasClient = true;
272  MPI_Comm intraCommServer, interCommServer;
273 
274 
275  if (CServer::serverLevel != 1)
276  // initClient is called by client
277  {
278  client = new CContextClient(this, intraComm, interComm, cxtServer);
279  if (cxtServer) // Attached mode
280  {
281  intraCommServer = intraComm;
282  interCommServer = interComm;
283  }
284  else
285  {
286  MPI_Comm_dup(intraComm, &intraCommServer);
287  comms.push_back(intraCommServer);
288  MPI_Comm_dup(interComm, &interCommServer);
289  comms.push_back(interCommServer);
290  }
291 /* for registry take the id of client context */
292 /* for servers, supress the _server_ from id */
293  string contextRegistryId=getId() ;
294  size_t pos=contextRegistryId.find("_server_") ;
295  if (pos!=std::string::npos) contextRegistryId=contextRegistryId.substr(0,pos) ;
296 
297  registryIn=new CRegistry(intraComm);
298  registryIn->setPath(contextRegistryId) ;
299  if (client->clientRank==0) registryIn->fromFile("xios_registry.bin") ;
300  registryIn->bcastRegistry() ;
301  registryOut=new CRegistry(intraComm) ;
302 
303  registryOut->setPath(contextRegistryId) ;
304 
305  server = new CContextServer(this, intraCommServer, interCommServer);
306  }
307  else
308  // initClient is called by primary server
309  {
310  clientPrimServer.push_back(new CContextClient(this, intraComm, interComm));
311  MPI_Comm_dup(intraComm, &intraCommServer);
312  comms.push_back(intraCommServer);
313  MPI_Comm_dup(interComm, &interCommServer);
314  comms.push_back(interCommServer);
315  serverPrimServer.push_back(new CContextServer(this, intraCommServer, interCommServer));
316  }
317  }
319 
326  void CContext::setClientServerBuffer(CContextClient* contextClient, bool bufferForWriting)
327  TRY
328  {
329  // Estimated minimum event size for small events (10 is an arbitrary constant just for safety)
330  const size_t minEventSize = CEventClient::headerSize + getIdServer().size() + 10 * sizeof(int);
331 
332  // Ensure there is at least some room for 20 of such events in the buffers
333  size_t minBufferSize = std::max(CXios::minBufferSize, 20 * minEventSize);
334 
335 #define DECLARE_NODE(Name_, name_) \
336  if (minBufferSize < sizeof(C##Name_##Definition)) minBufferSize = sizeof(C##Name_##Definition);
337 #define DECLARE_NODE_PAR(Name_, name_)
338 #include "node_type.conf"
339 #undef DECLARE_NODE
340 #undef DECLARE_NODE_PAR
341 
342  // Compute the buffer sizes needed to send the attributes and data corresponding to fields
343  std::map<int, StdSize> maxEventSize;
344  std::map<int, StdSize> bufferSize = getAttributesBufferSize(maxEventSize, contextClient, bufferForWriting);
345  std::map<int, StdSize> dataBufferSize = getDataBufferSize(maxEventSize, contextClient, bufferForWriting);
346 
347  std::map<int, StdSize>::iterator it, ite = dataBufferSize.end();
348  for (it = dataBufferSize.begin(); it != ite; ++it)
349  if (it->second > bufferSize[it->first]) bufferSize[it->first] = it->second;
350 
351  // Apply the buffer size factor, check that we are above the minimum buffer size and below the maximum size
352  ite = bufferSize.end();
353  for (it = bufferSize.begin(); it != ite; ++it)
354  {
355  it->second *= CXios::bufferSizeFactor;
356  if (it->second < minBufferSize) it->second = minBufferSize;
357  if (it->second > CXios::maxBufferSize) it->second = CXios::maxBufferSize;
358  }
359 
360  // Leaders will have to send some control events so ensure there is some room for those in the buffers
361  if (contextClient->isServerLeader())
362  {
363  const std::list<int>& ranks = contextClient->getRanksServerLeader();
364  for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
365  {
366  if (!bufferSize.count(*itRank))
367  {
368  bufferSize[*itRank] = minBufferSize;
369  maxEventSize[*itRank] = minEventSize;
370  }
371  }
372  }
373  contextClient->setBufferSize(bufferSize, maxEventSize);
374  }
376 
379  TRY
380  {
381  return hasClient;
382  }
384 
385  void CContext::initServer(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtClient /*= 0*/)
386  TRY
387  {
388  hasServer=true;
389  server = new CContextServer(this,intraComm,interComm);
390 
391 /* for registry take the id of client context */
392 /* for servers, supress the _server_ from id */
393  string contextRegistryId=getId() ;
394  size_t pos=contextRegistryId.find("_server_") ;
395  if (pos!=std::string::npos) contextRegistryId=contextRegistryId.substr(0,pos) ;
396 
397  registryIn=new CRegistry(intraComm);
398  registryIn->setPath(contextRegistryId) ;
399  if (server->intraCommRank==0) registryIn->fromFile("xios_registry.bin") ;
400  registryIn->bcastRegistry() ;
401  registryOut=new CRegistry(intraComm) ;
402  registryOut->setPath(contextRegistryId) ;
403 
404  MPI_Comm intraCommClient, interCommClient;
405  if (cxtClient) // Attached mode
406  {
407  intraCommClient = intraComm;
408  interCommClient = interComm;
409  }
410  else
411  {
412  MPI_Comm_dup(intraComm, &intraCommClient);
413  comms.push_back(intraCommClient);
414  MPI_Comm_dup(interComm, &interCommClient);
415  comms.push_back(interCommClient);
416  }
417  client = new CContextClient(this,intraCommClient,interCommClient, cxtClient);
418  }
420 
422  bool CContext::checkBuffersAndListen(bool enableEventsProcessing /*= true*/)
423  TRY
424  {
425  bool clientReady, serverFinished;
426 
427  // Only classical servers are non-blocking
428  if (CServer::serverLevel == 0)
429  {
430  client->checkBuffers();
431  bool hasTmpBufferedEvent = client->hasTemporarilyBufferedEvent();
432  if (hasTmpBufferedEvent)
433  hasTmpBufferedEvent = !client->sendTemporarilyBufferedEvent();
434  // Don't process events if there is a temporarily buffered event
435  return server->eventLoop(!hasTmpBufferedEvent || !enableEventsProcessing);
436  }
437  else if (CServer::serverLevel == 1)
438  {
439  if (!finalized)
440  client->checkBuffers();
441  bool serverFinished = true;
442  if (!finalized)
443  serverFinished = server->eventLoop(enableEventsProcessing);
444  bool serverPrimFinished = true;
445  for (int i = 0; i < clientPrimServer.size(); ++i)
446  {
447  if (!finalized)
448  clientPrimServer[i]->checkBuffers();
449  if (!finalized)
450  serverPrimFinished *= serverPrimServer[i]->eventLoop(enableEventsProcessing);
451  }
452  return ( serverFinished && serverPrimFinished);
453  }
454 
455  else if (CServer::serverLevel == 2)
456  {
457  client->checkBuffers();
458  return server->eventLoop(enableEventsProcessing);
459  }
460  }
462 
465  TRY
466  {
467  if (hasClient && !hasServer) // For now we only use server level 1 to read data
468  {
470  }
471  // Send registry upon calling the function the first time
472  if (countChildCtx_ == 0)
473  if (hasClient) sendRegistry() ;
474 
475  // Client:
476  // (1) blocking send context finalize to its server
477  // (2) blocking receive context finalize from its server
478  // (3) some memory deallocations
479  if (CXios::isClient)
480  {
481  // Make sure that client (model) enters the loop only once
482  if (countChildCtx_ < 1)
483  {
484  ++countChildCtx_;
485 
486  client->finalize();
487  while (client->havePendingRequests())
488  client->checkBuffers();
489 
490  while (!server->hasFinished())
491  server->eventLoop();
492 
493  if (hasServer) // Mode attache
494  {
495  closeAllFile();
498  }
499 
502 
504  for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it)
505  MPI_Comm_free(&(*it));
506  comms.clear();
507 
508  info(20)<<"CContext: Context <"<<getId()<<"> is finalized."<<endl;
509  }
510  }
511  else if (CXios::isServer)
512  {
513  // First context finalize message received from a model
514  // Send context finalize to its child contexts (if any)
515  if (countChildCtx_ == 0)
516  for (int i = 0; i < clientPrimServer.size(); ++i)
518 
519  // (Last) context finalized message received
520  if (countChildCtx_ == clientPrimServer.size())
521  {
522  // Blocking send of context finalize message to its client (e.g. primary server or model)
523  info(100)<<"DEBUG: context "<<getId()<<" Send client finalize<<"<<endl ;
524  client->finalize();
525  bool bufferReleased;
526  do
527  {
528  client->checkBuffers();
529  bufferReleased = !client->havePendingRequests();
530  } while (!bufferReleased);
531  finalized = true;
532 
533  closeAllFile(); // Just move to here to make sure that server-level 1 can close files
534  if (hasServer && !hasClient)
535  {
538  }
539 
542  for (int i = 0; i < clientPrimServer.size(); ++i)
543  clientPrimServer[i]->releaseBuffers();
544 
546  for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it)
547  MPI_Comm_free(&(*it));
548  comms.clear();
549 
550  info(20)<<"CContext: Context <"<<getId()<<"> is finalized."<<endl;
551  }
552 
553  ++countChildCtx_;
554  }
555  }
557 
560  TRY
561  {
562  for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it)
563  MPI_Comm_free(&(*it));
564  comms.clear();
565  }
567 
570  TRY
571  {
573  for (int i = 0; i < clientPrimServer.size(); ++i)
574  clientPrimServer[i]->releaseBuffers();
575  }
577 
579  TRY
580  {
581  if (allProcessed) return;
582 
583  // After xml is parsed, there are some more works with post processing
584  postProcessing();
585 
586  // Check grid and calculate its distribution
588 
589  // Distribute files between secondary servers according to the data size
590  distributeFiles();
591 
593  for (int i = 0; i < clientPrimServer.size(); ++i)
595 
596  if (hasClient)
597  {
598  // Send all attributes of current context to server
600 
601  // Send all attributes of current calendar
603 
604  // We have enough information to send to server
605  // First of all, send all enabled files
607  // We only use server-level 1 (for now) to read data
608  if (!hasServer)
610 
611  // Then, send all enabled fields
613  if (!hasServer)
615 
616  // Then, check whether we have domain_ref, axis_ref or scalar_ref attached to the enabled fields
617  // If any, so send them to server
619  if (!hasServer)
621 
622  // Check whether enabled fields have grid_ref, if any, send this info to server
623  sendRefGrid(this->enabledFiles);
624  // This code may be useful in the future when we want to seperate completely read and write
625  // sendRefGrid(this->enabledWriteModeFiles);
626  // if (!hasServer)
627  // sendRefGrid(this->enabledReadModeFiles);
628 
629  // A grid of enabled fields composed of several components which must be checked then their
630  // checked attributes should be sent to server
631  sendGridComponentEnabledFieldsInFiles(this->enabledFiles); // This code can be seperated in two (one for reading, another for writing)
632 
633  // We have a xml tree on the server side and now, it should be also processed
635 
636  // Finally, we send information of grid itself to server
638  if (!hasServer)
640  }
641  allProcessed = true;
642  }
644 
646  TRY
647  {
648  // Use correct context client to send message
649  // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
650  int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
651  for (int i = 0; i < nbSrvPools; ++i)
652  {
653  CContextClient* contextClientTmp = (0 != clientPrimServer.size()) ? clientPrimServer[i] : client;
655 
656  if (contextClientTmp->isServerLeader())
657  {
658  CMessage msg;
659  if (hasServer)
660  msg<<this->getIdServer(i);
661  else
662  msg<<this->getIdServer();
663  const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
664  for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
665  event.push(*itRank,1,msg);
666  contextClientTmp->sendEvent(event);
667  }
668  else contextClientTmp->sendEvent(event);
669  }
670  }
672 
674  TRY
675  {
676  CBufferIn* buffer=event.subEvents.begin()->buffer;
677  string id;
678  *buffer>>id;
679  get(id)->recvPostProcessingGlobalAttributes(*buffer);
680  }
681  CATCH
682 
684  TRY
685  {
686  postProcessingGlobalAttributes();
687  }
689 
701  TRY
702  {
703  CTimer::get("Context : close definition").resume() ;
705 
707 
708  // There are some processings that should be done after all of above. For example: check mask or index
710 
711  if (hasClient && !hasServer)
712  {
715  }
716 
718 
720  if (hasClient) this->sendCloseDefinition();
721 
722  // Nettoyage de l'arborescence
723  if (hasClient) CleanTree(); // Only on client side??
724 
725  if (hasClient)
726  {
729  }
730  CTimer::get("Context : close definition").suspend() ;
731  }
733 
734  void CContext::findAllEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)
735  TRY
736  {
737  for (unsigned int i = 0; i < activeFiles.size(); i++)
738  (void)activeFiles[i]->getEnabledFields();
739  }
741 
743  TRY
744  {
745  for (unsigned int i = 0; i < this->enabledReadModeFiles.size(); ++i)
746  (void)this->enabledReadModeFiles[i]->readAttributesOfEnabledFieldsInReadMode();
747  }
749 
750  void CContext::sendGridComponentEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)
751  TRY
752  {
753  int size = activeFiles.size();
754  for (int i = 0; i < size; ++i)
755  {
756  activeFiles[i]->sendGridComponentOfEnabledFields();
757  }
758  }
760 
765  void CContext::sendGridEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)
766  TRY
767  {
768  int size = activeFiles.size();
769  for (int i = 0; i < size; ++i)
770  {
771  activeFiles[i]->sendGridOfEnabledFields();
772  }
773  }
775 
777  TRY
778  {
779  int size = enabledFiles.size();
780  for (int i = 0; i < size; ++i)
781  {
782  enabledFiles[i]->checkGridOfEnabledFields();
783  }
784  }
786 
791  void CContext::checkGridEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)
792  TRY
793  {
794  int size = activeFiles.size();
795  for (int i = 0; i < size; ++i)
796  {
797  activeFiles[i]->checkGridOfEnabledFields();
798  }
799  }
801 
808  TRY
809  {
810  int size = this->enabledFiles.size();
811  for (int i = 0; i < size; ++i)
812  {
813  this->enabledFiles[i]->solveOnlyRefOfEnabledFields(sendToServer);
814  }
815 
816  for (int i = 0; i < size; ++i)
817  {
818  this->enabledFiles[i]->generateNewTransformationGridDest();
819  }
820  }
822 
830  TRY
831  {
832  int size = this->enabledFiles.size();
833  for (int i = 0; i < size; ++i)
834  {
835  this->enabledFiles[i]->solveAllRefOfEnabledFieldsAndTransform(sendToServer);
836  }
837  }
839 
841  TRY
842  {
843  int size = this->enabledFiles.size();
844  for (int i = 0; i < size; ++i)
845  {
846  this->enabledFiles[i]->buildFilterGraphOfEnabledFields(garbageCollector);
847  }
848  }
850 
852  TRY
853  {
854  int size = enabledFiles.size();
855  for (int i = 0; i < size; ++i)
856  {
857  enabledFiles[i]->postProcessFilterGraph();
858  }
859  }
861 
863  TRY
864  {
865  int size = enabledReadModeFiles.size();
866  for (int i = 0; i < size; ++i)
867  {
868  enabledReadModeFiles[i]->prefetchEnabledReadModeFields();
869  }
870  }
872 
874  TRY
875  {
876  int size = enabledReadModeFiles.size();
877  for (int i = 0; i < size; ++i)
878  {
879  enabledReadModeFiles[i]->doPreTimestepOperationsForEnabledReadModeFields();
880  }
881  }
883 
885  TRY
886  {
887  int size = enabledReadModeFiles.size();
888  for (int i = 0; i < size; ++i)
889  {
890  enabledReadModeFiles[i]->doPostTimestepOperationsForEnabledReadModeFields();
891  }
892  }
894 
896  TRY
897  {
898  fieldsWithReadAccess.clear();
899  const vector<CField*> allFields = CField::getAll();
900  for (size_t i = 0; i < allFields.size(); ++i)
901  {
902  CField* field = allFields[i];
903 
904  if (field->file && !field->file->mode.isEmpty() && field->file->mode == CFile::mode_attr::read)
905  field->read_access = true;
906  else if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled))
907  fieldsWithReadAccess.push_back(field);
908  }
909  }
911 
913  TRY
914  {
915  for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
916  fieldsWithReadAccess[i]->solveAllReferenceEnabledField(false);
917  }
919 
921  TRY
922  {
923  for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
924  fieldsWithReadAccess[i]->buildFilterGraph(garbageCollector, true);
925  }
927 
929  TRY
930  {
931  // Résolution des héritages descendants (càd des héritages de groupes)
932  // pour chacun des contextes.
933  solveDescInheritance(apply);
934 
935  // Résolution des héritages par référence au niveau des fichiers.
936  const vector<CFile*> allFiles=CFile::getAll();
937  const vector<CGrid*> allGrids= CGrid::getAll();
938 
939  if (hasClient && !hasServer)
940  //if (hasClient)
941  {
942  for (unsigned int i = 0; i < allFiles.size(); i++)
943  allFiles[i]->solveFieldRefInheritance(apply);
944  }
945 
946  unsigned int vecSize = allGrids.size();
947  unsigned int i = 0;
948  for (i = 0; i < vecSize; ++i)
949  allGrids[i]->solveDomainAxisRefInheritance(apply);
950 
951  }
953 
955  TRY
956  {
957  const std::vector<CFile*> allFiles = CFile::getAll();
958  const CDate& initDate = calendar->getInitDate();
959 
960  for (unsigned int i = 0; i < allFiles.size(); i++)
961  if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
962  {
963  if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
964  {
965  if (allFiles[i]->output_freq.isEmpty())
966  {
967  ERROR("CContext::findEnabledFiles()",
968  << "Mandatory attribute output_freq must be defined for file \""<<allFiles[i]->getFileOutputName()
969  <<" \".")
970  }
971  if ((initDate + allFiles[i]->output_freq.getValue()) < (initDate + this->getCalendar()->getTimeStep()))
972  {
973  error(0)<<"WARNING: void CContext::findEnabledFiles()"<<endl
974  << "Output frequency in file \""<<allFiles[i]->getFileOutputName()
975  <<"\" is less than the time step. File will not be written."<<endl;
976  }
977  else
978  enabledFiles.push_back(allFiles[i]);
979  }
980  }
981  else
982  {
983  if (allFiles[i]->output_freq.isEmpty())
984  {
985  ERROR("CContext::findEnabledFiles()",
986  << "Mandatory attribute output_freq must be defined for file \""<<allFiles[i]->getFileOutputName()
987  <<" \".")
988  }
989  if ( (initDate + allFiles[i]->output_freq.getValue()) < (initDate + this->getCalendar()->getTimeStep()))
990  {
991  error(0)<<"WARNING: void CContext::findEnabledFiles()"<<endl
992  << "Output frequency in file \""<<allFiles[i]->getFileOutputName()
993  <<"\" is less than the time step. File will not be written."<<endl;
994  }
995  else
996  enabledFiles.push_back(allFiles[i]); // otherwise true by default
997  }
998 
999  if (enabledFiles.size() == 0)
1000  DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
1001  << getId() << "\" !");
1002 
1003  }
1005 
1007  TRY
1008  {
1009  bool distFileMemory=false ;
1010  distFileMemory=CXios::getin<bool>("server2_dist_file_memory", distFileMemory);
1011 
1012  if (distFileMemory) distributeFileOverMemoryBandwith() ;
1014  }
1016 
1018  TRY
1019  {
1020  double eps=std::numeric_limits<double>::epsilon()*10 ;
1021 
1022  // If primary server
1023  if (hasServer && hasClient)
1024  {
1025  std::ofstream ofs(("distribute_file_"+getId()+".dat").c_str(), std::ofstream::out);
1026  int nbPools = clientPrimServer.size();
1027 
1028  // (1) Find all enabled files in write mode
1029  // for (int i = 0; i < this->enabledFiles.size(); ++i)
1030  // {
1031  // if (enabledFiles[i]->mode.isEmpty() || (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write ))
1032  // enabledWriteModeFiles.push_back(enabledFiles[i]);
1033  // }
1034 
1035  // (2) Estimate the data volume for each file
1036  int size = this->enabledWriteModeFiles.size();
1037  std::vector<std::pair<double, CFile*> > dataSizeMap;
1038  double dataPerPool = 0;
1039  int nfield=0 ;
1040  ofs<<size<<endl ;
1041  for (size_t i = 0; i < size; ++i)
1042  {
1043  CFile* file = this->enabledWriteModeFiles[i];
1044  ofs<<file->getId()<<endl ;
1045  StdSize dataSize=0;
1046  std::vector<CField*> enabledFields = file->getEnabledFields();
1047  size_t numEnabledFields = enabledFields.size();
1048  ofs<<numEnabledFields<<endl ;
1049  for (size_t j = 0; j < numEnabledFields; ++j)
1050  {
1051  dataSize += enabledFields[j]->getGlobalWrittenSize() ;
1052  ofs<<enabledFields[j]->grid->getId()<<endl ;
1053  ofs<<enabledFields[j]->getGlobalWrittenSize()<<endl ;
1054  }
1055  double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ;
1056  double dataSizeSec= dataSize/ outFreqSec;
1057  ofs<<dataSizeSec<<endl ;
1058  nfield++ ;
1059 // add epsilon*nField to dataSizeSec in order to preserve reproductive ordering when sorting
1060  dataSizeMap.push_back(make_pair(dataSizeSec + dataSizeSec * eps * nfield , file));
1061  dataPerPool += dataSizeSec;
1062  }
1063  dataPerPool /= nbPools;
1064  std::sort(dataSizeMap.begin(), dataSizeMap.end());
1065 
1066  // (3) Assign contextClient to each enabled file
1067 
1068  std::multimap<double,int> poolDataSize ;
1069 // multimap is not garanty to preserve stable sorting in c++98 but it seems it does for c++11
1070 
1071  int j;
1072  double dataSize ;
1073  for (j = 0 ; j < nbPools ; ++j) poolDataSize.insert(std::pair<double,int>(0.,j)) ;
1074 
1075  for (int i = dataSizeMap.size()-1; i >= 0; --i)
1076  {
1077  dataSize=(*poolDataSize.begin()).first ;
1078  j=(*poolDataSize.begin()).second ;
1079  dataSizeMap[i].second->setContextClient(clientPrimServer[j]);
1080  dataSize+=dataSizeMap[i].first;
1081  poolDataSize.erase(poolDataSize.begin()) ;
1082  poolDataSize.insert(std::pair<double,int>(dataSize,j)) ;
1083  }
1084 
1085  for (std::multimap<double,int>:: iterator it=poolDataSize.begin() ; it!=poolDataSize.end(); ++it) info(30)<<"Load Balancing for servers (perfect=1) : "<<it->second<<" : ratio "<<it->first*1./dataPerPool<<endl ;
1086 
1087  for (int i = 0; i < this->enabledReadModeFiles.size(); ++i)
1088  {
1089  enabledReadModeFiles[i]->setContextClient(client);
1090  }
1091  }
1092  else
1093  {
1094  for (int i = 0; i < this->enabledFiles.size(); ++i)
1095  enabledFiles[i]->setContextClient(client);
1096  }
1097  }
1099 
1101  TRY
1102  {
1103  // If primary server
1104  if (hasServer && hasClient)
1105  {
1106  int nbPools = clientPrimServer.size();
1107  double ratio=0.5 ;
1108  ratio=CXios::getin<double>("server2_dist_file_memory_ratio", ratio);
1109 
1110  int nFiles = this->enabledWriteModeFiles.size();
1111  vector<SDistFile> files(nFiles);
1112  vector<SDistGrid> grids;
1113  map<string,int> gridMap ;
1114  string gridId;
1115  int gridIndex=0 ;
1116 
1117  for (size_t i = 0; i < nFiles; ++i)
1118  {
1119  StdSize dataSize=0;
1120  CFile* file = this->enabledWriteModeFiles[i];
1121  std::vector<CField*> enabledFields = file->getEnabledFields();
1122  size_t numEnabledFields = enabledFields.size();
1123 
1124  files[i].id_=file->getId() ;
1125  files[i].nbGrids_=numEnabledFields;
1126  files[i].assignedGrid_ = new int[files[i].nbGrids_] ;
1127 
1128  for (size_t j = 0; j < numEnabledFields; ++j)
1129  {
1130  gridId=enabledFields[j]->grid->getId() ;
1131  if (gridMap.find(gridId)==gridMap.end())
1132  {
1133  gridMap[gridId]=gridIndex ;
1134  SDistGrid newGrid;
1135  grids.push_back(newGrid) ;
1136  gridIndex++ ;
1137  }
1138  files[i].assignedGrid_[j]=gridMap[gridId] ;
1139  grids[files[i].assignedGrid_[j]].size_=enabledFields[j]->getGlobalWrittenSize() ;
1140  dataSize += enabledFields[j]->getGlobalWrittenSize() ; // usefull
1141  }
1142  double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ;
1143  files[i].bandwith_= dataSize/ outFreqSec ;
1144  }
1145 
1146  double bandwith=0 ;
1147  double memory=0 ;
1148 
1149  for(int i=0; i<nFiles; i++) bandwith+=files[i].bandwith_ ;
1150  for(int i=0; i<nFiles; i++) files[i].bandwith_ = files[i].bandwith_/bandwith * ratio ;
1151 
1152  for(int i=0; i<grids.size(); i++) memory+=grids[i].size_ ;
1153  for(int i=0; i<grids.size(); i++) grids[i].size_ = grids[i].size_ / memory * (1.0-ratio) ;
1154 
1155  distributeFileOverServer2(nbPools, grids.size(), &grids[0], nFiles, &files[0]) ;
1156 
1157  vector<double> memorySize(nbPools,0.) ;
1158  vector< set<int> > serverGrids(nbPools) ;
1159  vector<double> bandwithSize(nbPools,0.) ;
1160 
1161  for (size_t i = 0; i < nFiles; ++i)
1162  {
1163  bandwithSize[files[i].assignedServer_] += files[i].bandwith_* bandwith /ratio ;
1164  for(int j=0 ; j<files[i].nbGrids_;j++)
1165  {
1166  if (serverGrids[files[i].assignedServer_].find(files[i].assignedGrid_[j]) == serverGrids[files[i].assignedServer_].end())
1167  {
1168  memorySize[files[i].assignedServer_]+= grids[files[i].assignedGrid_[j]].size_ * memory / (1.0-ratio);
1169  serverGrids[files[i].assignedServer_].insert(files[i].assignedGrid_[j]) ;
1170  }
1171  }
1172  enabledWriteModeFiles[i]->setContextClient(clientPrimServer[files[i].assignedServer_]) ;
1173  delete [] files[i].assignedGrid_ ;
1174  }
1175 
1176  for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<" assigned file bandwith "<<bandwithSize[i]*86400.*4./1024/1024.<<" Mb / days"<<endl ;
1177  for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<" assigned grid memory "<<memorySize[i]*100/1024./1024.<<" Mb"<<endl ;
1178 
1179 
1180  for (int i = 0; i < this->enabledReadModeFiles.size(); ++i)
1181  {
1182  enabledReadModeFiles[i]->setContextClient(client);
1183  }
1184 
1185  }
1186  else
1187  {
1188  for (int i = 0; i < this->enabledFiles.size(); ++i)
1189  enabledFiles[i]->setContextClient(client);
1190  }
1191 }
1193 
1198  TRY
1199  {
1200  int size = this->enabledFiles.size();
1201  for (int i = 0; i < size; ++i)
1202  {
1203  if (enabledFiles[i]->mode.isEmpty() ||
1204  (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write ))
1205  enabledWriteModeFiles.push_back(enabledFiles[i]);
1206  }
1207  }
1209 
1214  TRY
1215  {
1216  int size = this->enabledFiles.size();
1217  for (int i = 0; i < size; ++i)
1218  {
1219  if (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::read)
1220  enabledReadModeFiles.push_back(enabledFiles[i]);
1221  }
1222  }
1224 
1226  TRY
1227  {
1228  std::vector<CFile*>::const_iterator
1229  it = this->enabledFiles.begin(), end = this->enabledFiles.end();
1230 
1231  for (; it != end; it++)
1232  {
1233  info(30)<<"Closing File : "<<(*it)->getId()<<endl;
1234  (*it)->close();
1235  }
1236  }
1238 
1247  TRY
1248  {
1249 
1250  if (SuperClass::dispatchEvent(event)) return true;
1251  else
1252  {
1253  switch(event.type)
1254  {
1255  case EVENT_ID_CLOSE_DEFINITION :
1256  recvCloseDefinition(event);
1257  return true;
1258  break;
1259  case EVENT_ID_UPDATE_CALENDAR:
1260  recvUpdateCalendar(event);
1261  return true;
1262  break;
1263  case EVENT_ID_CREATE_FILE_HEADER :
1264  recvCreateFileHeader(event);
1265  return true;
1266  break;
1267  case EVENT_ID_POST_PROCESS:
1268  recvPostProcessing(event);
1269  return true;
1270  case EVENT_ID_SEND_REGISTRY:
1271  recvRegistry(event);
1272  return true;
1273  break;
1274  case EVENT_ID_POST_PROCESS_GLOBAL_ATTRIBUTES:
1275  recvPostProcessingGlobalAttributes(event);
1276  return true;
1277  break;
1278  case EVENT_ID_PROCESS_GRID_ENABLED_FIELDS:
1279  recvProcessingGridOfEnabledFields(event);
1280  return true;
1281  break;
1282  default :
1283  ERROR("bool CContext::dispatchEvent(CEventServer& event)",
1284  <<"Unknown Event");
1285  return false;
1286  }
1287  }
1288  }
1289  CATCH
1290 
1293  TRY
1294  {
1295  // Use correct context client to send message
1296  int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
1297  for (int i = 0; i < nbSrvPools; ++i)
1298  {
1299  CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
1301  if (contextClientTmp->isServerLeader())
1302  {
1303  CMessage msg;
1304  if (hasServer)
1305  msg<<this->getIdServer(i);
1306  else
1307  msg<<this->getIdServer();
1308  const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1309  for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1310  event.push(*itRank,1,msg);
1311  contextClientTmp->sendEvent(event);
1312  }
1313  else contextClientTmp->sendEvent(event);
1314  }
1315  }
1317 
1320  TRY
1321  {
1322  CBufferIn* buffer=event.subEvents.begin()->buffer;
1323  string id;
1324  *buffer>>id;
1325  get(id)->closeDefinition();
1326  }
1327  CATCH
1328 
1331  TRY
1332  {
1333  // Use correct context client to send message
1334  int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
1335  for (int i = 0; i < nbSrvPools; ++i)
1336  {
1337  CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
1338  CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR);
1339 
1340  if (contextClientTmp->isServerLeader())
1341  {
1342  CMessage msg;
1343  if (hasServer)
1344  msg<<this->getIdServer(i)<<step;
1345  else
1346  msg<<this->getIdServer()<<step;
1347  const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1348  for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1349  event.push(*itRank,1,msg);
1350  contextClientTmp->sendEvent(event);
1351  }
1352  else contextClientTmp->sendEvent(event);
1353  }
1354  }
1356 
1359  TRY
1360  {
1361  CBufferIn* buffer=event.subEvents.begin()->buffer;
1362  string id;
1363  *buffer>>id;
1364  get(id)->recvUpdateCalendar(*buffer);
1365  }
1366  CATCH
1367 
1370  TRY
1371  {
1372  int step;
1373  buffer>>step;
1374  updateCalendar(step);
1375  if (hasClient && hasServer)
1376  {
1377  sendUpdateCalendar(step);
1378  }
1379  }
1381 
1384  TRY
1385  {
1386  // Use correct context client to send message
1387  // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
1388  int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
1389  for (int i = 0; i < nbSrvPools; ++i)
1390  {
1391  CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
1393 
1394  if (contextClientTmp->isServerLeader())
1395  {
1396  CMessage msg;
1397  if (hasServer)
1398  msg<<this->getIdServer(i);
1399  else
1400  msg<<this->getIdServer();
1401  const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1402  for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1403  event.push(*itRank,1,msg) ;
1404  contextClientTmp->sendEvent(event);
1405  }
1406  else contextClientTmp->sendEvent(event);
1407  }
1408  }
1410 
1413  TRY
1414  {
1415  CBufferIn* buffer=event.subEvents.begin()->buffer;
1416  string id;
1417  *buffer>>id;
1418  get(id)->recvCreateFileHeader(*buffer);
1419  }
1420  CATCH
1421 
1424  TRY
1425  {
1426  if (!hasClient && hasServer)
1427  createFileHeader();
1428  }
1430 
1433  TRY
1434  {
1435  // Use correct context client to send message
1436  int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
1437  for (int i = 0; i < nbSrvPools; ++i)
1438  {
1439  CContextClient* contextClientTmp = (0 != clientPrimServer.size()) ? clientPrimServer[i] : client;
1441 
1442  if (contextClientTmp->isServerLeader())
1443  {
1444  CMessage msg;
1445  if (hasServer)
1446  msg<<this->getIdServer(i);
1447  else
1448  msg<<this->getIdServer();
1449  const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1450  for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1451  event.push(*itRank,1,msg);
1452  contextClientTmp->sendEvent(event);
1453  }
1454  else contextClientTmp->sendEvent(event);
1455  }
1456  }
1458 
1461  TRY
1462  {
1463  CBufferIn* buffer=event.subEvents.begin()->buffer;
1464  string id;
1465  *buffer>>id;
1466  }
1467  CATCH
1468 
1471  TRY
1472  {
1473  // Use correct context client to send message
1474  // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
1475  int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
1476  for (int i = 0; i < nbSrvPools; ++i)
1477  {
1478  CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
1480  if (contextClientTmp->isServerLeader())
1481  {
1482  CMessage msg;
1483  if (hasServer)
1484  msg<<this->getIdServer(i);
1485  else
1486  msg<<this->getIdServer();
1487  const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1488  for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1489  event.push(*itRank,1,msg);
1490  contextClientTmp->sendEvent(event);
1491  }
1492  else contextClientTmp->sendEvent(event);
1493  }
1494  }
1496 
1499  TRY
1500  {
1501  CBufferIn* buffer=event.subEvents.begin()->buffer;
1502  string id;
1503  *buffer>>id;
1504  get(id)->recvPostProcessing(*buffer);
1505  }
1506  CATCH
1507 
1510  TRY
1511  {
1513  postProcessing();
1514  }
1516 
1518  TRY
1519  {
1520  if (hasClient)
1521  {
1522  idServer_ = this->getId();
1523  idServer_ += "_server";
1524  return idServer_;
1525  }
1526  if (hasServer) return (this->getId());
1527  }
1529 
1530  const StdString& CContext::getIdServer(const int i)
1531  TRY
1532  {
1533  idServer_ = this->getId();
1534  idServer_ += "_server_";
1535  idServer_ += std::to_string(static_cast<unsigned long long>(i));
1536  return idServer_;
1537  }
1539 
1547  TRY
1548  {
1549  if (isPostProcessed) return;
1550 
1551  // Make sure the calendar was correctly created
1552  if (!calendar)
1553  ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"")
1554  else if (calendar->getTimeStep() == NoneDu)
1555  ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"")
1556  // Calendar first update to set the current date equals to the start date
1557  calendar->update(0);
1558 
1559  // Find all inheritance in xml structure
1560  this->solveAllInheritance();
1561 
1562 // ShowTree(info(10));
1563 
1564  // Check if some axis, domains or grids are eligible to for compressed indexed output.
1565  // Warning: This must be done after solving the inheritance and before the rest of post-processing
1567 
1568  // Check if some automatic time series should be generated
1569  // Warning: This must be done after solving the inheritance and before the rest of post-processing
1570 
1571  // The timeseries should only be prepared in client
1573 
1574  //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
1575  findEnabledFiles();
1578 
1579  // For now, only read files with client and only one level server
1580  // if (hasClient && !hasServer) findEnabledReadModeFiles();
1581 
1582  // Find all enabled fields of each file
1585 
1586  // For now, only read files with client and only one level server
1587  // if (hasClient && !hasServer)
1588  // findAllEnabledFieldsInFiles(this->enabledReadModeFiles);
1589 
1590  if (hasClient && !hasServer)
1591  {
1592  initReadFiles();
1593  // Try to read attributes of fields in file then fill in corresponding grid (or domain, axis)
1595  }
1596 
1597  // Only search and rebuild all reference objects of enable fields, don't transform
1598  this->solveOnlyRefOfEnabledFields(false);
1599 
1600  // Search and rebuild all reference object of enabled fields, and transform
1602 
1603  // Find all fields with read access from the public API
1605  // and solve the all reference for them
1607 
1608  isPostProcessed = true;
1609  }
1611 
1619  std::map<int, StdSize> CContext::getAttributesBufferSize(std::map<int, StdSize>& maxEventSize,
1620  CContextClient* contextClient, bool bufferForWriting /*= "false"*/)
1621  TRY
1622  {
1623  // As calendar attributes are sent even if there are no active files or fields, maps are initialized according the size of calendar attributes
1624  std::map<int, StdSize> attributesSize = CCalendarWrapper::get(CCalendarWrapper::GetDefName())->getMinimumBufferSizeForAttributes(contextClient);
1626 
1627  std::vector<CFile*>& fileList = this->enabledFiles;
1628  size_t numEnabledFiles = fileList.size();
1629  for (size_t i = 0; i < numEnabledFiles; ++i)
1630  {
1631 // CFile* file = this->enabledWriteModeFiles[i];
1632  CFile* file = fileList[i];
1633  std::vector<CField*> enabledFields = file->getEnabledFields();
1634  size_t numEnabledFields = enabledFields.size();
1635  for (size_t j = 0; j < numEnabledFields; ++j)
1636  {
1637  const std::map<int, StdSize> mapSize = enabledFields[j]->getGridAttributesBufferSize(contextClient, bufferForWriting);
1638  std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
1639  for (; it != itE; ++it)
1640  {
1641  // If attributesSize[it->first] does not exist, it will be zero-initialized
1642  // so we can use it safely without checking for its existence
1643  if (attributesSize[it->first] < it->second)
1644  attributesSize[it->first] = it->second;
1645 
1646  if (maxEventSize[it->first] < it->second)
1647  maxEventSize[it->first] = it->second;
1648  }
1649  }
1650  }
1651  return attributesSize;
1652  }
1654 
1662  std::map<int, StdSize> CContext::getDataBufferSize(std::map<int, StdSize>& maxEventSize,
1663  CContextClient* contextClient, bool bufferForWriting /*= "false"*/)
1664  TRY
1665  {
1666  std::map<int, StdSize> dataSize;
1667 
1668  // Find all reference domain and axis of all active fields
1669  std::vector<CFile*>& fileList = bufferForWriting ? this->enabledWriteModeFiles : this->enabledReadModeFiles;
1670  size_t numEnabledFiles = fileList.size();
1671  for (size_t i = 0; i < numEnabledFiles; ++i)
1672  {
1673  CFile* file = fileList[i];
1674  if (file->getContextClient() == contextClient)
1675  {
1676  std::vector<CField*> enabledFields = file->getEnabledFields();
1677  size_t numEnabledFields = enabledFields.size();
1678  for (size_t j = 0; j < numEnabledFields; ++j)
1679  {
1680  // const std::vector<std::map<int, StdSize> > mapSize = enabledFields[j]->getGridDataBufferSize(contextClient);
1681  const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataBufferSize(contextClient,bufferForWriting);
1682  std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
1683  for (; it != itE; ++it)
1684  {
1685  // If dataSize[it->first] does not exist, it will be zero-initialized
1686  // so we can use it safely without checking for its existance
1688  dataSize[it->first] += it->second;
1689  else if (dataSize[it->first] < it->second)
1690  dataSize[it->first] = it->second;
1691 
1692  if (maxEventSize[it->first] < it->second)
1693  maxEventSize[it->first] = it->second;
1694  }
1695  }
1696  }
1697  }
1698  return dataSize;
1699  }
1701 
1703  void CContext::sendEnabledFiles(const std::vector<CFile*>& activeFiles)
1704  TRY
1705  {
1706  int size = activeFiles.size();
1707 
1708  // In a context, each type has a root definition, e.g: axis, domain, field.
1709  // Every object must be a child of one of these root definition. In this case
1710  // all new file objects created on server must be children of the root "file_definition"
1711  StdString fileDefRoot("file_definition");
1712  CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
1713 
1714  for (int i = 0; i < size; ++i)
1715  {
1716  CFile* f = activeFiles[i];
1717  cfgrpPtr->sendCreateChild(f->getId(),f->getContextClient());
1720  }
1721  }
1723 
1725  void CContext::sendEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)
1726  TRY
1727  {
1728  int size = activeFiles.size();
1729  for (int i = 0; i < size; ++i)
1730  {
1731  activeFiles[i]->sendEnabledFields(activeFiles[i]->getContextClient());
1732  }
1733  }
1735 
1738  TRY
1739  {
1740  if (!hasClient) return;
1741 
1742  const vector<CAxis*> allAxis = CAxis::getAll();
1743  for (vector<CAxis*>::const_iterator it = allAxis.begin(); it != allAxis.end(); it++)
1744  (*it)->checkEligibilityForCompressedOutput();
1745 
1746  const vector<CDomain*> allDomains = CDomain::getAll();
1747  for (vector<CDomain*>::const_iterator it = allDomains.begin(); it != allDomains.end(); it++)
1748  (*it)->checkEligibilityForCompressedOutput();
1749 
1750  const vector<CGrid*> allGrids = CGrid::getAll();
1751  for (vector<CGrid*>::const_iterator it = allGrids.begin(); it != allGrids.end(); it++)
1752  (*it)->checkEligibilityForCompressedOutput();
1753  }
1755 
1758  TRY
1759  {
1760  if (!hasClient) return;
1761 
1762  const std::vector<CFile*> allFiles = CFile::getAll();
1763  for (size_t i = 0; i < allFiles.size(); i++)
1764  {
1765  CFile* file = allFiles[i];
1766 
1767  std::vector<CVariable*> fileVars, fieldVars, vars = file->getAllVariables();
1768  for (size_t k = 0; k < vars.size(); k++)
1769  {
1770  CVariable* var = vars[k];
1771 
1772  if (var->ts_target.isEmpty()
1773  || var->ts_target == CVariable::ts_target_attr::file || var->ts_target == CVariable::ts_target_attr::both)
1774  fileVars.push_back(var);
1775 
1776  if (!var->ts_target.isEmpty()
1777  && (var->ts_target == CVariable::ts_target_attr::field || var->ts_target == CVariable::ts_target_attr::both))
1778  fieldVars.push_back(var);
1779  }
1780 
1781  if (!file->timeseries.isEmpty() && file->timeseries != CFile::timeseries_attr::none)
1782  {
1783  StdString fileNameStr("%file_name%") ;
1784  StdString tsPrefix = !file->ts_prefix.isEmpty() ? file->ts_prefix : fileNameStr ;
1785 
1786  StdString fileName=file->getFileOutputName();
1787  size_t pos=tsPrefix.find(fileNameStr) ;
1788  while (pos!=std::string::npos)
1789  {
1790  tsPrefix=tsPrefix.replace(pos,fileNameStr.size(),fileName) ;
1791  pos=tsPrefix.find(fileNameStr) ;
1792  }
1793 
1794  const std::vector<CField*> allFields = file->getAllFields();
1795  for (size_t j = 0; j < allFields.size(); j++)
1796  {
1797  CField* field = allFields[j];
1798 
1799  if (!field->ts_enabled.isEmpty() && field->ts_enabled)
1800  {
1801  CFile* tsFile = CFile::create();
1802  tsFile->duplicateAttributes(file);
1803 
1804  // Add variables originating from file and targeted to timeserie file
1805  for (size_t k = 0; k < fileVars.size(); k++)
1806  tsFile->getVirtualVariableGroup()->addChild(fileVars[k]);
1807 
1808 
1809  tsFile->name = tsPrefix + "_";
1810  if (!field->name.isEmpty())
1811  tsFile->name.get() += field->name;
1812  else if (field->hasDirectFieldReference()) // We cannot use getBaseFieldReference() just yet
1813  tsFile->name.get() += field->field_ref;
1814  else
1815  tsFile->name.get() += field->getId();
1816 
1817  if (!field->ts_split_freq.isEmpty())
1818  tsFile->split_freq = field->ts_split_freq;
1819 
1820  CField* tsField = tsFile->addField();
1821  tsField->field_ref = field->getId();
1822 
1823  // Add variables originating from file and targeted to timeserie field
1824  for (size_t k = 0; k < fieldVars.size(); k++)
1825  tsField->getVirtualVariableGroup()->addChild(fieldVars[k]);
1826 
1827  vars = field->getAllVariables();
1828  for (size_t k = 0; k < vars.size(); k++)
1829  {
1830  CVariable* var = vars[k];
1831 
1832  // Add variables originating from field and targeted to timeserie field
1833  if (var->ts_target.isEmpty()
1834  || var->ts_target == CVariable::ts_target_attr::field || var->ts_target == CVariable::ts_target_attr::both)
1835  tsField->getVirtualVariableGroup()->addChild(var);
1836 
1837  // Add variables originating from field and targeted to timeserie file
1838  if (!var->ts_target.isEmpty()
1839  && (var->ts_target == CVariable::ts_target_attr::file || var->ts_target == CVariable::ts_target_attr::both))
1840  tsFile->getVirtualVariableGroup()->addChild(var);
1841  }
1842 
1843  tsFile->solveFieldRefInheritance(true);
1844 
1845  if (file->timeseries == CFile::timeseries_attr::exclusive)
1846  field->enabled = false;
1847  }
1848  }
1849 
1850  // Finally disable the original file is need be
1851  if (file->timeseries == CFile::timeseries_attr::only)
1852  file->enabled = false;
1853  }
1854  }
1855  }
1857 
1859  void CContext::sendRefGrid(const std::vector<CFile*>& activeFiles)
1860  TRY
1861  {
1862  std::set<StdString> gridIds;
1863  int sizeFile = activeFiles.size();
1864  CFile* filePtr(NULL);
1865 
1866  // Firstly, find all reference grids of all active fields
1867  for (int i = 0; i < sizeFile; ++i)
1868  {
1869  filePtr = activeFiles[i];
1870  std::vector<CField*> enabledFields = filePtr->getEnabledFields();
1871  int sizeField = enabledFields.size();
1872  for (int numField = 0; numField < sizeField; ++numField)
1873  {
1874  if (0 != enabledFields[numField]->getRelGrid())
1875  gridIds.insert(CGrid::get(enabledFields[numField]->getRelGrid())->getId());
1876  }
1877  }
1878 
1879  // Create all reference grids on server side
1880  StdString gridDefRoot("grid_definition");
1881  CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
1882  std::set<StdString>::const_iterator it, itE = gridIds.end();
1883  for (it = gridIds.begin(); it != itE; ++it)
1884  {
1885  gridPtr->sendCreateChild(*it);
1887  CGrid::get(*it)->sendAllDomains();
1888  CGrid::get(*it)->sendAllAxis();
1889  CGrid::get(*it)->sendAllScalars();
1890  }
1891  }
1893 
1895  void CContext::sendRefDomainsAxisScalars(const std::vector<CFile*>& activeFiles)
1896  TRY
1897  {
1898  std::set<StdString> domainIds, axisIds, scalarIds;
1899 
1900  // Find all reference domain and axis of all active fields
1901  int numEnabledFiles = activeFiles.size();
1902  for (int i = 0; i < numEnabledFiles; ++i)
1903  {
1904  std::vector<CField*> enabledFields = activeFiles[i]->getEnabledFields();
1905  int numEnabledFields = enabledFields.size();
1906  for (int j = 0; j < numEnabledFields; ++j)
1907  {
1908  const std::vector<StdString>& prDomAxisScalarId = enabledFields[j]->getRefDomainAxisIds();
1909  if ("" != prDomAxisScalarId[0]) domainIds.insert(prDomAxisScalarId[0]);
1910  if ("" != prDomAxisScalarId[1]) axisIds.insert(prDomAxisScalarId[1]);
1911  if ("" != prDomAxisScalarId[2]) scalarIds.insert(prDomAxisScalarId[2]);
1912  }
1913  }
1914 
1915  // Create all reference axis on server side
1916  std::set<StdString>::iterator itDom, itAxis, itScalar;
1917  std::set<StdString>::const_iterator itE;
1918 
1919  StdString scalarDefRoot("scalar_definition");
1920  CScalarGroup* scalarPtr = CScalarGroup::get(scalarDefRoot);
1921  itE = scalarIds.end();
1922  for (itScalar = scalarIds.begin(); itScalar != itE; ++itScalar)
1923  {
1924  if (!itScalar->empty())
1925  {
1926  scalarPtr->sendCreateChild(*itScalar);
1928  }
1929  }
1930 
1931  StdString axiDefRoot("axis_definition");
1932  CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
1933  itE = axisIds.end();
1934  for (itAxis = axisIds.begin(); itAxis != itE; ++itAxis)
1935  {
1936  if (!itAxis->empty())
1937  {
1938  axisPtr->sendCreateChild(*itAxis);
1940  }
1941  }
1942 
1943  // Create all reference domains on server side
1944  StdString domDefRoot("domain_definition");
1945  CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
1946  itE = domainIds.end();
1947  for (itDom = domainIds.begin(); itDom != itE; ++itDom)
1948  {
1949  if (!itDom->empty()) {
1950  domPtr->sendCreateChild(*itDom);
1952  }
1953  }
1954  }
1956 
1959  TRY
1960  {
1961  int prevStep = calendar->getStep();
1962 
1963  if (prevStep < step)
1964  {
1965  if (hasClient && !hasServer) // For now we only use server level 1 to read data
1966  {
1967  doPreTimestepOperationsForEnabledReadModeFiles();
1968  }
1969 
1970  info(50) << "updateCalendar : before : " << calendar->getCurrentDate() << endl;
1971  calendar->update(step);
1972  info(50) << "updateCalendar : after : " << calendar->getCurrentDate() << endl;
1973  #ifdef XIOS_MEMTRACK_LIGHT
1974  info(50) << " Current memory used by XIOS : "<< MemTrack::getCurrentMemorySize()*1.0/(1024*1024)<<" Mbyte, at timestep "<<step<<" of context "<<this->getId()<<endl ;
1975  #endif
1976 
1977  if (hasClient && !hasServer) // For now we only use server level 1 to read data
1978  {
1979  doPostTimestepOperationsForEnabledReadModeFiles();
1980  garbageCollector.invalidate(calendar->getCurrentDate());
1981  }
1982  }
1983  else if (prevStep == step)
1984  info(50) << "updateCalendar: already at step " << step << ", no operation done." << endl;
1985  else // if (prevStep > step)
1986  ERROR("void CContext::updateCalendar(int step)",
1987  << "Illegal calendar update: previous step was " << prevStep << ", new step " << step << "is in the past!")
1988  }
1990 
1992  TRY
1993  {
1994  vector<CFile*>::const_iterator it;
1995 
1996  for (it=enabledReadModeFiles.begin(); it != enabledReadModeFiles.end(); it++)
1997  {
1998  (*it)->initRead();
1999  }
2000  }
2002 
2005  TRY
2006  {
2007  vector<CFile*>::const_iterator it;
2008 
2009  for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
2010  // for (it=enabledWriteModeFiles.begin(); it != enabledWriteModeFiles.end(); it++)
2011  {
2012  (*it)->initWrite();
2013  }
2014  }
2016 
2019  TRY
2020  {
2021  return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get();
2022  }
2023  CATCH
2024 
2029  void CContext::setCurrent(const string& id)
2030  TRY
2031  {
2034  }
2035  CATCH
2036 
2043  TRY
2044  {
2046 
2047  bool hasctxt = CContext::has(id);
2048  CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
2049  getRoot();
2050  if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
2051 
2052 #define DECLARE_NODE(Name_, name_) \
2053  C##Name_##Definition::create(C##Name_##Definition::GetDefName());
2054 #define DECLARE_NODE_PAR(Name_, name_)
2055 #include "node_type.conf"
2056 
2057  return (context);
2058  }
2059  CATCH
2060 
2063  TRY
2064  {
2065  CBufferIn* buffer=event.subEvents.begin()->buffer;
2066  string id;
2067  *buffer>>id;
2068  get(id)->recvRegistry(*buffer);
2069  }
2070  CATCH
2071 
2073  TRY
2074  {
2075  if (server->intraCommRank==0)
2076  {
2077  CRegistry registry(server->intraComm) ;
2078  registry.fromBuffer(buffer) ;
2079  registryOut->mergeRegistry(registry) ;
2080  }
2081  }
2083 
2085  TRY
2086  {
2088 
2089  // Use correct context client to send message
2090  int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
2091  for (int i = 0; i < nbSrvPools; ++i)
2092  {
2093  CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
2095  if (contextClientTmp->isServerLeader())
2096  {
2097  CMessage msg ;
2098  if (hasServer)
2099  msg<<this->getIdServer(i);
2100  else
2101  msg<<this->getIdServer();
2102  if (contextClientTmp->clientRank==0) msg<<*registryOut ;
2103  const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
2104  for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
2105  event.push(*itRank,1,msg);
2106  contextClientTmp->sendEvent(event);
2107  }
2108  else contextClientTmp->sendEvent(event);
2109  }
2110  }
2112 
2118  TRY
2119  {
2120  return finalized;
2121  }
2125  {
2126  StdString str;
2127  str.append("enabled files=\"");
2128  int size = this->enabledFiles.size();
2129  for (int i = 0; i < size; ++i)
2130  {
2131  str.append(enabledFiles[i]->getId());
2132  str.append(" ");
2133  }
2134  str.append("\"");
2135  return str;
2136  }
2137 
2138 } // namespace xios
#define CATCH_DUMP_ATTR
Definition: exception.hpp:156
void buildFilterGraphOfEnabledFields()
Definition: context.cpp:840
static bool isClient
Check if xios is client.
Definition: cxios.hpp:39
static const size_t headerSize
void solveAllRefOfFieldsWithReadAccess()
Definition: context.cpp:912
void updateCalendar(int step)
Update calendar in each time step.
Definition: context.cpp:1958
CATCH CDomainAlgorithmReorder::CDomainAlgorithmReorder(CDomain *domainDestination, CDomain *domainSource, CReorderDomain *reorderDomain if)(domainDestination->type!=CDomain::type_attr::rectilinear)
void sendEvent(CEventClient &event)
In case of attached mode, the current context must be reset to context for client.
void sendAllAxis()
Send all attributes of axis from client to server.
Definition: grid.cpp:2669
void sendEnabledFieldsInFiles(const std::vector< CFile * > &activeFiles)
Client side: Send information of active fields (ones are written onto files)
Definition: context.cpp:1725
std::vector< CFile * > enabledFiles
Definition: context.hpp:231
const StdString getFileOutputName(void) const
Accesseurs ///.
Definition: file.cpp:54
CContext(void)
Constructeurs ///.
Definition: context.cpp:29
void sendCreateFileHeader(void)
Client side: Send a message to create header part of netcdf file.
Definition: context.cpp:1383
std::vector< CField * > getAllFields(void) const
Get all fields of a file.
Definition: file.cpp:117
void freeComms(void)
Free internally allcoated communicators.
Definition: context.cpp:559
const StdString & getIdServer()
Definition: context.cpp:1517
std::vector< CVariable * > getAllVariables(void) const
Get all variables of a file.
Definition: file.cpp:125
void sendRefGrid(const std::vector< CFile * > &activeFiles)
Client side: Send information of reference grid of active fields.
Definition: context.cpp:1859
void readAttributesOfEnabledFieldsInReadModeFiles()
Definition: context.cpp:742
void findEnabledWriteModeFiles(void)
Find all files in write mode.
Definition: context.cpp:1197
void sendAllScalars()
Send all attributes of scalars from client to server.
Definition: grid.cpp:2686
bool isPostProcessed
Definition: context.hpp:259
bool allProcessed
Definition: context.hpp:260
std::list< MPI_Comm > comms
Communicators allocated internally.
Definition: context.hpp:265
CLog info("info")
Definition: log.hpp:55
CContextClient * getContextClient()
Definition: file.cpp:1130
void releaseBuffers(void)
Release all buffers.
void findEnabledFiles(void)
Definition: context.cpp:954
void solveOnlyRefOfEnabledFields(bool sendToServer)
Go up the hierachical tree via field_ref and do check of attributes of fields This can be done in a c...
Definition: context.cpp:807
static void SetCurrentContextId(const StdString &context)
Mutateurs ///.
static void recvPostProcessing(CEventServer &event)
Server side: Receive a message to do some post processing.
Definition: context.cpp:1498
void postProcessFilterGraph()
Definition: context.cpp:851
bool eventLoop(bool enableEventsProcessing=true)
void initServer(MPI_Comm intraComm, MPI_Comm interComm, CContext *cxtClient=0)
Definition: context.cpp:385
static bool has(const string &id)
#define TRY
Definition: exception.hpp:154
static double bufferSizeFactor
Factor used to tune the buffer size.
Definition: cxios.hpp:50
static bool isOptPerformance
Check if buffer size is for performance (as large as possible)
Definition: cxios.hpp:54
std::vector< CContextClient * > clientPrimServer
Definition: context.hpp:253
CField * addField(const string &id="")
Add a field into file.
Definition: file.cpp:1066
std::shared_ptr< CCalendar > getCalendar(void) const
Accesseurs ///.
Definition: context.cpp:81
CContextServer * server
Concrete context server.
Definition: context.hpp:250
#define UNUSED(parameter)
Macro ///.
Definition: xios_spl.hpp:38
void startPrefetchingOfEnabledReadModeFiles()
Definition: context.cpp:862
static T * get(const string &id)
static ENodeType GetType(void)
Definition: context.cpp:59
void postProcessing()
Do some simple post processings after parsing xml file After the xml file (iodef.xml) is parsed...
Definition: context.cpp:1546
static const StdString & GetRootName(void)
Accesseurs statiques ///.
Definition: xml_node.cpp:95
const CDuration NoneDu(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
Definition: duration.hpp:47
static void recvCloseDefinition(CEventServer &event)
Server side: Receive a message of client announcing a context close.
Definition: context.cpp:1319
void initClient(MPI_Comm intraComm, MPI_Comm interComm, CContext *cxtServer=0)
Definition: context.cpp:267
static StdString GetName(void)
Accesseurs statiques ///.
Definition: context.cpp:57
static void recvRegistry(CEventServer &event)
Server side: Receive a message to do some post processing.
Definition: context.cpp:2062
void checkGridEnabledFields()
Definition: context.cpp:776
void suspend(void)
Definition: timer.cpp:23
std::vector< CField * > getEnabledFields(int default_outputlevel=5, int default_level=1, bool default_enabled=true)
Get all enabled fields of file A field is considered to be enabled if it fullfil these conditions: it...
Definition: file.cpp:142
static void recvCreateFileHeader(CEventServer &event)
Server side: Receive a message of client annoucing the creation of header part of netcdf file...
Definition: context.cpp:1412
static int serverLevel
Definition: server.hpp:35
void findEnabledReadModeFiles(void)
Find all files in read mode.
Definition: context.cpp:1213
std::string StdString
Definition: xios_spl.hpp:48
void checkAxisDomainsGridsEligibilityForCompressedOutput()
Client side: Check if the defined axis, domains and grids are eligible for compressed indexed output...
Definition: context.cpp:1737
const std::list< int > & getRanksServerLeader(void) const
Get leading server in the group of connected server.
#define xios(arg)
std::map< int, StdSize > getAttributesBufferSize(std::map< int, StdSize > &maxEventSize, CContextClient *contextClient, bool bufferForWriting=false)
Compute the required buffer size to send the attributes (mostly those grid related).
Definition: context.cpp:1619
const StdString & getId(void) const
Accesseurs ///.
Definition: object.cpp:26
void buildFilterGraphOfFieldsWithReadAccess()
Definition: context.cpp:920
long long int Time
////////////////////// Déclarations ////////////////////// ///
Definition: duration.hpp:11
static CRegistry * globalRegistry
global registry which is wrote by the root process of the servers
Definition: cxios.hpp:55
void initReadFiles(void)
Definition: context.cpp:1991
ifstream f(fileToReadWrite_.c_str())
static StdString GetDefName(void)
////////////////////// Déclarations ////////////////////// ///
virtual void solveDescInheritance(bool apply, const CAttributeMap *const parent=0)
Find all inheritace among objects in a context.
Definition: context.cpp:227
#define DECLARE_NODE_PAR(Name_, name_)
StdString idServer_
Definition: context.hpp:263
#define DECLARE_NODE(Name_, name_)
static void AddChild(std::shared_ptr< U > group, std::shared_ptr< typename U::RelChild > child)
static void setCurrent(const string &id)
Set context with an id be the current context.
Definition: context.cpp:2029
void finalize(void)
Finalize context client and do some reports.
void distributeFileOverMemoryBandwith()
Definition: context.cpp:1100
virtual ~CContext(void)
Destructeur ///.
Definition: context.cpp:46
void mergeRegistry(const CRegistry &inRegistry)
Definition: registry.cpp:170
static void ShowTree(StdOStream &out=std::clog)
Show tree structure of context.
Definition: context.cpp:166
static void CleanTree(void)
Definition: context.cpp:255
void sendPostProcessing()
Client side: Send a message to do some post processing on server.
Definition: context.cpp:1470
void sendRegistry(void)
Definition: context.cpp:2084
void solveAllInheritance(bool apply=true)
Definition: context.cpp:928
static void SetCurrentContextId(const StdString &context)
Mutateurs ///.
bool isFinalized(void)
Context is finalized if it received context post finalize event.
Definition: context.cpp:2117
std::vector< CFile * > enabledReadModeFiles
Definition: context.hpp:233
void setCalendar(std::shared_ptr< CCalendar > newCalendar)
Mutateurs ///.
Definition: context.cpp:94
vector< CVariable * > getAllVariables(void) const
Definition: field.cpp:86
virtual bool hasChild(void) const
Verify if all root definition in the context have child.
Definition: context.cpp:241
void distributeFiles(void)
Definition: context.cpp:1006
This class is a registry database which store key with an associated value.
Definition: registry.hpp:20
CATCH CScalarAlgorithmReduceScalar::CScalarAlgorithmReduceScalar(CScalar *scalarDestination, CScalar *scalarSource, CReduceScalarToScalar *algo ERROR)("CScalarAlgorithmReduceScalar::CScalarAlgorithmReduceScalar(CScalar* scalarDestination, CScalar* scalarSource, CReduceScalarToScalar* algo)",<< "Operation must be defined."<< "Scalar source "<< scalarSource->getId()<< std::endl<< "Scalar destination "<< scalarDestination->getId())
static void recvUpdateCalendar(CEventServer &event)
Server side: Receive a message of client annoucing calendar update.
Definition: context.cpp:1358
std::map< int, size_t > getMinimumBufferSizeForAttributes(CContextClient *client)
StdString dumpClassAttributes(void)
Definition: context.cpp:2124
A context can be both on client and on server side.
static void ParseInclude(StdIStream &stream, const string &fluxId, T &object)
std::map< StdString, StdString > THashAttributes
////////////////////// Déclarations ////////////////////// ///
Definition: xml_node.hpp:15
virtual StdString toString(void) const
Convert context object into string (to print)
Definition: context.cpp:193
////////////////////// Déclarations ////////////////////// ///
void setClientServerBuffer(CContextClient *contextClient, bool bufferForWriting=false)
Sets client buffers.
Definition: context.cpp:326
void push(int rank, int nbSender, CMessage &msg)
CFile * file
Definition: field.hpp:218
std::shared_ptr< CCalendar > calendar
Definition: context.hpp:228
static CContext * create(const string &id="")
Create a context with specific id.
Definition: context.cpp:2042
void doPostTimestepOperationsForEnabledReadModeFiles()
Definition: context.cpp:884
void closeDefinition(void)
Close all the context defintion and do processing data After everything is well defined on client sid...
Definition: context.cpp:700
bool isInitialized(void)
Verify whether a context is initialized.
Definition: context.cpp:378
static StdSize minBufferSize
Minimum buffer size.
Definition: cxios.hpp:52
std::map< int, StdSize > getDataBufferSize(std::map< int, StdSize > &maxEventSize, CContextClient *contextClient, bool bufferForWriting=false)
Compute the required buffer size to send the fields data.
Definition: context.cpp:1662
void distributeFileOverServer2(int nbServers, int nGrids, SDistGrid *grids, int nFiles, SDistFile *files)
std::size_t StdSize
Definition: xios_spl.hpp:49
int clientRank
Rank of current client.
void createCalendar(void)
Try to create the calendar from the parsed attributes.
CLog error("error", cerr.rdbuf())
Definition: log.hpp:57
std::vector< CField * > fieldsWithReadAccess
Definition: context.hpp:239
static void recvProcessingGridOfEnabledFields(CEventServer &event)
Server side: Receive a message to do some post processing.
Definition: context.cpp:1460
std::vector< CContextServer * > serverPrimServer
Definition: context.hpp:252
std::vector< CFile * > enabledWriteModeFiles
Definition: context.hpp:235
void distributeFileOverBandwith()
Definition: context.cpp:1017
virtual void parse(xml::CXMLNode &node)
static bool dispatchEvent(CEventServer &event)
Deallocate buffers allocated by clientContexts.
Definition: context.cpp:1246
static const vector< CField * > getAll()
static bool isServer
Check if xios is server.
Definition: cxios.hpp:40
static CContextGroup * getRoot(void)
Get context group (context root)
Definition: context.cpp:67
bool havePendingRequests(void)
void sendEnabledFiles(const std::vector< CFile * > &activeFiles)
Client side: Send infomation of active files (files are enabled to write out)
Definition: context.cpp:1703
void resume(void)
Definition: timer.cpp:33
static CFile * create(const string &id=string(""))
void solveAllRefOfEnabledFieldsAndTransform(bool sendToServer)
Go up the hierachical tree via field_ref and do check of attributes of fields.
Definition: context.cpp:829
void closeAllFile(void)
Definition: context.cpp:1225
void sendAddAllVariables(CContextClient *client)
Send messages to duplicate all variables on server side Because each variable has also its attributes...
Definition: file.cpp:1235
static StdSize maxBufferSize
Maximum buffer size.
Definition: cxios.hpp:53
void createFileHeader(void)
Server side: Create header of netcdf file.
Definition: context.cpp:2004
void sendRefDomainsAxisScalars(const std::vector< CFile * > &activeFiles)
Client side: Send information of reference domain, axis and scalar of active fields.
Definition: context.cpp:1895
enum xios::_node_type ENodeType
////////////////////// Définitions ////////////////////// ///
void findAllEnabledFieldsInFiles(const std::vector< CFile * > &activeFiles)
Definition: context.cpp:734
static std::shared_ptr< CContextGroup > root
Definition: context.hpp:242
void sendCloseDefinition(void)
Client side: Send a message to server to make it close.
Definition: context.cpp:1292
static CTimer & get(std::string name)
Definition: timer.cpp:54
void sendProcessingGridOfEnabledFields()
after be gathered to the root process of the context, merged registry is sent to the root process of ...
Definition: context.cpp:1432
void sendPostProcessingGlobalAttributes()
Definition: context.cpp:645
void checkGridEnabledFieldsInFiles(const std::vector< CFile * > &activeFiles)
Check grid of active (enabled) fields in file.
Definition: context.cpp:791
std::shared_ptr< T > getShared(void)
bool fromBuffer(CBufferIn &buffer)
Definition: registry.cpp:116
CGarbageCollector garbageCollector
Definition: context.hpp:264
void sendGridEnabledFieldsInFiles(const std::vector< CFile * > &activeFiles)
Send active (enabled) fields in file from a client to others.
Definition: context.cpp:765
#define CATCH
Definition: exception.hpp:155
#define DEBUG(x)
Definition: exception.hpp:70
void sendUpdateCalendar(int step)
Client side: Send a message to update calendar in each time step.
Definition: context.cpp:1330
ENodeType getType(void) const
Accesseurs ///.
void findFieldsWithReadAccess(void)
Definition: context.cpp:895
std::ostream StdOStream
Definition: xios_spl.hpp:46
std::ostringstream StdOStringStream
Définition de types (issus de la bibliothèque standard)///.
Definition: xios_spl.hpp:41
std::ifstream StdIFStream
Definition: xios_spl.hpp:45
void duplicateAttributes(const CAttributeMap *const _parent)
Duplicate attribute map with a specific attribute map.
virtual void parse(xml::CXMLNode &node)
Parse xml file and write information into context object.
Definition: context.cpp:106
void hierarchicalGatherRegistry(void)
Definition: registry.cpp:258
void sendAllDomains()
Send all attributes of domains from client to server.
Definition: grid.cpp:2653
void releaseClientBuffers(void)
Deallocate buffers allocated by clientContexts.
Definition: context.cpp:569
void sendGridComponentEnabledFieldsInFiles(const std::vector< CFile * > &activeFiles)
Definition: context.cpp:750
int countChildCtx_
Counter of child contexts (for now it is the number of secondary server pools)
Definition: context.hpp:262
static StdString GetDefName(void)
Definition: context.cpp:58
CRegistry * registryOut
output registry which will be written into file at the finalize
Definition: context.hpp:256
CVariableGroup * getVirtualVariableGroup(void) const
Get virtual variable group In each file, there always exists a variable group which is the ancestor o...
Definition: file.cpp:109
void solveFieldRefInheritance(bool apply)
Definition: file.cpp:1046
void doPreTimestepOperationsForEnabledReadModeFiles()
Definition: context.cpp:873
static void recvPostProcessingGlobalAttributes(CEventServer &event)
Definition: context.cpp:673
bool checkBuffersAndListen(bool enableEventsProcessing=true)
Try to send the buffers and receive possible answers.
Definition: context.cpp:422
void finalize(void)
Terminate a context.
Definition: context.cpp:464
static CContext * getCurrent(void)
Get current context.
Definition: context.cpp:2018
CContextClient * client
Concrete contex client.
Definition: context.hpp:251
bool isServerLeader(void) const
Check if client connects to leading server.
static StdString & GetCurrentContextId(void)
Accesseurs ///.
bool checkBuffers(list< int > &ranks)
Verify state of buffers corresponding to a connection.
void postProcessingGlobalAttributes()
Definition: context.cpp:578
void prepareTimeseries(void)
Client side: Prepare the timeseries by adding the necessary files.
Definition: context.cpp:1757