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

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

output file in mutiple file option are now indexed by digit with a width equal to the width of the server communicator size.

YM

File size: 15.2 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) 
242            {
243              oss << "_"  ;
244              int width=0 ; int n=server->intraCommSize-1 ;
245              while(n != 0) { n=n/10 ; width++ ;}
246              oss.width(width) ;
247              oss.fill('0') ;
248              oss<<right<< server->intraCommRank;
249            }
250         }
251         oss << ".nc";
252
253         if (isOpen) data_out->closeFile() ;
254         bool isCollective=true ;
255         if (!par_access.isEmpty())
256         {
257           if (par_access.getValue()=="independent") isCollective=false ;
258           else if (par_access.getValue()=="collective") isCollective=true ;
259           else 
260           {
261             ERROR("void Context::createDataOutput(void)",
262                        "incorrect file <par_access> attribut : must be <collective> or <indepedent>, "
263                        <<"having : <"<<type.getValue()<<">") ;
264           }
265         }
266         data_out=shared_ptr<CDataOutput>(new CNc4DataOutput(oss.str(), false,server->intraComm,multifile, isCollective));
267         isOpen=true ;
268
269         data_out->writeFile(CFile::get(this));
270         for (it = this->enabledFields.begin() ;it != end; it++)
271         {
272            CField* field = *it;
273            this->data_out->writeFieldGrid(field);
274         }
275         
276         for (it = this->enabledFields.begin() ;it != end; it++)
277         {
278            CField* field = *it;
279            this->data_out->writeField(field);
280         }
281         
282         this->data_out->definition_end();
283      }
284   }
285
286   void CFile::close(void)
287   {
288     delete lastSync ;
289     delete lastSplit ;
290     if (!AllDomainEmpty ||  type==type_attr::one_file)
291       if (isOpen) 
292       {
293         this->data_out->closeFile();
294       }
295   }
296   //----------------------------------------------------------------
297
298   void CFile::parse(xml::CXMLNode & node)
299   {
300      SuperClass::parse(node);
301      if (node.goToChildElement() & this->hasId())
302      { // Si la définition du fichier intégre des champs et si le fichier est identifié.
303         node.goToParentElement();
304//         this->setVirtualFieldGroup(this->getId());
305         this->getVirtualFieldGroup()->parse(node, false);
306      }
307   }
308   //----------------------------------------------------------------
309
310   StdString CFile::toString(void) const
311   {
312      StdOStringStream oss;
313
314      oss << "<" << CFile::GetName() << " ";
315      if (this->hasId())
316         oss << " id=\"" << this->getId() << "\" ";
317      oss << SuperClassAttribute::toString() << ">" << std::endl;
318      if (this->getVirtualFieldGroup() != NULL)
319         oss << *this->getVirtualFieldGroup() << std::endl;
320      oss << "</" << CFile::GetName() << " >";
321      return (oss.str());
322   }
323
324   //----------------------------------------------------------------
325   
326   void CFile::solveDescInheritance(const CAttributeMap * const parent)
327   {
328      SuperClassAttribute::setAttributes(parent);
329      this->getVirtualFieldGroup()->solveDescInheritance(NULL);
330   }
331
332   //----------------------------------------------------------------
333
334   void CFile::solveFieldRefInheritance(void)
335   {
336      // Résolution des héritages par référence de chacun des champs contenus dans le fichier.
337      std::vector<CField*> allF = this->getAllFields();
338      for (unsigned int i = 0; i < allF.size(); i++)
339         allF[i]->solveRefInheritance();
340   }
341
342   //----------------------------------------------------------------
343
344   void CFile::solveEFGridRef(void)
345   {
346      for (unsigned int i = 0; i < this->enabledFields.size(); i++)
347         this->enabledFields[i]->solveGridReference();
348   }
349
350   //----------------------------------------------------------------
351
352   void CFile::solveEFOperation(void)
353   {
354      for (unsigned int i = 0; i < this->enabledFields.size(); i++)
355         this->enabledFields[i]->solveOperation();
356   }
357   
358   //---------------------------------------------------------------
359/*
360   void CFile::toBinary  (StdOStream & os) const
361   {
362      ENodeType genum = CFileGroup::GetType();
363      bool hasVFG = (this->getVirtualFieldGroup() != NULL);
364      SuperClass::toBinary(os);
365     
366      os.write (reinterpret_cast<const char*>(&genum) , sizeof(ENodeType));
367      os.write (reinterpret_cast<const char*>(&hasVFG) , sizeof(bool));
368     
369      if (hasVFG)this->getVirtualFieldGroup()->toBinary(os);
370         
371   }
372   
373   //----------------------------------------------------------------
374   
375   void CFile::fromBinary(StdIStream & is)
376   {
377      ENodeType renum = Unknown;
378      bool hasVFG = false;
379      SuperClass::fromBinary(is);
380     
381      is.read (reinterpret_cast<char*>(&renum), sizeof(ENodeType));
382      is.read (reinterpret_cast<char*>(&hasVFG), sizeof(bool));
383     
384      if (renum != CFileGroup::GetType())
385         ERROR("CFile::fromBinary(StdIStream & is)",
386               << "[ renum = " << renum << "] Bad type !");
387     
388//      this->setVirtualFieldGroup(this->getId());
389      if (hasVFG)this->getVirtualFieldGroup()->fromBinary(is);
390     
391   }
392*/
393
394   CField* CFile::addField(const string& id)
395   {
396     return vFieldGroup->createChild(id) ;
397   }
398
399   CFieldGroup* CFile::addFieldGroup(const string& id)
400   {
401     return vFieldGroup->createChildGroup(id) ;
402   }
403   
404 
405   void CFile::sendAddField(const string& id)
406   {
407    CContext* context=CContext::getCurrent() ;
408   
409    if (! context->hasServer )
410    {
411       CContextClient* client=context->client ;
412
413       CEventClient event(this->getType(),EVENT_ID_ADD_FIELD) ;   
414       if (client->isServerLeader())
415       {
416         CMessage msg ;
417         msg<<this->getId() ;
418         msg<<id ;
419         event.push(client->getServerLeader(),1,msg) ;
420         client->sendEvent(event) ;
421       }
422       else client->sendEvent(event) ;
423    }
424     
425   }
426   
427   void CFile::sendAddFieldGroup(const string& id)
428   {
429    CContext* context=CContext::getCurrent() ;
430    if (! context->hasServer )
431    {
432       CContextClient* client=context->client ;
433
434       CEventClient event(this->getType(),EVENT_ID_ADD_FIELD_GROUP) ;   
435       if (client->isServerLeader())
436       {
437         CMessage msg ;
438         msg<<this->getId() ;
439         msg<<id ;
440         event.push(client->getServerLeader(),1,msg) ;
441         client->sendEvent(event) ;
442       }
443       else client->sendEvent(event) ;
444    }
445     
446   }
447   
448   void CFile::recvAddField(CEventServer& event)
449   {
450     
451      CBufferIn* buffer=event.subEvents.begin()->buffer;
452      string id;
453      *buffer>>id ;
454      get(id)->recvAddField(*buffer) ;
455   }
456   
457   
458   void CFile::recvAddField(CBufferIn& buffer)
459   {
460      string id ;
461      buffer>>id ;
462      addField(id) ;
463   }
464
465   void CFile::recvAddFieldGroup(CEventServer& event)
466   {
467     
468      CBufferIn* buffer=event.subEvents.begin()->buffer;
469      string id;
470      *buffer>>id ;
471      get(id)->recvAddFieldGroup(*buffer) ;
472   }
473   
474   
475   void CFile::recvAddFieldGroup(CBufferIn& buffer)
476   {
477      string id ;
478      buffer>>id ;
479      addFieldGroup(id) ;
480   }
481   
482
483   bool CFile::dispatchEvent(CEventServer& event)
484   {
485      if (SuperClass::dispatchEvent(event)) return true ;
486      else
487      {
488        switch(event.type)
489        {
490           case EVENT_ID_ADD_FIELD :
491             recvAddField(event) ;
492             return true ;
493             break ;
494         
495           case EVENT_ID_ADD_FIELD_GROUP :
496             recvAddFieldGroup(event) ;
497             return true ;
498             break ;       
499         
500           default :
501              ERROR("bool CFile::dispatchEvent(CEventServer& event)", <<"Unknown Event") ;
502           return false ;
503        }
504      }
505   }
506   
507   
508   
509   
510   ///---------------------------------------------------------------
511
512} // namespace xios
Note: See TracBrowser for help on using the repository browser.