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

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

Add splitting file functionality
new file attribut "split_freq" to put the frequency of splitting

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 xmlioserver {
18namespace tree {
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<io::CDataOutput> CFile::getDataOutput(void) const
44   {
45      return (data_out);
46   }
47
48   boost::shared_ptr<CFieldGroup> CFile::getVirtualFieldGroup(void) const
49   {
50      return (this->vFieldGroup);
51   }
52
53   std::vector<boost::shared_ptr<CField> > CFile::getAllFields(void) const
54   {
55      return (this->vFieldGroup->getAllChildren());
56   }
57
58   //----------------------------------------------------------------
59
60   std::vector<boost::shared_ptr<CField> > CFile::getEnabledFields
61      (int default_outputlevel, int default_level, 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<boost::shared_ptr<CField> >::iterator it;
69      this->enabledFields = this->getAllFields();
70
71      std::vector<boost::shared_ptr<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(CObjectFactory::GetObject(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(boost::shared_ptr<CFieldGroup> newVFieldGroup)
116   { 
117      this->vFieldGroup = newVFieldGroup; 
118   }
119
120   //----------------------------------------------------------------
121
122   void CFile::setVirtualFieldGroup(void)
123   {
124      this->setVirtualFieldGroup
125         (CObjectFactory::CreateObject<CFieldGroup>());
126   }
127
128   //----------------------------------------------------------------
129   bool CFile::isSyncTime(void)
130   {
131     shared_ptr<CContext> context=CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()) ;
132     date::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      shared_ptr<CContext> context=CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()) ;
147      date::CDate& currentDate=context->calendar->getCurrentDate() ;
148     
149      if (! sync_freq.isEmpty()) syncFreq = date::CDuration::FromString(sync_freq.getValue());
150      if (! split_freq.isEmpty()) splitFreq = date::CDuration::FromString(split_freq.getValue());
151      if (! output_freq.isEmpty()) outputFreq = date::CDuration::FromString(output_freq.getValue());
152      lastSync=new date::CDate(currentDate) ;
153      lastSplit=new date::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     shared_ptr<CContext> context=CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()) ;
168     date::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      shared_ptr<CContext> context=CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()) ;
185      date::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<boost::shared_ptr<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      shared_ptr<CContext> context=CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()) ;
204      date::CDate& currentDate=context->calendar->getCurrentDate() ;
205     
206      std::vector<boost::shared_ptr<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         boost::shared_ptr<CField> field = *it;
213         AllDomainEmpty&=field->grid->domain->isEmpty() ;
214         setDomain.insert(field->grid->domain.get()) ;
215      }
216      nbDomain=setDomain.size() ;
217
218      if (!AllDomainEmpty ||  type.getValue()=="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*date::Second)).getStryyyymmdd();
227         bool multifile=true ;
228         if (!type.isEmpty())
229         {
230           if (type.getValue()=="one_file") multifile=false ;
231           else if (type.getValue()=="multi_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         
247         data_out=shared_ptr<io::CDataOutput>(new io::CNc4DataOutput(oss.str(), false,server->intraComm,multifile));
248         isOpen=true ;
249
250         data_out->writeFile(CObjectFactory::GetObject<CFile>(this));
251         for (it = this->enabledFields.begin() ;it != end; it++)
252         {
253            boost::shared_ptr<CField> field = *it;
254            this->data_out->writeFieldGrid(field);
255         }
256         
257         for (it = this->enabledFields.begin() ;it != end; it++)
258         {
259            boost::shared_ptr<CField> field = *it;
260            this->data_out->writeField(field);
261         }
262         
263         this->data_out->definition_end();
264      }
265   }
266
267   void CFile::close(void)
268   {
269     delete lastSync ;
270     delete lastSplit ;
271     if (!AllDomainEmpty ||  type.getValue()=="one_file")
272       if (isOpen) 
273       {
274         this->data_out->closeFile();
275       }
276   }
277   //----------------------------------------------------------------
278
279   void CFile::parse(xml::CXMLNode & node)
280   {
281      SuperClass::parse(node);
282      if (node.goToChildElement() & this->hasId())
283      { // Si la définition du fichier intégre des champs et si le fichier est identifié.
284         node.goToParentElement();
285//         this->setVirtualFieldGroup(this->getId());
286         this->getVirtualFieldGroup()->parse(node, false);
287      }
288   }
289   //----------------------------------------------------------------
290
291   StdString CFile::toString(void) const
292   {
293      StdOStringStream oss;
294
295      oss << "<" << CFile::GetName() << " ";
296      if (this->hasId())
297         oss << " id=\"" << this->getId() << "\" ";
298      oss << SuperClassAttribute::toString() << ">" << std::endl;
299      if (this->getVirtualFieldGroup().get() != NULL)
300         oss << *this->getVirtualFieldGroup() << std::endl;
301      oss << "</" << CFile::GetName() << " >";
302      return (oss.str());
303   }
304
305   //----------------------------------------------------------------
306   
307   void CFile::solveDescInheritance(const CAttributeMap * const parent)
308   {
309      SuperClassAttribute::setAttributes(parent);
310      this->getVirtualFieldGroup()->solveDescInheritance(NULL);
311   }
312
313   //----------------------------------------------------------------
314
315   void CFile::solveFieldRefInheritance(void)
316   {
317      // Résolution des héritages par référence de chacun des champs contenus dans le fichier.
318      std::vector<boost::shared_ptr<CField> > allF = this->getAllFields();
319      for (unsigned int i = 0; i < allF.size(); i++)
320         allF[i]->solveRefInheritance();
321   }
322
323   //----------------------------------------------------------------
324
325   void CFile::solveEFGridRef(void)
326   {
327      for (unsigned int i = 0; i < this->enabledFields.size(); i++)
328         this->enabledFields[i]->solveGridReference();
329   }
330
331   //----------------------------------------------------------------
332
333   void CFile::solveEFOperation(void)
334   {
335      for (unsigned int i = 0; i < this->enabledFields.size(); i++)
336         this->enabledFields[i]->solveOperation();
337   }
338   
339   //---------------------------------------------------------------
340   
341   void CFile::toBinary  (StdOStream & os) const
342   {
343      ENodeType genum = CFileGroup::GetType();
344      bool hasVFG = (this->getVirtualFieldGroup().get() != NULL);
345      SuperClass::toBinary(os);
346     
347      os.write (reinterpret_cast<const char*>(&genum) , sizeof(ENodeType));
348      os.write (reinterpret_cast<const char*>(&hasVFG) , sizeof(bool));
349     
350      if (hasVFG)this->getVirtualFieldGroup()->toBinary(os);
351         
352   }
353   
354   //----------------------------------------------------------------
355   
356   void CFile::fromBinary(StdIStream & is)
357   {
358      ENodeType renum = Unknown;
359      bool hasVFG = false;
360      SuperClass::fromBinary(is);
361     
362      is.read (reinterpret_cast<char*>(&renum), sizeof(ENodeType));
363      is.read (reinterpret_cast<char*>(&hasVFG), sizeof(bool));
364     
365      if (renum != CFileGroup::GetType())
366         ERROR("CFile::fromBinary(StdIStream & is)",
367               << "[ renum = " << renum << "] Bad type !");
368     
369//      this->setVirtualFieldGroup(this->getId());
370      if (hasVFG)this->getVirtualFieldGroup()->fromBinary(is);
371     
372   }
373   
374   shared_ptr<CField> CFile::addField(const string& id)
375   {
376     return vFieldGroup->createChild(id) ;
377   }
378
379   shared_ptr<CFieldGroup> CFile::addFieldGroup(const string& id)
380   {
381     return vFieldGroup->createChildGroup(id) ;
382   }
383   
384 
385   void CFile::sendAddField(const string& id)
386   {
387    shared_ptr<CContext> context=CContext::current() ;
388   
389    if (! context->hasServer )
390    {
391       CContextClient* client=context->client ;
392
393       CEventClient event(this->getType(),EVENT_ID_ADD_FIELD) ;   
394       if (client->isServerLeader())
395       {
396         CMessage msg ;
397         msg<<this->getId() ;
398         msg<<id ;
399         event.push(client->getServerLeader(),1,msg) ;
400         client->sendEvent(event) ;
401       }
402       else client->sendEvent(event) ;
403    }
404     
405   }
406   
407   void CFile::sendAddFieldGroup(const string& id)
408   {
409    shared_ptr<CContext> context=CContext::current() ;
410    if (! context->hasServer )
411    {
412       CContextClient* client=context->client ;
413
414       CEventClient event(this->getType(),EVENT_ID_ADD_FIELD_GROUP) ;   
415       if (client->isServerLeader())
416       {
417         CMessage msg ;
418         msg<<this->getId() ;
419         msg<<id ;
420         event.push(client->getServerLeader(),1,msg) ;
421         client->sendEvent(event) ;
422       }
423       else client->sendEvent(event) ;
424    }
425     
426   }
427   
428   void CFile::recvAddField(CEventServer& event)
429   {
430     
431      CBufferIn* buffer=event.subEvents.begin()->buffer;
432      string id;
433      *buffer>>id ;
434      get(id)->recvAddField(*buffer) ;
435   }
436   
437   
438   void CFile::recvAddField(CBufferIn& buffer)
439   {
440      string id ;
441      buffer>>id ;
442      addField(id) ;
443   }
444
445   void CFile::recvAddFieldGroup(CEventServer& event)
446   {
447     
448      CBufferIn* buffer=event.subEvents.begin()->buffer;
449      string id;
450      *buffer>>id ;
451      get(id)->recvAddFieldGroup(*buffer) ;
452   }
453   
454   
455   void CFile::recvAddFieldGroup(CBufferIn& buffer)
456   {
457      string id ;
458      buffer>>id ;
459      addFieldGroup(id) ;
460   }
461   
462
463   bool CFile::dispatchEvent(CEventServer& event)
464   {
465      if (SuperClass::dispatchEvent(event)) return true ;
466      else
467      {
468        switch(event.type)
469        {
470           case EVENT_ID_ADD_FIELD :
471             recvAddField(event) ;
472             return true ;
473             break ;
474         
475           case EVENT_ID_ADD_FIELD_GROUP :
476             recvAddFieldGroup(event) ;
477             return true ;
478             break ;       
479         
480           default :
481              ERROR("bool CFile::dispatchEvent(CEventServer& event)", <<"Unknown Event") ;
482           return false ;
483        }
484      }
485   }
486   
487   
488   
489   
490   ///---------------------------------------------------------------
491
492} // namespace tree
493} // namespace xmlioserver
Note: See TracBrowser for help on using the repository browser.