1 /*****************************************************************************/
2 /*                                    XDMF                                   */
3 /*                       eXtensible Data Model and Format                    */
4 /*                                                                           */
5 /*  Id : XdmfHeavyDataWriter.hpp                                             */
6 /*                                                                           */
7 /*  Author:                                                                  */
8 /*     Kenneth Leiter                                                        */
9 /*     kenneth.leiter@arl.army.mil                                           */
10 /*     US Army Research Laboratory                                           */
11 /*     Aberdeen Proving Ground, MD                                           */
12 /*                                                                           */
13 /*     Copyright @ 2011 US Army Research Laboratory                          */
14 /*     All Rights Reserved                                                   */
15 /*     See Copyright.txt for details                                         */
16 /*                                                                           */
17 /*     This software is distributed WITHOUT ANY WARRANTY; without            */
18 /*     even the implied warranty of MERCHANTABILITY or FITNESS               */
19 /*     FOR A PARTICULAR PURPOSE.  See the above copyright notice             */
20 /*     for more information.                                                 */
21 /*                                                                           */
22 /*****************************************************************************/
23 
24 #ifndef XDMFHEAVYDATAWRITER_HPP_
25 #define XDMFHEAVYDATAWRITER_HPP_
26 
27 #include "XdmfCore.hpp"
28 #include "XdmfArrayType.hpp"
29 #include "XdmfHeavyDataController.hpp"
30 #include "XdmfVisitor.hpp"
31 
32 #ifdef __cplusplus
33 
34 // Forward Declarations
35 class XdmfArray;
36 
37 // Includes
38 #include <string>
39 #include <list>
40 
41 /**
42  * @brief Traverses the Xdmf graph and writes heavy data stored in
43  * XdmfArrays to heavy data files on disk.
44  *
45  * This is an abstract base class to support the writing of different
46  * heavy data formats.
47  *
48  * XdmfHeavyDataWriter traverses an Xdmf graph structure and writes
49  * data stored in XdmfArrays to heavy data files on disk. Writing
50  * begins by calling the accept() operation on any XdmfItem and
51  * supplying this writer as the parameter. The writer will write all
52  * XdmfArrays under the XdmfItem to a heavy data file on disk. It will
53  * also attach an XdmfHeavyDataController to all XdmfArrays that it
54  * writes to disk.
55  *
56  * There are three modes of operation for this writer:
57  *   Default - All initialized XdmfArrays are written to new heavy datasets
58  *             regardless of whether they are attached to another heavy
59  *             dataset on disk via an XdmfHeavyDataController.
60  *   Overwrite - If an initialized XdmfArray is attached to an heavy dataset
61  *               via an XdmfHeavyDataController the writer will write values
62  *               to that location, overwriting all previous written values.
63  *               The dataset on disk will be resized appropriately.
64  *   Append - If an initialized XdmfArray is attached to an heavy dataset via
65  *            an XdmfHeavyDataController the writer will append the values to
66  *            the end of the dataset on disk.
67  *   Hyperslab - If an initialized XdmfArray is attached to a heavy dataset
68  *               via an XdmfHeavyDataController the writer will write to a
69  *               hyperslab in the dataset based on the start, stride, and
70  *               dimensions of the XdmfHeavyDataController.
71  */
72 class XDMFCORE_EXPORT XdmfHeavyDataWriter : public XdmfVisitor,
73                                             public Loki::Visitor<XdmfArray> {
74 
75 public:
76 
77   enum Mode {
78     Default,
79     Overwrite,
80     Append,
81     Hyperslab
82   };
83 
84   virtual ~XdmfHeavyDataWriter() = 0;
85 
86   /**
87    * Close file. This is only needed when the file is opened manually
88    * through openFile().
89    *
90    * Example of use:
91    *
92    * C++
93    *
94    * @dontinclude ExampleXdmfHeavyDataWriter.cpp
95    * @skipline //#initialization
96    * @until //#initialization
97    * @skipline //#closeFile
98    * @until //#closeFile
99    *
100    * Python
101    *
102    * @dontinclude XdmfExampleHeavyDataWriter.py
103    * @skipline #//initialization
104    * @until #//initialization
105    * @skipline #//closeFile
106    * @until #//closeFile
107    */
108   virtual void closeFile() = 0;
109 
110   /**
111    * Gets whether the HDF5 Writer is allowed to split data sets when writing to hdf5.
112    * Splitting should only occur for massive data sets.
113    * Setting to false assures compatibility with previous editions.
114    * Default setting is false.
115    *
116    * Example of use:
117    *
118    * C++
119    *
120    * @dontinclude ExampleXdmfHeavyDataWriter.cpp
121    * @skipline //#initialization
122    * @until //#initialization
123    * @skipline //#getAllowSetSplitting
124    * @until //#getAllowSetSplitting
125    *
126    * Python
127    *
128    * @dontinclude XdmfExampleHeavyDataWriter.py
129    * @skipline #//initialization
130    * @until #//initialization
131    * @skipline #//getAllowSetSplitting
132    * @until #//getAllowSetSplitting
133    *
134    * @return    Whether to allow data sets to be split across hdf5 files
135    */
136   int getAllowSetSplitting();
137 
138   /**
139    * Gets the file index. Used when file splitting and incremented whent he current file is full.
140    *
141    * C++
142    *
143    * @dontinclude ExampleXdmfHeavyDataWriter.cpp
144    * @skipline //#initialization
145    * @until //#initialization
146    * @skipline //#getFileIndex
147    * @until //#getFileIndex
148    *
149    * Python
150    *
151    * @dontinclude XdmfExampleHeavyDataWriter.py
152    * @skipline #//initialization
153    * @until #//initialization
154    * @skipline #//getFileIndex
155    * @until #//getFileIndex
156    *
157    * @return    The current file index.
158    */
159   int getFileIndex();
160 
161   /**
162    * Gets the amount of bytes that the heavy data writer uses as overhead for the data type.
163    *
164    * Example of use:
165    *
166    * C++
167    *
168    * @dontinclude ExampleXdmfHeavyDataWriter.cpp
169    * @skipline //#initialization
170    * @until //#initialization
171    * @skipline //#getFileOverhead
172    * @until //#getFileOverhead
173    *
174    * Python
175    *
176    * @dontinclude XdmfExampleHeavyDataWriter.py
177    * @skipline #//initialization
178    * @until #//initialization
179    * @skipline #//getFileOverhead
180    * @until #//getFileOverhead
181    *
182    * @return    Amount of bytes used as overhead
183    */
184   unsigned int getFileOverhead();
185 
186   /**
187    * Get the path to the heavy data file on disk this writer is writing to.
188    *
189    * Example of use:
190    *
191    * C++
192    *
193    * @dontinclude ExampleXdmfHeavyDataWriter.cpp
194    * @skipline //#initialization
195    * @until //#initialization
196    * @skipline //#getFilePath
197    * @until //#getFilePath
198    *
199    * Python
200    *
201    * @dontinclude XdmfExampleHeavyDataWriter.py
202    * @skipline #//initialization
203    * @until #//initialization
204    * @skipline #//getFilePath
205    * @until #//getFilePath
206    *
207    * @return    A std::string containing the path to the heavy file on disk this
208    *            writer is writing to.
209    */
210   std::string getFilePath() const;
211 
212   /**
213    * Gets the file size limit of the HDF5 files produced by the writer in MB. Overflow is pushed to a new HDF5 file.
214    *
215    * Example of use:
216    *
217    * C++
218    *
219    * @dontinclude ExampleXdmfHeavyDataWriter.cpp
220    * @skipline //#initialization
221    * @until //#initialization
222    * @skipline //#getFileSizeLimit
223    * @until //#getFileSizeLimit
224    *
225    * Python
226    *
227    * @dontinclude XdmfExampleHeavyDataWriter.py
228    * @skipline #//initialization
229    * @until #//initialization
230    * @skipline #//getFileSizeLimit
231    * @until #//getFileSizeLimit
232    *
233    * @return    The size limit in MB
234    */
235   int getFileSizeLimit();
236 
237   /**
238    * Get the Mode of operation for this writer.
239    *
240    * Example of use:
241    *
242    * C++
243    *
244    * @dontinclude ExampleXdmfHeavyDataWriter.cpp
245    * @skipline //#initialization
246    * @until //#initialization
247    * @skipline //#getMode
248    * @until //#getMode
249    *
250    * Python
251    *
252    * @dontinclude XdmfExampleHeavyDataWriter.py
253    * @skipline #//initialization
254    * @until #//initialization
255    * @skipline #//getMode
256    * @until #//getMode
257    *
258    * @return    The Mode of operation for this writer.
259    */
260   Mode getMode() const;
261 
262   /**
263    * Get whether to release data from memory after writing to disk.
264    *
265    * Example of use:
266    *
267    * C++
268    *
269    * @dontinclude ExampleXdmfHeavyDataWriter.cpp
270    * @skipline //#initialization
271    * @until //#initialization
272    * @skipline //#getReleaseData
273    * @until //#getReleaseData
274    *
275    * Python
276    *
277    * @dontinclude XdmfExampleHeavyDataWriter.py
278    * @skipline #//initialization
279    * @until #//initialization
280    * @skipline #//getReleaseData
281    * @until #//getReleaseData
282    *
283    * @return    True if data is freed after writing
284    */
285   bool getReleaseData() const;
286 
287   /**
288    * Open file for writing. This is an optional command that can
289    * improve performance for some writers when writing many datasets
290    * to a single file. User must call closeFile() after completing
291    * output.
292    *
293    * By default, heavy data files are open and closed before and after
294    * writing each dataset to ensure that other writers have access to
295    * the file (we never know whether we will be writing to the file
296    * again). This is expensive in some cases, but is always
297    * safe. Opening the file once and writing many datasets may result
298    * in improved performance, but the user must tell the writer when
299    * to open and close the file.
300    *
301    * Example of use:
302    *
303    * C++
304    *
305    * @dontinclude ExampleXdmfHeavyDataWriter.cpp
306    * @skipline //#initialization
307    * @until //#initialization
308    * @skipline //#openFile
309    * @until //#openFile
310    *
311    * Python
312    *
313    * @dontinclude XdmfExampleHeavyDataWriter.py
314    * @skipline #//initialization
315    * @until #//initialization
316    * @skipline #//openFile
317    * @until #//openFile
318    */
319   virtual void openFile() = 0;
320 
321   /**
322    * Sets whether to allow the HDF5 writer to split data sets when writing to hdf5.
323    * Splitting should only occur for massive data sets.
324    * Setting to false assures compatibility with previous editions.
325    * Default setting is false
326    *
327    * Example of use:
328    *
329    * C++
330    *
331    * @dontinclude ExampleXdmfHeavyDataWriter.cpp
332    * @skipline //#initialization
333    * @until //#initialization
334    * @skipline //#setAllowSetSplitting
335    * @until //#setAllowSetSplitting
336    *
337    * Python
338    *
339    * @dontinclude XdmfExampleHeavyDataWriter.py
340    * @skipline #//initialization
341    * @until #//initialization
342    * @skipline #//setAllowSetSplitting
343    * @until #//setAllowSetSplitting
344    *
345    * @param     newAllow        Whether to allow data sets to be split across hdf5 files
346    */
347   void setAllowSetSplitting(bool newAllow);
348 
349   /**
350    * Sets the file index. Used when file splitting and incremented when the current file is full. Set to 0 before using hyperslab or overwrite.
351    *
352    * C++
353    *
354    * @dontinclude ExampleXdmfHeavyDataWriter.cpp
355    * @skipline //#initialization
356    * @until //#initialization
357    * @skipline //#getFileIndex
358    * @until //#getFileIndex
359    *
360    * Python
361    *
362    * @dontinclude XdmfExampleHeavyDataWriter.py
363    * @skipline #//initialization
364    * @until #//initialization
365    * @skipline #//getFileIndex
366    * @until #//getFileIndex
367    *
368    * @param     newIndex        The index that the writer will append to the file name when incorperating file splitting
369    */
370   void setFileIndex(int newIndex);
371 
372   /**
373    * Sets the file size limit of the HDF5 files produced by the writer in MB. Overflow is pushed to a new HDF5 file.
374    * Using with arrays of string type may reduce performance.
375    *
376    * Example of use:
377    *
378    * C++
379    *
380    * @dontinclude ExampleXdmfHeavyDataWriter.cpp
381    * @skipline //#initialization
382    * @until //#initialization
383    * @skipline //#setFileSizeLimit
384    * @until //#setFileSizeLimit
385    *
386    * Python
387    *
388    * @dontinclude XdmfExampleHeavyDataWriter.py
389    * @skipline #//initialization
390    * @until #//initialization
391    * @skipline #//setFileSizeLimit
392    * @until #//setFileSizeLimit
393    *
394    * @param     newSize         The size limit in MB
395    */
396   void setFileSizeLimit(int newSize);
397 
398   /**
399    * Set the mode of operation for this writer.
400    *
401    * Example of use:
402    *
403    * C++
404    *
405    * @dontinclude ExampleXdmfHeavyDataWriter.cpp
406    * @skipline //#initialization
407    * @until //#initialization
408    * @skipline //#setMode
409    * @until //#setMode
410    *
411    * Python
412    *
413    * @dontinclude XdmfExampleHeavyDataWriter.py
414    * @skipline #//initialization
415    * @until #//initialization
416    * @skipline #//setMode
417    * @until #//setMode
418    *
419    * @param     mode    The Mode of operation for this writer.
420    */
421   void setMode(const Mode mode);
422 
423   /**
424    * Set whether to release data from memory after writing to disk.
425    *
426    * Example of use:
427    *
428    * C++
429    *
430    * @dontinclude ExampleXdmfHeavyDataWriter.cpp
431    * @skipline //#initialization
432    * @until //#initialization
433    * @skipline //#setReleaseData
434    * @until //#setReleaseData
435    *
436    * Python
437    *
438    * @dontinclude XdmfExampleHeavyDataWriter.py
439    * @skipline #//initialization
440    * @until #//initialization
441    * @skipline #//setReleaseData
442    * @until #//setReleaseData
443    *
444    * @param     releaseData     True if data should be freed after writing
445    */
446   void setReleaseData(const bool releaseData = true);
447 
448   /**
449    * Write an XdmfArray to heavy data file on disk.
450    *
451    * Example of use:
452    *
453    * C++
454    *
455    * @dontinclude ExampleXdmfHeavyDataWriter.cpp
456    * @skipline //#initialization
457    * @until //#initialization
458    * @skipline //#visit
459    * @until //#visit
460    *
461    * Python
462    *
463    * @dontinclude XdmfExampleHeavyDataWriter.py
464    * @skipline #//initialization
465    * @until #//initialization
466    * @skipline #//visit
467    * @until #//visit
468    *
469    * @param     array           An XdmfArray to write to heavy data.
470    * @param     visitor         A smart pointer to this visitor --- aids in grid traversal.
471    */
472   using XdmfVisitor::visit;
473   virtual void visit(XdmfArray & array,
474                      const shared_ptr<XdmfBaseVisitor> visitor) = 0;
475 
476 protected:
477 
478   XdmfHeavyDataWriter(const double compression = 1, const unsigned int overhead = 0);
479   XdmfHeavyDataWriter(const std::string & filePath, const double compression = 1, const unsigned int overhead = 0);
480 
481   virtual shared_ptr<XdmfHeavyDataController>
482   createController(const std::string & filePath,
483                    const std::string & descriptor,
484                    const shared_ptr<const XdmfArrayType> type,
485                    const std::vector<unsigned int> & start,
486                    const std::vector<unsigned int> & stride,
487                    const std::vector<unsigned int> & dimensions,
488                    const std::vector<unsigned int> & dataspaceDimensions) = 0;
489 
490   virtual int getDataSetSize(shared_ptr<XdmfHeavyDataController> descriptionController) = 0;
491 
492   bool mAllowSplitDataSets;
493   int mDataSetId;
494   int mFileIndex;
495   std::string mFilePath;
496   unsigned int mFileSizeLimit;
497   Mode mMode;
498   bool mReleaseData;
499   double  mCompressionRatio;
500   unsigned int mFileOverhead;
501 
502 private:
503 
504   XdmfHeavyDataWriter(const XdmfHeavyDataWriter &); // Not implemented.
505   void operator=(const XdmfHeavyDataWriter &);  // Not implemented.
506 
507 };
508 
509 #endif
510 
511 #ifdef __cplusplus
512 extern "C" {
513 #endif
514 
515 struct XDMFHEAVYDATAWRITER; // Simply as a typedef to ensure correct typing
516 typedef struct XDMFHEAVYDATAWRITER XDMFHEAVYDATAWRITER;
517 
518 #define XDMF_HEAVY_WRITER_MODE_DEFAULT   20
519 #define XDMF_HEAVY_WRITER_MODE_OVERWRITE 21
520 #define XDMF_HEAVY_WRITER_MODE_APPEND    22
521 #define XDMF_HEAVY_WRITER_MODE_HYPERSLAB 23
522 
523 // C wrappers go here
524 
525 XDMFCORE_EXPORT void XdmfHeavyDataWriterFree(XDMFHEAVYDATAWRITER * item);
526 
527 XDMFCORE_EXPORT int XdmfHeavyDataWriterGetAllowSetSplitting(XDMFHEAVYDATAWRITER * writer);
528 
529 XDMFCORE_EXPORT int XdmfHeavyDataWriterGetFileIndex(XDMFHEAVYDATAWRITER * writer);
530 
531 XDMFCORE_EXPORT unsigned int XdmfHeavyDataWriterGetFileOverhead(XDMFHEAVYDATAWRITER * writer);
532 
533 XDMFCORE_EXPORT char * XdmfHeavyDataWriterGetFilePath(XDMFHEAVYDATAWRITER * writer);
534 
535 XDMFCORE_EXPORT int XdmfHeavyDataWriterGetFileSizeLimit(XDMFHEAVYDATAWRITER * writer);
536 
537 XDMFCORE_EXPORT int XdmfHeavyDataWriterGetMode(XDMFHEAVYDATAWRITER * writer);
538 
539 XDMFCORE_EXPORT int XdmfHeavyDataWriterGetReleaseData(XDMFHEAVYDATAWRITER * writer);
540 
541 XDMFCORE_EXPORT void XdmfHeavyDataWriterSetAllowSetSplitting(XDMFHEAVYDATAWRITER * writer, int newAllow);
542 
543 XDMFCORE_EXPORT void XdmfHeavyDataWriterSetFileIndex(XDMFHEAVYDATAWRITER * writer, int newIndex);
544 
545 XDMFCORE_EXPORT void XdmfHeavyDataWriterSetFileSizeLimit(XDMFHEAVYDATAWRITER * writer, int newSize);
546 
547 XDMFCORE_EXPORT void XdmfHeavyDataWriterSetMode(XDMFHEAVYDATAWRITER * writer, int mode, int * status);
548 
549 XDMFCORE_EXPORT void XdmfHeavyDataWriterSetReleaseData(XDMFHEAVYDATAWRITER * writer, int releaseData);
550 
551 #define XDMF_HEAVYWRITER_C_CHILD_DECLARE(ClassName, CClassName, Level)                        \
552                                                                                               \
553 Level##_EXPORT void ClassName##Free( CClassName * item);                                      \
554 Level##_EXPORT int ClassName##GetAllowSetSplitting( CClassName * writer);                     \
555 Level##_EXPORT int ClassName##GetFileIndex( CClassName * writer);                             \
556 Level##_EXPORT unsigned int ClassName##GetFileOverhead( CClassName * writer);                 \
557 Level##_EXPORT char * ClassName##GetFilePath( CClassName * writer);                           \
558 Level##_EXPORT int ClassName##GetFileSizeLimit( CClassName * writer);                         \
559 Level##_EXPORT int ClassName##GetMode( CClassName * writer);                                  \
560 Level##_EXPORT int ClassName##GetReleaseData( CClassName * writer);                           \
561 Level##_EXPORT void ClassName##SetAllowSetSplitting( CClassName * writer, int newAllow);      \
562 Level##_EXPORT void ClassName##SetFileIndex( CClassName * writer, int newIndex);              \
563 Level##_EXPORT void ClassName##SetFileSizeLimit( CClassName * writer, int newSize);           \
564 Level##_EXPORT void ClassName##SetMode( CClassName * writer, int mode, int * status);         \
565 Level##_EXPORT void ClassName##SetReleaseData( CClassName * writer, int releaseData);
566 
567 
568 
569 #define XDMF_HEAVYWRITER_C_CHILD_WRAPPER(ClassName, CClassName)                               \
570                                                                                               \
571 void  ClassName##Free( CClassName * item)                                                     \
572 {                                                                                             \
573   XdmfHeavyDataWriterFree((XDMFHEAVYDATAWRITER *)((void *)item));                             \
574 }                                                                                             \
575                                                                                               \
576 int ClassName##GetAllowSetSplitting( CClassName * writer)                                     \
577 {                                                                                             \
578   return XdmfHeavyDataWriterGetAllowSetSplitting((XDMFHEAVYDATAWRITER *)((void *)writer));    \
579 }                                                                                             \
580                                                                                               \
581 int ClassName##GetFileIndex( CClassName * writer)                                             \
582 {                                                                                             \
583   return XdmfHeavyDataWriterGetFileIndex((XDMFHEAVYDATAWRITER *)((void *)writer));            \
584 }                                                                                             \
585                                                                                               \
586 unsigned int ClassName##GetFileOverhead( CClassName * writer)                                 \
587 {                                                                                             \
588   return XdmfHeavyDataWriterGetFileOverhead((XDMFHEAVYDATAWRITER *)((void *)writer));         \
589 }                                                                                             \
590                                                                                               \
591 char * ClassName##GetFilePath( CClassName * writer)                                           \
592 {                                                                                             \
593   return XdmfHeavyDataWriterGetFilePath((XDMFHEAVYDATAWRITER *)((void *)writer));             \
594 }                                                                                             \
595                                                                                               \
596 int ClassName##GetFileSizeLimit( CClassName * writer)                                         \
597 {                                                                                             \
598   return XdmfHeavyDataWriterGetFileSizeLimit((XDMFHEAVYDATAWRITER *)((void *)writer));        \
599 }                                                                                             \
600                                                                                               \
601 int ClassName##GetMode( CClassName * writer)                                                  \
602 {                                                                                             \
603   return XdmfHeavyDataWriterGetMode((XDMFHEAVYDATAWRITER *)((void *)writer));                 \
604 }                                                                                             \
605                                                                                               \
606 int ClassName##GetReleaseData( CClassName * writer)                                           \
607 {                                                                                             \
608   return XdmfHeavyDataWriterGetReleaseData((XDMFHEAVYDATAWRITER *)((void *)writer));          \
609 }                                                                                             \
610                                                                                               \
611 void ClassName##SetAllowSetSplitting( CClassName * writer, int newAllow)                      \
612 {                                                                                             \
613   XdmfHeavyDataWriterSetAllowSetSplitting((XDMFHEAVYDATAWRITER *)((void *)writer), newAllow); \
614 }                                                                                             \
615                                                                                               \
616 void ClassName##SetFileIndex( CClassName * writer, int newIndex)                              \
617 {                                                                                             \
618   XdmfHeavyDataWriterSetFileIndex((XDMFHEAVYDATAWRITER *)((void *)writer), newIndex);         \
619 }                                                                                             \
620                                                                                               \
621 void ClassName##SetFileSizeLimit( CClassName * writer, int newSize)                           \
622 {                                                                                             \
623   XdmfHeavyDataWriterSetFileSizeLimit((XDMFHEAVYDATAWRITER *)((void *)writer), newSize);      \
624 }                                                                                             \
625                                                                                               \
626 void ClassName##SetMode( CClassName * writer, int mode, int * status)                         \
627 {                                                                                             \
628   XdmfHeavyDataWriterSetMode((XDMFHEAVYDATAWRITER *)((void *)writer), mode, status);          \
629 }                                                                                             \
630                                                                                               \
631 void ClassName##SetReleaseData( CClassName * writer, int releaseData)                         \
632 {                                                                                             \
633   XdmfHeavyDataWriterSetReleaseData((XDMFHEAVYDATAWRITER *)((void *)writer), releaseData);    \
634 }
635 
636 #ifdef __cplusplus
637 }
638 #endif
639 
640 #endif /* XDMFHEAVYDATAWRITER_HPP_ */
641