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

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

Major Update

  • redesign Type and attribute manipulation
  • add enumerate type and attribute
  • use blitz class array instead of boost class array

YM

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