1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 #include "mpioimpl.h"
7 
8 #ifdef HAVE_WEAK_SYMBOLS
9 
10 #if defined(HAVE_PRAGMA_WEAK)
11 #pragma weak MPI_File_open = PMPI_File_open
12 #elif defined(HAVE_PRAGMA_HP_SEC_DEF)
13 #pragma _HP_SECONDARY_DEF PMPI_File_open MPI_File_open
14 #elif defined(HAVE_PRAGMA_CRI_DUP)
15 #pragma _CRI duplicate MPI_File_open as PMPI_File_open
16 /* end of weak pragmas */
17 #elif defined(HAVE_WEAK_ATTRIBUTE)
18 int MPI_File_open(MPI_Comm comm, const char *filename, int amode, MPI_Info info, MPI_File * fh)
19     __attribute__ ((weak, alias("PMPI_File_open")));
20 #endif
21 
22 /* Include mapping from MPI->PMPI */
23 #define MPIO_BUILD_PROFILING
24 #include "mpioprof.h"
25 #endif
26 
27 /* for user-definde reduce operator */
28 #include "adio_extern.h"
29 
30 
31 extern int ADIO_Init_keyval;
32 
33 /*@
34     MPI_File_open - Opens a file
35 
36 Input Parameters:
37 . comm - communicator (handle)
38 . filename - name of file to open (string)
39 . amode - file access mode (integer)
40 . info - info object (handle)
41 
42 Output Parameters:
43 . fh - file handle (handle)
44 
45 .N fortran
46 @*/
MPI_File_open(MPI_Comm comm,ROMIO_CONST char * filename,int amode,MPI_Info info,MPI_File * fh)47 int MPI_File_open(MPI_Comm comm, ROMIO_CONST char *filename, int amode,
48                   MPI_Info info, MPI_File * fh)
49 {
50     int error_code = MPI_SUCCESS, file_system, flag, tmp_amode = 0, rank;
51     char *tmp;
52     MPI_Comm dupcomm = MPI_COMM_NULL;
53     ADIOI_Fns *fsops;
54     static char myname[] = "MPI_FILE_OPEN";
55 #ifdef MPI_hpux
56     int fl_xmpi;
57 
58     HPMP_IO_OPEN_START(fl_xmpi, comm);
59 #endif /* MPI_hpux */
60 
61     ROMIO_THREAD_CS_ENTER();
62 
63     /* --BEGIN ERROR HANDLING-- */
64     MPIO_CHECK_COMM(comm, myname, error_code);
65     MPIO_CHECK_INFO_ALL(info, error_code, comm);
66     /* --END ERROR HANDLING-- */
67 
68     error_code = MPI_Comm_test_inter(comm, &flag);
69     /* --BEGIN ERROR HANDLING-- */
70     if (error_code || flag) {
71         error_code = MPIO_Err_create_code(error_code, MPIR_ERR_RECOVERABLE,
72                                           myname, __LINE__, MPI_ERR_COMM, "**commnotintra", 0);
73         goto fn_fail;
74     }
75 
76     if (((amode & MPI_MODE_RDONLY) ? 1 : 0) + ((amode & MPI_MODE_RDWR) ? 1 : 0) +
77         ((amode & MPI_MODE_WRONLY) ? 1 : 0) != 1) {
78         error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
79                                           myname, __LINE__, MPI_ERR_AMODE, "**fileamodeone", 0);
80         goto fn_fail;
81     }
82 
83     if ((amode & MPI_MODE_RDONLY) && ((amode & MPI_MODE_CREATE) || (amode & MPI_MODE_EXCL))) {
84         error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
85                                           myname, __LINE__, MPI_ERR_AMODE, "**fileamoderead", 0);
86         goto fn_fail;
87     }
88 
89     if ((amode & MPI_MODE_RDWR) && (amode & MPI_MODE_SEQUENTIAL)) {
90         error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
91                                           myname, __LINE__, MPI_ERR_AMODE, "**fileamodeseq", 0);
92         goto fn_fail;
93     }
94 
95     MPI_Comm_dup(comm, &dupcomm);
96 
97 /* check if ADIO has been initialized. If not, initialize it */
98     MPIR_MPIOInit(&error_code);
99     if (error_code != MPI_SUCCESS)
100         goto fn_fail;
101 
102 /* check if amode is the same on all processes: at first glance, one might try
103  * to use a built-in operator like MPI_BAND, but we need every mpi process to
104  * agree the amode was not the same.  Consider process A with
105  * MPI_MODE_CREATE|MPI_MODE_RDWR, and B with MPI_MODE_RDWR:  MPI_BAND yields
106  * MPI_MODE_RDWR.  A determines amodes are different, but B proceeds having not
107  * detected an error */
108     MPI_Allreduce(&amode, &tmp_amode, 1, MPI_INT, ADIO_same_amode, dupcomm);
109 
110     if (tmp_amode == ADIO_AMODE_NOMATCH) {
111         error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
112                                           myname, __LINE__, MPI_ERR_NOT_SAME, "**fileamodediff", 0);
113         goto fn_fail;
114     }
115     /* --END ERROR HANDLING-- */
116 
117     file_system = -1;
118 
119     /* resolve file system type from file name; this is a collective call */
120     ADIO_ResolveFileType(dupcomm, filename, &file_system, &fsops, &error_code);
121     /* --BEGIN ERROR HANDLING-- */
122     if (error_code != MPI_SUCCESS) {
123         /* ADIO_ResolveFileType() will print as informative a message as it
124          * possibly can or call MPIO_Err_setmsg.  We just need to propagate
125          * the error up.
126          */
127         goto fn_fail;
128     }
129 
130     /* --END ERROR HANDLING-- */
131 
132     /* strip off prefix if there is one, but only skip prefixes
133      * if they are greater than length one to allow for windows
134      * drive specifications (e.g. c:\...) */
135 
136     tmp = strchr(filename, ':');
137     if (tmp > filename + 1) {
138         filename = tmp + 1;
139     }
140 
141 /* use default values for disp, etype, filetype */
142 
143     *fh = ADIO_Open(comm, dupcomm, filename, file_system, fsops, amode, 0,
144                     MPI_BYTE, MPI_BYTE, info, ADIO_PERM_NULL, &error_code);
145 
146     /* --BEGIN ERROR HANDLING-- */
147     if (error_code != MPI_SUCCESS) {
148         goto fn_fail;
149     }
150     /* --END ERROR HANDLING-- */
151 
152     /* if MPI_MODE_SEQUENTIAL requested, file systems cannot do explicit offset
153      * or independent file pointer accesses, leaving not much else aside from
154      * shared file pointer accesses. */
155     if (!ADIO_Feature((*fh), ADIO_SHARED_FP) && (amode & MPI_MODE_SEQUENTIAL)) {
156         error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
157                                           myname, __LINE__,
158                                           MPI_ERR_UNSUPPORTED_OPERATION, "**iosequnsupported", 0);
159         ADIO_Close(*fh, &error_code);
160         goto fn_fail;
161     }
162 
163     /* determine name of file that will hold the shared file pointer */
164     /* can't support shared file pointers on a file system that doesn't
165      * support file locking. */
166     if ((error_code == MPI_SUCCESS) && ADIO_Feature((*fh), ADIO_SHARED_FP)) {
167         MPI_Comm_rank(dupcomm, &rank);
168         ADIOI_Shfp_fname(*fh, rank, &error_code);
169         if (error_code != MPI_SUCCESS)
170             goto fn_fail;
171 
172         /* if MPI_MODE_APPEND, set the shared file pointer to end of file.
173          * indiv. file pointer already set to end of file in ADIO_Open.
174          * Here file view is just bytes. */
175         if ((*fh)->access_mode & MPI_MODE_APPEND) {
176             if (rank == (*fh)->hints->ranklist[0])      /* only one person need set the sharedfp */
177                 ADIO_Set_shared_fp(*fh, (*fh)->fp_ind, &error_code);
178             MPI_Barrier(dupcomm);
179         }
180     }
181 #ifdef MPI_hpux
182     HPMP_IO_OPEN_END(fl_xmpi, *fh, comm);
183 #endif /* MPI_hpux */
184 
185   fn_exit:
186     ROMIO_THREAD_CS_EXIT();
187     return error_code;
188   fn_fail:
189     /* --BEGIN ERROR HANDLING-- */
190     if (dupcomm != MPI_COMM_NULL)
191         MPI_Comm_free(&dupcomm);
192     error_code = MPIO_Err_return_file(MPI_FILE_NULL, error_code);
193     goto fn_exit;
194     /* --END ERROR HANDLING-- */
195 }
196