New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
file.cpp in vendors/XIOS/current/src/node – NEMO

source: vendors/XIOS/current/src/node/file.cpp @ 3408

Last change on this file since 3408 was 3408, checked in by rblod, 12 years ago

importing initial XIOS vendor drop

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 14.9 KB
Line 
1#include "file.hpp"
2
3#include "attribute_template_impl.hpp"
4#include "object_template_impl.hpp"
5#include "group_template_impl.hpp"
6
7#include "object_factory.hpp"
8#include "object_factory_impl.hpp"
9#include "data_output.hpp"
10#include "context.hpp"
11#include "context_server.hpp"
12#include "nc4_data_output.hpp"
13#include "calendar_util.hpp"
14#include "date.hpp"
15
16
17namespace xios {
18   
19   /// ////////////////////// Définitions ////////////////////// ///
20
21   CFile::CFile(void)
22      : CObjectTemplate<CFile>(), CFileAttributes()
23      , vFieldGroup(), data_out(), enabledFields()
24   { setVirtualFieldGroup() ;}
25
26   CFile::CFile(const StdString & id)
27      : CObjectTemplate<CFile>(id), CFileAttributes()
28      , vFieldGroup(), data_out(), enabledFields()
29   { setVirtualFieldGroup() ;}
30
31   CFile::~CFile(void)
32   { /* Ne rien faire de plus */ }
33
34   ///---------------------------------------------------------------
35
36   StdString CFile::GetName(void)   { return (StdString("file")); }
37   StdString CFile::GetDefName(void){ return (CFile::GetName()); }
38   ENodeType CFile::GetType(void)   { return (eFile); }
39
40   //----------------------------------------------------------------
41
42   boost::shared_ptr<CDataOutput> CFile::getDataOutput(void) const
43   {
44      return (data_out);
45   }
46
47   CFieldGroup* CFile::getVirtualFieldGroup(void) const
48   {
49      return (this->vFieldGroup);
50   }
51
52   std::vector<CField*> CFile::getAllFields(void) const
53   {
54      return (this->vFieldGroup->getAllChildren());
55   }
56
57   //----------------------------------------------------------------
58
59   std::vector<CField*> CFile::getEnabledFields(int default_outputlevel, 
60                                                int default_level,
61                                                bool default_enabled)
62   {
63      if (!this->enabledFields.empty())
64         return (this->enabledFields);
65
66      const int _outputlevel =
67         (!output_level.isEmpty()) ? output_level.getValue() : default_outputlevel;
68      std::vector<CField*>::iterator it;
69      this->enabledFields = this->getAllFields();
70
71      std::vector<CField*> newEnabledFields;
72     
73      for ( it = this->enabledFields.begin() ; it != this->enabledFields.end(); it++ )
74      {
75         if (!(*it)->enabled.isEmpty()) // Si l'attribut 'enabled' est défini ...
76         {
77            if (! (*it)->enabled.getValue()) continue;
78//            { it--; this->enabledFields.erase(it+1); continue; }
79         }
80         else // Si l'attribut 'enabled' n'est pas défini ...
81         {
82            if (!default_enabled) continue ;
83//            { it--; this->enabledFields.erase(it+1); continue; }
84         }
85
86         if (!(*it)->level.isEmpty()) // Si l'attribut 'level' est défini ...
87         {
88            if ((*it)->level.getValue() > _outputlevel) continue ;
89//            { it--; this->enabledFields.erase(it+1); continue; }
90         }
91         else // Si l'attribut 'level' n'est pas défini ...
92         {
93            if (default_level > _outputlevel) continue ;
94//            { it--; this->enabledFields.erase(it+1); continue; }
95         }
96 
97//         CField* field_tmp=(*it).get() ;
98//         shared_ptr<CField> sptfield=*it ;
99//         field_tmp->refObject.push_back(sptfield) ;
100         newEnabledFields.push_back(*it) ;
101         // Le champ est finalement actif, on y ajoute sa propre reference.
102         (*it)->refObject.push_back(*it);
103         // Le champ est finalement actif, on y ajoute la référence au champ de base.
104         (*it)->setRelFile(CFile::get(this));
105         (*it)->baseRefObject->refObject.push_back(*it);
106         // A faire, ajouter les references intermediaires...
107      }
108      enabledFields=newEnabledFields ;
109
110      return (this->enabledFields);
111   }
112
113   //----------------------------------------------------------------
114
115   void CFile::setVirtualFieldGroup(CFieldGroup* newVFieldGroup)
116   { 
117      this->vFieldGroup = newVFieldGroup; 
118   }
119
120   //----------------------------------------------------------------
121
122   void CFile::setVirtualFieldGroup(void)
123   {
124      this->setVirtualFieldGroup(CFieldGroup::create());
125   }
126
127   //----------------------------------------------------------------
128   bool CFile::isSyncTime(void)
129   {
130     CContext* context = CContext::getCurrent() ;
131     CDate& currentDate=context->calendar->getCurrentDate() ;
132     if (! sync_freq.isEmpty())
133     {
134       if (*lastSync+syncFreq < currentDate)
135       {
136         *lastSync=currentDate ;
137         return true ;
138        }
139      }
140      return false ;
141    }
142   
143   void CFile::initFile(void)
144   {
145      CContext* context = CContext::getCurrent() ;
146      CDate& currentDate=context->calendar->getCurrentDate() ;
147     
148      if (! sync_freq.isEmpty()) syncFreq = CDuration::FromString(sync_freq.getValue());
149      if (! split_freq.isEmpty()) splitFreq = CDuration::FromString(split_freq.getValue());
150      if (! output_freq.isEmpty()) outputFreq = CDuration::FromString(output_freq.getValue());
151      lastSync=new CDate(currentDate) ;
152      lastSplit=new CDate(currentDate) ;
153      isOpen=false ;
154    }
155   
156    void CFile::checkFile(void)
157    {
158      if (!isOpen) createHeader() ;
159      checkSync() ;
160      checkSplit() ;
161    }
162     
163     
164   bool CFile::checkSync(void)
165   {
166     CContext* context = CContext::getCurrent() ;
167     CDate& currentDate=context->calendar->getCurrentDate() ;
168     if (! sync_freq.isEmpty())
169     {
170       if (*lastSync+syncFreq < currentDate)
171       {
172         *lastSync=currentDate ;
173         data_out->syncFile() ;
174         return true ;
175        }
176      }
177      return false ;
178    }
179   
180   
181    bool CFile::checkSplit(void)
182    {
183      CContext* context = CContext::getCurrent() ;
184      CDate& currentDate=context->calendar->getCurrentDate() ;
185      if (! split_freq.isEmpty())
186      {
187        if (*lastSplit+splitFreq < currentDate)
188        {
189          *lastSplit=currentDate-outputFreq ;
190       
191          std::vector<CField*>::iterator it, end = this->enabledFields.end();
192          for (it = this->enabledFields.begin() ;it != end; it++)  (*it)->resetNStep() ;
193          createHeader() ;
194          return true ;
195        }
196      }
197      return false ;
198    }
199   
200   void CFile::createHeader(void)
201   {
202      CContext* context = CContext::getCurrent() ;
203      CDate& currentDate=context->calendar->getCurrentDate() ;
204     
205      std::vector<CField*>::iterator it, end = this->enabledFields.end();
206
207      AllDomainEmpty=true ;
208      set<CDomain*> setDomain ;
209      for (it = this->enabledFields.begin() ;it != end; it++)
210      {
211         CField* field = *it;
212         AllDomainEmpty&=field->grid->domain->isEmpty() ;
213         setDomain.insert(field->grid->domain) ;
214      }
215      nbDomain=setDomain.size() ;
216
217      if (!AllDomainEmpty ||  type.getValue()=="one_file")
218      {
219         StdString filename = (!name.isEmpty()) ?   name.getValue() : getId();
220         StdOStringStream oss;
221//         if (! output_dir.isEmpty()) oss << output_dir.getValue();
222         oss << filename;
223         if (!name_suffix.isEmpty()) oss << name_suffix.getValue();
224//         if (!split_freq.isEmpty()) oss<<"-["<<currentDate.toString()<<"]" ;
225         if (!split_freq.isEmpty()) oss<<"_"<<lastSplit->getStryyyymmdd()<<"-"<< (*lastSplit+(splitFreq-1*Second)).getStryyyymmdd();
226         bool multifile=true ;
227         if (!type.isEmpty())
228         {
229           if (type.getValue()=="one_file") multifile=false ;
230           else if (type.getValue()=="multi_file") multifile=true ;
231           else ERROR("void Context::createDataOutput(void)",
232                      "incorrect file <type> attribut : must be <multi_file> or <one_file>, "
233                      <<"having : <"<<type.getValue()<<">") ;
234         } 
235         
236         CContextServer* server=context->server ;
237
238         if (multifile) 
239         {
240            if (server->intraCommSize > 1) oss << "_" << server->intraCommRank;
241         }
242         oss << ".nc";
243
244         if (isOpen) data_out->closeFile() ;
245         bool isCollective=true ;
246         if (!par_access.isEmpty())
247         {
248           if (par_access.getValue()=="independent") isCollective=false ;
249           else if (par_access.getValue()=="collective") isCollective=true ;
250           else 
251           {
252             ERROR("void Context::createDataOutput(void)",
253                        "incorrect file <par_access> attribut : must be <collective> or <indepedent>, "
254                        <<"having : <"<<type.getValue()<<">") ;
255           }
256         }
257         data_out=shared_ptr<CDataOutput>(new CNc4DataOutput(oss.str(), false,server->intraComm,multifile, isCollective));
258         isOpen=true ;
259
260         data_out->writeFile(CFile::get(this));
261         for (it = this->enabledFields.begin() ;it != end; it++)
262         {
263            CField* field = *it;
264            this->data_out->writeFieldGrid(field);
265         }
266         
267         for (it = this->enabledFields.begin() ;it != end; it++)
268         {
269            CField* field = *it;
270            this->data_out->writeField(field);
271         }
272         
273         this->data_out->definition_end();
274      }
275   }
276
277   void CFile::close(void)
278   {
279     delete lastSync ;
280     delete lastSplit ;
281     if (!AllDomainEmpty ||  type.getValue()=="one_file")
282       if (isOpen) 
283       {
284         this->data_out->closeFile();
285       }
286   }
287   //----------------------------------------------------------------
288
289   void CFile::parse(xml::CXMLNode & node)
290   {
291      SuperClass::parse(node);
292      if (node.goToChildElement() & this->hasId())
293      { // Si la définition du fichier intégre des champs et si le fichier est identifié.
294         node.goToParentElement();
295//         this->setVirtualFieldGroup(this->getId());
296         this->getVirtualFieldGroup()->parse(node, false);
297      }
298   }
299   //----------------------------------------------------------------
300
301   StdString CFile::toString(void) const
302   {
303      StdOStringStream oss;
304
305      oss << "<" << CFile::GetName() << " ";
306      if (this->hasId())
307         oss << " id=\"" << this->getId() << "\" ";
308      oss << SuperClassAttribute::toString() << ">" << std::endl;
309      if (this->getVirtualFieldGroup() != NULL)
310         oss << *this->getVirtualFieldGroup() << std::endl;
311      oss << "</" << CFile::GetName() << " >";
312      return (oss.str());
313   }
314
315   //----------------------------------------------------------------
316   
317   void CFile::solveDescInheritance(const CAttributeMap * const parent)
318   {
319      SuperClassAttribute::setAttributes(parent);
320      this->getVirtualFieldGroup()->solveDescInheritance(NULL);
321   }
322
323   //----------------------------------------------------------------
324
325   void CFile::solveFieldRefInheritance(void)
326   {
327      // Résolution des héritages par référence de chacun des champs contenus dans le fichier.
328      std::vector<CField*> allF = this->getAllFields();
329      for (unsigned int i = 0; i < allF.size(); i++)
330         allF[i]->solveRefInheritance();
331   }
332
333   //----------------------------------------------------------------
334
335   void CFile::solveEFGridRef(void)
336   {
337      for (unsigned int i = 0; i < this->enabledFields.size(); i++)
338         this->enabledFields[i]->solveGridReference();
339   }
340
341   //----------------------------------------------------------------
342
343   void CFile::solveEFOperation(void)
344   {
345      for (unsigned int i = 0; i < this->enabledFields.size(); i++)
346         this->enabledFields[i]->solveOperation();
347   }
348   
349   //---------------------------------------------------------------
350   
351   void CFile::toBinary  (StdOStream & os) const
352   {
353      ENodeType genum = CFileGroup::GetType();
354      bool hasVFG = (this->getVirtualFieldGroup() != NULL);
355      SuperClass::toBinary(os);
356     
357      os.write (reinterpret_cast<const char*>(&genum) , sizeof(ENodeType));
358      os.write (reinterpret_cast<const char*>(&hasVFG) , sizeof(bool));
359     
360      if (hasVFG)this->getVirtualFieldGroup()->toBinary(os);
361         
362   }
363   
364   //----------------------------------------------------------------
365   
366   void CFile::fromBinary(StdIStream & is)
367   {
368      ENodeType renum = Unknown;
369      bool hasVFG = false;
370      SuperClass::fromBinary(is);
371     
372      is.read (reinterpret_cast<char*>(&renum), sizeof(ENodeType));
373      is.read (reinterpret_cast<char*>(&hasVFG), sizeof(bool));
374     
375      if (renum != CFileGroup::GetType())
376         ERROR("CFile::fromBinary(StdIStream & is)",
377               << "[ renum = " << renum << "] Bad type !");
378     
379//      this->setVirtualFieldGroup(this->getId());
380      if (hasVFG)this->getVirtualFieldGroup()->fromBinary(is);
381     
382   }
383   
384   CField* CFile::addField(const string& id)
385   {
386     return vFieldGroup->createChild(id) ;
387   }
388
389   CFieldGroup* CFile::addFieldGroup(const string& id)
390   {
391     return vFieldGroup->createChildGroup(id) ;
392   }
393   
394 
395   void CFile::sendAddField(const string& id)
396   {
397    CContext* context=CContext::getCurrent() ;
398   
399    if (! context->hasServer )
400    {
401       CContextClient* client=context->client ;
402
403       CEventClient event(this->getType(),EVENT_ID_ADD_FIELD) ;   
404       if (client->isServerLeader())
405       {
406         CMessage msg ;
407         msg<<this->getId() ;
408         msg<<id ;
409         event.push(client->getServerLeader(),1,msg) ;
410         client->sendEvent(event) ;
411       }
412       else client->sendEvent(event) ;
413    }
414     
415   }
416   
417   void CFile::sendAddFieldGroup(const string& id)
418   {
419    CContext* context=CContext::getCurrent() ;
420    if (! context->hasServer )
421    {
422       CContextClient* client=context->client ;
423
424       CEventClient event(this->getType(),EVENT_ID_ADD_FIELD_GROUP) ;   
425       if (client->isServerLeader())
426       {
427         CMessage msg ;
428         msg<<this->getId() ;
429         msg<<id ;
430         event.push(client->getServerLeader(),1,msg) ;
431         client->sendEvent(event) ;
432       }
433       else client->sendEvent(event) ;
434    }
435     
436   }
437   
438   void CFile::recvAddField(CEventServer& event)
439   {
440     
441      CBufferIn* buffer=event.subEvents.begin()->buffer;
442      string id;
443      *buffer>>id ;
444      get(id)->recvAddField(*buffer) ;
445   }
446   
447   
448   void CFile::recvAddField(CBufferIn& buffer)
449   {
450      string id ;
451      buffer>>id ;
452      addField(id) ;
453   }
454
455   void CFile::recvAddFieldGroup(CEventServer& event)
456   {
457     
458      CBufferIn* buffer=event.subEvents.begin()->buffer;
459      string id;
460      *buffer>>id ;
461      get(id)->recvAddFieldGroup(*buffer) ;
462   }
463   
464   
465   void CFile::recvAddFieldGroup(CBufferIn& buffer)
466   {
467      string id ;
468      buffer>>id ;
469      addFieldGroup(id) ;
470   }
471   
472
473   bool CFile::dispatchEvent(CEventServer& event)
474   {
475      if (SuperClass::dispatchEvent(event)) return true ;
476      else
477      {
478        switch(event.type)
479        {
480           case EVENT_ID_ADD_FIELD :
481             recvAddField(event) ;
482             return true ;
483             break ;
484         
485           case EVENT_ID_ADD_FIELD_GROUP :
486             recvAddFieldGroup(event) ;
487             return true ;
488             break ;       
489         
490           default :
491              ERROR("bool CFile::dispatchEvent(CEventServer& event)", <<"Unknown Event") ;
492           return false ;
493        }
494      }
495   }
496   
497   
498   
499   
500   ///---------------------------------------------------------------
501
502} // namespace xios
Note: See TracBrowser for help on using the repository browser.