1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
2 /*
3  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
4  *                         University Research and Technology
5  *                         Corporation.  All rights reserved.
6  * Copyright (c) 2004-2007 The University of Tennessee and The University
7  *                         of Tennessee Research Foundation.  All rights
8  *                         reserved.
9  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
10  *                         University of Stuttgart.  All rights reserved.
11  * Copyright (c) 2004-2005 The Regents of the University of California.
12  *                         All rights reserved.
13  * Copyright (c) 2009      Sun Microsystems, Inc.  All rights reserved.
14  * Copyright (c) 2009-2017 Cisco Systems, Inc.  All rights reserved
15  * Copyright (c) 2015      Research Organization for Information Science
16  *                         and Technology (RIST). All rights reserved.
17  * Copyright (c) 2016      University of Houston. All rights reserved.
18  * Copyright (c) 2016-2017 IBM Corporation. All rights reserved.
19  * $COPYRIGHT$
20  *
21  * Additional copyrights may follow
22  *
23  * $HEADER$
24  */
25 
26 #ifndef OMPI_FILE_H
27 #define OMPI_FILE_H
28 
29 #include "ompi_config.h"
30 #include "mpi.h"
31 #include "opal/class/opal_list.h"
32 #include "ompi/errhandler/errhandler.h"
33 #include "opal/threads/mutex.h"
34 #include "opal/util/info_subscriber.h"
35 #include "ompi/mca/io/io.h"
36 
37 /*
38  * Flags
39  */
40 #define OMPI_FILE_ISCLOSED     0x00000001
41 #define OMPI_FILE_HIDDEN       0x00000002
42 
43 BEGIN_C_DECLS
44 
45 /**
46  * Back-end structure for MPI_File
47  */
48 struct ompi_file_t {
49     /** Base of OBJ_* interface */
50     opal_infosubscriber_t super;
51 
52     /** Communicator that this file was created with */
53     struct ompi_communicator_t *f_comm;
54 
55     /** Filename that this file was created with */
56     char *f_filename;
57 
58     /** Amode that this file was created with */
59     int f_amode;
60 
61     /** Bit flags */
62     int32_t f_flags;
63 
64     /** Index in Fortran <-> C translation array */
65     int f_f_to_c_index;
66 
67     /** Error handler.  This field does not have the "f_" prefix so
68         that the OMPI_ERRHDL_* macros can find it, regardless of
69         whether it's a comm, window, or file. */
70     struct ompi_errhandler_t *error_handler;
71 
72     /** Type of the error handler.  This field does not have the "f_"
73         prefix for the same reason as the field error_handler. */
74     ompi_errhandler_type_t errhandler_type;
75 
76     /** Indicate what version of the IO component we're using (this
77         indicates what member to look at in the union, below) */
78     mca_io_base_version_t f_io_version;
79 
80     /** Mutex to be used to protect access to the selected component
81         on a per file-handle basis */
82     opal_mutex_t f_mutex;
83 
84     /** The selected component (note that this is a union) -- we need
85         this to add and remove the component from the list of
86         components currently in use by the io framework for
87         progression porpoises. */
88     mca_io_base_components_t f_io_selected_component;
89 
90     /** The selected module (note that this is a union) */
91     mca_io_base_modules_t f_io_selected_module;
92 
93     /** Allow the selected module to cache data on the file */
94     struct mca_io_base_file_t *f_io_selected_data;
95 };
96 /**
97  * Convenience typedef
98  */
99 typedef struct ompi_file_t ompi_file_t;
100 
101 /**
102  * Padded struct to maintain back compatibiltiy.
103  * See ompi/communicator/communicator.h comments with struct ompi_communicator_t
104  * for full explanation why we chose the following padding construct for predefines.
105  */
106 #define PREDEFINED_FILE_PAD 1536
107 
108 struct ompi_predefined_file_t {
109     struct ompi_file_t file;
110     char padding[PREDEFINED_FILE_PAD - sizeof(ompi_file_t)];
111 };
112 typedef struct ompi_predefined_file_t ompi_predefined_file_t;
113 
114 /**
115  * Back-end instances for MPI_FILE_NULL (_addr flavor is for F03 bindings)
116  */
117 OMPI_DECLSPEC extern ompi_predefined_file_t  ompi_mpi_file_null;
118 OMPI_DECLSPEC extern ompi_predefined_file_t  *ompi_mpi_file_null_addr;
119 
120 
121 /**
122  * Fortran to C conversion table
123  */
124 extern opal_pointer_array_t ompi_file_f_to_c_table;
125 
126 /**
127  * Initialize MPI_File handling.
128  *
129  * @retval OMPI_SUCCESS Always.
130  *
131  * Invoked during ompi_mpi_init().
132  */
133 int ompi_file_init(void);
134 
135 /**
136  * Back-end to MPI_FILE_OPEN: create a file handle, select an io
137  * component to use, and have that componet open the file.
138  *
139  * @param comm Communicator
140  * @param filename String filename
141  * @param amode Mode flags
142  * @param info Info
143  * @param fh Output file handle
144  *
145  * @retval OMPI_SUCCESS Upon success
146  * @retval OMPI_ERR* Upon error
147  *
148  * Create a file handle and select an io module to be paired with
149  * it.  There is a corresponding ompi_file_close() function; it
150  * mainly calls OBJ_RELEASE() but also does some other error
151  * handling as well.
152  */
153 int ompi_file_open(struct ompi_communicator_t *comm, const char *filename,
154                    int amode, struct opal_info_t *info,
155                    ompi_file_t **fh);
156 
157 /**
158  * Atomicly set a name on a file handle.
159  *
160  * @param file MPI_File handle to set the name on
161  * @param name NULL-terminated string to use
162  *
163  * @returns OMPI_SUCCESS Always.
164  *
165  * At most (MPI_MAX_OBJECT_NAME-1) characters will be copied over to
166  * the file name's name.  This function is performed atomically -- a
167  * lock is used to ensure that there are not multiple writers to the
168  * name to ensure that we don't end up with an erroneous name (e.g.,
169  * a name without a \0 at the end).  After invoking this function,
170  * ompi_file_is_name_set() will return true.
171  */
172 int ompi_file_set_name(ompi_file_t *file, char *name);
173 
174 /**
175  * Back-end to MPI_FILE_CLOSE: destroy an ompi_file_t handle and
176  * close the file.
177  *
178  * @param file Pointer to ompi_file_t
179  *
180  * @returns OMPI_SUCCESS Always.
181  *
182  * This is the preferred mechanism for freeing an ompi_file_t.
183  * Although the main action that it performs is OBJ_RELEASE(), it
184  * also does some additional handling for error checking, etc.
185  */
186 int ompi_file_close(ompi_file_t **file);
187 
188 /**
189  * Tear down MPI_File handling.
190  *
191  * @retval OMPI_SUCCESS Always.
192  *
193  * Invoked during ompi_mpi_finalize().
194  */
195 int ompi_file_finalize(void);
196 
197 /**
198  * Check to see if an MPI_File handle is valid.
199  *
200  * @param file The MPI file handle
201  *
202  * @retval true If the file handle is not valid
203  * @retval false If the file handle is valid
204  *
205  * This is a convenience function, mainly for error checking in
206  * top-level MPI API functions.
207  */
ompi_file_invalid(ompi_file_t * file)208 static inline bool ompi_file_invalid(ompi_file_t *file)
209 {
210     return (NULL == file ||
211             &ompi_mpi_file_null.file == file ||
212             0 != (file->f_flags & OMPI_FILE_ISCLOSED));
213 }
214 
215 END_C_DECLS
216 
217 #endif /* OMPI_FILE_H */
218