Code_Saturne
CFD tool
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
cs_file.h
Go to the documentation of this file.
1 #ifndef __CS_FILE_H__
2 #define __CS_FILE_H__
3 
4 /*============================================================================
5  * File and directory operations, with parallel file I/O
6  *============================================================================*/
7 
8 /*
9  This file is part of Code_Saturne, a general-purpose CFD tool.
10 
11  Copyright (C) 1998-2012 EDF S.A.
12 
13  This program is free software; you can redistribute it and/or modify it under
14  the terms of the GNU General Public License as published by the Free Software
15  Foundation; either version 2 of the License, or (at your option) any later
16  version.
17 
18  This program is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20  FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
21  details.
22 
23  You should have received a copy of the GNU General Public License along with
24  this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
25  Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 */
27 
28 /*----------------------------------------------------------------------------*/
29 
30 #if defined(HAVE_MPI)
31 #include <mpi.h>
32 #endif
33 
34 /*----------------------------------------------------------------------------
35  * Local headers
36  *----------------------------------------------------------------------------*/
37 
38 #include "cs_defs.h"
39 
40 /*----------------------------------------------------------------------------*/
41 
43 
44 /*=============================================================================
45  * Macro definitions
46  *============================================================================*/
47 
48 /*
49  * File hints and semantics
50  */
51 
52 #define CS_FILE_NO_MPI_IO (1 << 0)
53 #define CS_FILE_NO_PREDISTRIBUTE (1 << 1)
54 
55 /* MPI-IO positioning semantics */
56 
57 #define CS_FILE_EXPLICIT_OFFSETS (1 << 2)
58 #define CS_FILE_INDIVIDUAL_POINTERS (1 << 3)
59 
60 /*============================================================================
61  * Type definitions
62  *============================================================================*/
63 
64 /* File descriptor */
65 
66 typedef struct _cs_file_t cs_file_t;
67 
68 /* Helper structure for IO serialization */
69 
70 #if defined(HAVE_MPI)
71 typedef struct _cs_file_serializer_t cs_file_serializer_t;
72 #endif
73 
74 /* File modes */
75 
76 typedef enum {
77 
78  CS_FILE_MODE_READ, /* Read mode */
79  CS_FILE_MODE_WRITE, /* Write mode */
80  CS_FILE_MODE_APPEND /* Append mode */
81 
83 
84 /* Hints for file management */
85 
86 typedef unsigned int cs_file_hints_t;
87 
88 /* Offset for file position indicator (int64_t in C99) */
89 
90 #if defined(SIZEOF_LONG_LONG)
91 typedef long long cs_file_off_t;
92 #else
93 typedef long cs_file_off_t;
94 #endif
95 
96 /* Possibilities for the third argument of cs_file_seek() */
97 
98 typedef enum {
99 
100  CS_FILE_SEEK_SET, /* Seek from beginning of file */
101  CS_FILE_SEEK_CUR, /* Seek from current position */
102  CS_FILE_SEEK_END /* Seek from end of file */
103 
105 
106 /*=============================================================================
107  * Public function prototypes
108  *============================================================================*/
109 
110 /*----------------------------------------------------------------------------
111  * Create a file descriptor and open the associated file.
112  *
113  * By default, data is written or read as native data. This behavior may be
114  * modified by cs_file_set_swap_endian().
115  *
116  * parameters:
117  * name <-- file name
118  * mode <-- file acces mode: read, write, or append
119  * hints <-- file I/O hints (for MPI and MPI I/O behavior)
120  *
121  * returns:
122  * pointer to cs_file_t file descriptor (NULL in case of failure);
123  * currently, errors are fatal.
124  *----------------------------------------------------------------------------*/
125 
126 #if defined(HAVE_MPI)
127 
128 cs_file_t *
129 cs_file_open(const char *name,
130  cs_file_mode_t mode,
131  cs_file_hints_t hints,
132  MPI_Comm comm);
133 
134 #else
135 
136 cs_file_t *
137 cs_file_open(const char *name,
138  cs_file_mode_t mode,
139  cs_file_hints_t hints);
140 
141 #endif
142 
143 /*----------------------------------------------------------------------------
144  * Destroy a file descriptor and close the associated file.
145  *
146  * parameters:
147  * f <-> file descriptor to destroy
148  *
149  * returns:
150  * NULL pointer
151  *----------------------------------------------------------------------------*/
152 
153 cs_file_t *
155 
156 /*----------------------------------------------------------------------------
157  * Return a file's name.
158  *
159  * parameters:
160  * f <-- cs_file_t descriptor
161  *
162  * returns:
163  * pointer to the file's name.
164  *----------------------------------------------------------------------------*/
165 
166 const char *
167 cs_file_get_name(const cs_file_t *f);
168 
169 /*----------------------------------------------------------------------------
170  * Ensure that data is read or written in big-endian
171  * (network standard) format.
172  *
173  * parameters:
174  * f <-> cs_file_t descriptor
175  *----------------------------------------------------------------------------*/
176 
177 void
179 
180 /*----------------------------------------------------------------------------
181  * Return a file's byte-swapping behavior.
182  *
183  * parameters:
184  * f <-- cs_file_t descriptor
185  *
186  * returns:
187  * 0 if file's endianness is the same as the system's, 1 otherwise.
188  *----------------------------------------------------------------------------*/
189 
190 int
192 
193 /*----------------------------------------------------------------------------
194  * Set a file's byte-swapping behavior.
195  *
196  * Using this function assumes one is familiar with a file's coding
197  * or structure; use with caution.
198  *
199  * parameters:
200  * f <-> cs_file_t descriptor
201  * swap <-- 1 if bytes must be swapped, 0 otherwise
202  *----------------------------------------------------------------------------*/
203 
204 void
206  int swap);
207 
208 /*----------------------------------------------------------------------------
209  * Read global data from a file, distributing it to all processes
210  * associated with that file.
211  *
212  * parameters:
213  * f <-- cs_file_t descriptor
214  * buf --> pointer to location receiving data
215  * size <-- size of each item of data in bytes
216  * ni <-- number of items to read
217  *
218  * returns:
219  * the number of items (not bytes) sucessfully read; currently,
220  * errors are fatal.
221  *----------------------------------------------------------------------------*/
222 
223 size_t
225  void *buf,
226  size_t size,
227  size_t ni);
228 
229 /*----------------------------------------------------------------------------
230  * Write global data to a file.
231  *
232  * Under MPI, data is only written by the associated communicator's root
233  * rank. The buffers on other ranks are ignored, though the file offset
234  * is updated (i.e. the call to this function is collective).
235  *
236  * parameters:
237  * f <-- cs_file_t descriptor
238  * buf <-- pointer to location containing data
239  * size <-- size of each item of data in bytes
240  * ni <-- number of items to read
241  *
242  * returns:
243  * the number of items (not bytes) sucessfully written; currently,
244  * errors are fatal.
245  *----------------------------------------------------------------------------*/
246 
247 size_t
249  const void *buf,
250  size_t size,
251  size_t ni);
252 
253 /*----------------------------------------------------------------------------
254  * Read data to a buffer, distributing a contiguous part of it to each
255  * process associated with a file.
256  *
257  * Each process should receive a (possibly empty) block of the data,
258  * and we should have:
259  * global_num_start at rank 0 = 1
260  * global_num_start at rank i+1 = global_num_end at rank i.
261  * Otherwise, behavior (especially positioning for future reads) is undefined.
262  *
263  * parameters:
264  * f <-- cs_file_t descriptor
265  * buf --> pointer to location receiving data
266  * size <-- size of each item of data in bytes
267  * stride <-- number of (interlaced) values per block item
268  * global_num_start <-- global number of first block item (1 to n numbering)
269  * global_num_end <-- global number of past-the end block item
270  * (1 to n numbering)
271  *
272  * returns:
273  * the (local) number of items (not bytes) sucessfully read; currently,
274  * errors are fatal.
275  *----------------------------------------------------------------------------*/
276 
277 size_t
279  void *buf,
280  size_t size,
281  size_t stride,
282  cs_gnum_t global_num_start,
283  cs_gnum_t global_num_end);
284 
285 /*----------------------------------------------------------------------------
286  * Write data to a file, each associated process providing a contiguous part
287  * of this data.
288  *
289  * Each process should provide a (possibly empty) block of the data,
290  * and we should have:
291  * global_num_start at rank 0 = 1
292  * global_num_start at rank i+1 = global_num_end at rank i.
293  * Otherwise, behavior (especially positioning for future reads) is undefined.
294  *
295  * This function may require an internal copy of the data to ensure that
296  * the buffer contents are not modified, so if the buffer contents are
297  * temporary values, to be deleted after writing, using
298  * cs_file_write_block_buffer() instead may be used to avoid an unneeded
299  * memory allocation and copy.
300  *
301  * parameters:
302  * f <-- cs_file_t descriptor
303  * buf <-- pointer to location containing data
304  * size <-- size of each item of data in bytes
305  * stride <-- number of (interlaced) values per block item
306  * global_num_start <-- global number of first block item (1 to n numbering)
307  * global_num_end <-- global number of past-the end block item
308  * (1 to n numbering)
309  *
310  * returns:
311  * the (local) number of items (not bytes) sucessfully written; currently,
312  * errors are fatal.
313  *----------------------------------------------------------------------------*/
314 
315 size_t
317  const void *buf,
318  size_t size,
319  size_t stride,
320  cs_gnum_t global_num_start,
321  cs_gnum_t global_num_end);
322 
323 /*----------------------------------------------------------------------------
324  * Write data to a file, each associated process providing a contiguous part
325  * of this data.
326  *
327  * Each process should provide a (possibly empty) block of the data,
328  * and we should have:
329  * global_num_start at rank 0 = 1
330  * global_num_start at rank i+1 = global_num_end at rank i.
331  * Otherwise, behavior (especially positioning for future reads) is undefined.
332  *
333  * This function is intended to be used mainly data that is already a
334  * copy of original data (such as data that has been redistributed across
335  * processors just for the sake of output), or that is to be deleted after
336  * writing, so it may modify the values in its input buffer (notably to
337  * convert from little-endian to big-endian of vice-versa if necessary).
338  *
339  * parameters:
340  * f <-- cs_file_t descriptor
341  * buf <-> pointer to location containing data
342  * size <-- size of each item of data in bytes
343  * stride <-- number of (interlaced) values per block item
344  * global_num_start <-- global number of first block item (1 to n numbering)
345  * global_num_end <-- global number of past-the end block item
346  * (1 to n numbering)
347  *
348  * returns:
349  * the (local) number of items (not bytes) sucessfully written; currently,
350  * errors are fatal.
351  *----------------------------------------------------------------------------*/
352 
353 size_t
355  void *buf,
356  size_t size,
357  size_t stride,
358  cs_gnum_t global_num_start,
359  cs_gnum_t global_num_end);
360 
361 /*----------------------------------------------------------------------------
362  * Update the file pointer according to whence.
363  *
364  * parameters:
365  * f <-> cs_file_t descriptor.
366  * offset <-- add to position specified to whence to obtain new position,
367  * measured in characters from the beginning of the file.
368  * whence <-- beginning if CS_FILE_SEEK_SET, current if CS_FILE_SEEK_CUR,
369  * or end-of-file if CS_FILE_SEEK_END.
370  *
371  * returns:
372  * 0 upon success, nonzero otherwise; currently, errors are fatal.
373  *----------------------------------------------------------------------------*/
374 
375 int
377  cs_file_off_t offset,
378  cs_file_seek_t whence);
379 
380 /*----------------------------------------------------------------------------
381  * Return the position of the file pointer.
382  *
383  * When using MPI-IO with individual file pointers, we consider the file
384  * pointer to be equal to the highest value of the individual file pointers.
385  *
386  * parameters:
387  * f <-- cs_file_t descriptor
388  *
389  * returns:
390  * current position of the file pointer
391  *----------------------------------------------------------------------------*/
392 
395 
396 /*----------------------------------------------------------------------------
397  * Get the default semantics for file access.
398  *
399  * returns:
400  * current default semantics for file access
401  *----------------------------------------------------------------------------*/
402 
405 
406 /*----------------------------------------------------------------------------
407  * Set the default semantics for file access.
408  *
409  * This may fail if semantics given contain incompatible values,
410  * such as (CS_FILE_EXPLICIT_OFFSETS | CS_FILE_INDIVIDUAL_POINTERS),
411  * or when setting MPI-IO access semantics when MPI-IO is not available.
412  *
413  * parameters:
414  * hints <-- flag (bit mask) defining default semantics
415  *
416  * returns:
417  * 0 if the semantics were valid, 1 otherwise.
418  *----------------------------------------------------------------------------*/
419 
420 int
422 
423 /*----------------------------------------------------------------------------
424  * Dump the metadata of a file structure in human readable form
425  *
426  * parameters:
427  * f <-- pointer to file
428  *----------------------------------------------------------------------------*/
429 
430 void
431 cs_file_dump(const cs_file_t *f);
432 
433 #if defined(HAVE_MPI)
434 
435 /*----------------------------------------------------------------------------
436  * Create a cs_file_serializer_t structure.
437  *
438  * The buf_block_size argument is optional, and may be used when the buffer
439  * on rank 0 is larger than (global_num_end - global_num_start)*size*stride
440  * bytes. If zero, a block size of (global_num_end - global_num_start) on
441  * rank 0 is assumed; a buffer may not be smaller than this, as it must
442  * initially contain all data on rank 0's block.
443  *
444  * parameters:
445  * size <-- size of each item of data in bytes
446  * stride <-- number of (interlaced) values per block item
447  * global_num_start <-- global number of first block item (1 to n numbering)
448  * global_num_end <-- global number of past-the end block item
449  * (1 to n numbering)
450  * buf_block_size <-- Local data buffer block size, or 0 for default
451  * global_num_end - global_num_start
452  * (only useful on rank 0)
453  * buf <-- pointer to local block data buffer
454  * comm <-- associated MPI communicator
455  *
456  * returns:
457  * pointer to new serializer structure
458  *----------------------------------------------------------------------------*/
459 
460 cs_file_serializer_t *
461 cs_file_serializer_create(size_t size,
462  size_t stride,
463  cs_gnum_t global_num_start,
464  cs_gnum_t global_num_end,
465  size_t buf_block_size,
466  void *buf,
467  MPI_Comm comm);
468 
469 /*----------------------------------------------------------------------------
470  * Destroy a cs_file_serializer_t structure.
471  *
472  * parameters:
473  * s <-> pointer to pointer structure that should be destroyed
474  *----------------------------------------------------------------------------*/
475 
476 void
477 cs_file_serializer_destroy(cs_file_serializer_t **s);
478 
479 /*----------------------------------------------------------------------------
480  * Advance a cs_file_serializer_t structure.
481  *
482  * Data from the buffer of the next communicating rank is copied
483  * to rank 0 (this is a no-op the first time this function is called,
484  * as rank 0 already has its data).
485  *
486  * On rank 0, the return value may point to the buffer defined when
487  * initializing the serializer, or to an aditional buffer if the former is
488  * too small to receive data from all ranks.
489  *
490  * Note also that for ranks > 0, this function always returns NULL,
491  * as only one call is needed for those ranks.
492  *
493  * parameters:
494  * s <-- pointer to serializer structure
495  * cur_range --> optional start and past-the end global numbers for the
496  * current block (size: 2), or NULL; only on rank 0
497  *
498  * returns:
499  * a pointer to the buffer containing new data (first call counts as new),
500  * or NULL if we are finished; always NULL on ranks > 0
501  *----------------------------------------------------------------------------*/
502 
503 void *
504 cs_file_serializer_advance(cs_file_serializer_t *s,
505  cs_gnum_t cur_range[2]);
506 
507 #endif /* defined(HAVE_MPI) */
508 
509 /*----------------------------------------------------------------------------
510  * Create a new directory using default permissions.
511  *
512  * This function is similar to the POSIX function mkdir(), except that
513  * it has no "mode" argument: by default, on a POSIX type system,
514  * permissions include read, write, and execute access for the user,
515  * group and others, modified by the users umask value (so with a
516  * typical configuration, the user will have read, write, and execute
517  * pemission, the group and others will only have read and execute
518  * permission, but this behavior may be modified).
519  *
520  * Also, contrary to the usual mkdir(), if the directory already
521  * exists (and is truly a directory), this is considered a success
522  * and not a failure, and 0 is returned: the aim of this function
523  * is to make a directory available, so if it already exists,
524  * this is considered acceptable.
525  *
526  * parameters:
527  * path: <-- name of new directory.
528  *
529  * returns:
530  * 0 on success, -1 if an error occured (in which case errno
531  * contains the appropriate error code). If the underlying
532  * system has no mkdir() function or it was not detected
533  * upon BFT configuration, 1 is returned.
534  *----------------------------------------------------------------------------*/
535 
536 int
537 cs_file_mkdir_default(const char *path);
538 
539 /*----------------------------------------------------------------------------
540  * Check if a file exists and is a regular file.
541  *
542  * parameters:
543  * path <-- file name.
544  *
545  * returns:
546  * 1 if file exists and is a regular file, 0 otherwise.
547  *----------------------------------------------------------------------------*/
548 
549 int
550 cs_file_isreg(const char *path);
551 
552 /*----------------------------------------------------------------------------
553  * Check if a directory exists.
554  *
555  * parameters:
556  * path <-- directory name.
557  *
558  * returns:
559  * 1 if directory exists, 0 otherwise.
560  *----------------------------------------------------------------------------*/
561 
562 int
563 cs_file_isdir(const char *path);
564 
565 /*----------------------------------------------------------------------------
566  * List files inside a directory.
567  *
568  * The array returned must be freed by the caller using BFT_FREE,
569  * as well as the individual entries in the array.
570  *
571  * parameters:
572  * path <-- name of directory.
573  *
574  * returns:
575  * an array of file names in a directory. The last entry is set to NULL.
576  * If no means to list the directory or an error occured, the return
577  * value is simply NULL.
578  *----------------------------------------------------------------------------*/
579 
580 char **
581 cs_file_listdir(const char *path);
582 
583 /*----------------------------------------------------------------------------*/
584 
586 
587 #endif /* __CS_FILE_H__ */
cs_file_t * cs_file_open(const char *name, cs_file_mode_t mode, cs_file_hints_t hints)
Create a file descriptor and open the associated file.
Definition: cs_file.c:1379
size_t cs_file_write_block_buffer(cs_file_t *f, void *buf, size_t size, size_t stride, cs_gnum_t global_num_start, cs_gnum_t global_num_end)
Write data to a file, each associated process providing a contiguous part of this data...
Definition: cs_file.c:1972
int cs_file_set_default_semantics(cs_file_hints_t hints)
Set the default semantics for file access.
Definition: cs_file.c:2176
void cs_file_set_swap_endian(cs_file_t *f, int swap)
Set a file's byte-swapping behavior.
Definition: cs_file.c:1576
char ** cs_file_listdir(const char *path)
List files inside a directory.
Definition: cs_file.c:2648
cs_file_seek_t
Definition: cs_file.h:98
Definition: cs_file.h:79
int cs_file_get_swap_endian(const cs_file_t *f)
Return a file's byte-swapping behavior.
Definition: cs_file.c:1559
size_t cs_file_write_block(cs_file_t *f, const void *buf, size_t size, size_t stride, cs_gnum_t global_num_start, cs_gnum_t global_num_end)
Write data to a file, each associated process providing a contiguous part of this data...
Definition: cs_file.c:1891
size_t cs_file_read_block(cs_file_t *f, void *buf, size_t size, size_t stride, cs_gnum_t global_num_start, cs_gnum_t global_num_end)
Read data to a buffer, distributing a contiguous part of it to each process associated with a file...
Definition: cs_file.c:1813
struct _cs_file_t cs_file_t
Definition: cs_file.h:66
#define BEGIN_C_DECLS
Definition: cs_defs.h:365
int cs_file_isdir(const char *path)
Check if a directory exists.
Definition: cs_file.c:2601
Definition: cs_file.h:78
cs_file_t * cs_file_free(cs_file_t *f)
Destroy a file descriptor and close the associated file.
Definition: cs_file.c:1473
void cs_file_dump(const cs_file_t *f)
Dump the metadata of a file structure in human readable form.
Definition: cs_file.c:2210
cs_file_mode_t
Definition: cs_file.h:76
Definition: cs_file.h:102
const char * cs_file_get_name(const cs_file_t *f)
Return a file's name.
Definition: cs_file.c:1508
int cs_file_mkdir_default(const char *path)
Create a new directory using default permissions.
Definition: cs_file.c:2480
unsigned int cs_file_hints_t
Definition: cs_file.h:86
int cs_file_seek(cs_file_t *f, cs_file_off_t offset, cs_file_seek_t whence)
Update the file pointer according to whence.
Definition: cs_file.c:2042
size_t cs_file_write_global(cs_file_t *f, const void *buf, size_t size, size_t ni)
Write global data to a file.
Definition: cs_file.c:1694
unsigned cs_gnum_t
Definition: cs_defs.h:255
int cs_file_isreg(const char *path)
Check if a file exists and is a regular file.
Definition: cs_file.c:2555
Definition: cs_file.h:80
size_t cs_file_read_global(cs_file_t *f, void *buf, size_t size, size_t ni)
Read global data from a file, distributing it to all processes associated with that file...
Definition: cs_file.c:1600
cs_file_off_t cs_file_tell(cs_file_t *f)
Return the position of the file pointer.
Definition: cs_file.c:2102
#define END_C_DECLS
Definition: cs_defs.h:366
Definition: cs_file.h:101
cs_file_hints_t cs_file_get_default_semantics(void)
Get the default semantics for file access.
Definition: cs_file.c:2156
long cs_file_off_t
Definition: cs_file.h:93
Definition: cs_file.h:100
void cs_file_set_big_endian(cs_file_t *f)
Ensure that data is read or written in big-endian (network standard) format.
Definition: cs_file.c:1525