source: XIOS/trunk/src/node/file.cpp @ 346

Last change on this file since 346 was 346, checked in by ymipsl, 12 years ago

Suppress access to CObjectFactory class and CTreeManager.

YM

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