root/ompi/file/file.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ompi_file_init
  2. ompi_file_open
  3. ompi_file_close
  4. ompi_file_finalize
  5. file_constructor
  6. file_destructor

   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-2017 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) 2008-2009 Sun Microsystems, Inc.  All rights reserved.
  14  * Copyright (c) 2009-2012 Cisco Systems, Inc.  All rights reserved.
  15  * Copyright (c) 2015-2017 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 #include "ompi_config.h"
  27 
  28 #include "ompi/communicator/communicator.h"
  29 #include "ompi/file/file.h"
  30 #include "opal/class/opal_list.h"
  31 #include "opal/util/output.h"
  32 #include "ompi/runtime/params.h"
  33 #include "ompi/mca/io/base/base.h"
  34 #include "ompi/info/info.h"
  35 
  36 
  37 opal_mutex_t ompi_mpi_file_bootstrap_mutex = OPAL_MUTEX_STATIC_INIT;
  38 
  39 
  40 /*
  41  * Table for Fortran <-> C file handle conversion
  42  */
  43 opal_pointer_array_t ompi_file_f_to_c_table = {{0}};
  44 
  45 /*
  46  * MPI_FILE_NULL (_addr flavor is for F03 bindings)
  47  */
  48 ompi_predefined_file_t  ompi_mpi_file_null = {{{{0}}}};
  49 ompi_predefined_file_t  *ompi_mpi_file_null_addr = &ompi_mpi_file_null;
  50 
  51 
  52 /*
  53  * Local functions
  54  */
  55 static void file_constructor(ompi_file_t *obj);
  56 static void file_destructor(ompi_file_t *obj);
  57 
  58 
  59 /*
  60  * Class instance for ompi_file_t
  61  */
  62 OBJ_CLASS_INSTANCE(ompi_file_t,
  63                    opal_infosubscriber_t,
  64                    file_constructor,
  65                    file_destructor);
  66 
  67 
  68 /*
  69  * Initialize file handling bookeeping
  70  */
  71 int ompi_file_init(void)
  72 {
  73     /* Setup file array */
  74 
  75     OBJ_CONSTRUCT(&ompi_file_f_to_c_table, opal_pointer_array_t);
  76     if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_file_f_to_c_table, 0,
  77                                                 OMPI_FORTRAN_HANDLE_MAX, 16) ) {
  78         return OMPI_ERROR;
  79     }
  80 
  81     /* Setup MPI_FILE_NULL.  Note that it will have the default error
  82        handler of MPI_ERRORS_RETURN, per MPI-2:9.7 (p265).  */
  83 
  84     OBJ_CONSTRUCT(&ompi_mpi_file_null.file, ompi_file_t);
  85     ompi_mpi_file_null.file.f_comm = &ompi_mpi_comm_null.comm;
  86     OBJ_RETAIN(ompi_mpi_file_null.file.f_comm);
  87     ompi_mpi_file_null.file.f_f_to_c_index = 0;
  88     opal_pointer_array_set_item(&ompi_file_f_to_c_table, 0,
  89                                 &ompi_mpi_file_null.file);
  90 
  91     /* All done */
  92 
  93     return OMPI_SUCCESS;
  94 }
  95 
  96 
  97 /*
  98  * Back end to MPI_FILE_OPEN
  99  */
 100 int ompi_file_open(struct ompi_communicator_t *comm, const char *filename,
 101                    int amode, struct opal_info_t *info, ompi_file_t **fh)
 102 {
 103     int ret;
 104     ompi_file_t *file;
 105 
 106     file = OBJ_NEW(ompi_file_t);
 107     if (NULL == file) {
 108         return OMPI_ERR_OUT_OF_RESOURCE;
 109     }
 110 
 111 
 112     /* Save the params */
 113 
 114     file->f_comm = comm;
 115     OBJ_RETAIN(comm);
 116 
 117     /* Copy the info for the info layer */
 118     file->super.s_info = OBJ_NEW(opal_info_t);
 119     if (info) {
 120         opal_info_dup(info, &(file->super.s_info));
 121     }
 122 
 123     file->f_amode = amode;
 124     file->f_filename = strdup(filename);
 125     if (NULL == file->f_filename) {
 126         OBJ_RELEASE(file);
 127         return OMPI_ERR_OUT_OF_RESOURCE;
 128     }
 129 
 130     /* Create the mutex */
 131     OBJ_CONSTRUCT(&file->f_lock, opal_mutex_t);
 132 
 133     /* Select a module and actually open the file */
 134 
 135     if (OMPI_SUCCESS != (ret = mca_io_base_file_select(file, NULL))) {
 136         OBJ_RELEASE(file);
 137         return ret;
 138     }
 139 
 140     /* All done */
 141 
 142     *fh = file;
 143     return OMPI_SUCCESS;
 144 }
 145 
 146 
 147 /*
 148  * Back end to MPI_FILE_CLOSE.
 149  */
 150 int ompi_file_close(ompi_file_t **file)
 151 {
 152 
 153     OBJ_DESTRUCT(&(*file)->f_lock);
 154 
 155     (*file)->f_flags |= OMPI_FILE_ISCLOSED;
 156     OBJ_RELEASE(*file);
 157     *file = &ompi_mpi_file_null.file;
 158 
 159     return OMPI_SUCCESS;
 160 }
 161 
 162 
 163 /*
 164  * Shut down the MPI_File bookkeeping
 165  */
 166 int ompi_file_finalize(void)
 167 {
 168     int i, max;
 169     size_t num_unnamed;
 170     ompi_file_t *file;
 171 
 172     /* Release MPI_FILE_NULL.  Do this so that we don't get a bogus leak
 173        report on it.  Plus, it's statically allocated, so we don't want
 174      to call OBJ_RELEASE on it. */
 175 
 176     OBJ_DESTRUCT(&ompi_mpi_file_null.file);
 177     opal_pointer_array_set_item(&ompi_file_f_to_c_table, 0, NULL);
 178 
 179     /* Iterate through all the file handles and destroy them.  Note
 180        that this also takes care of destroying MPI_FILE_NULL. */
 181 
 182     max = opal_pointer_array_get_size(&ompi_file_f_to_c_table);
 183     for (num_unnamed = i = 0; i < max; ++i) {
 184         file = (ompi_file_t *)opal_pointer_array_get_item(&ompi_file_f_to_c_table, i);
 185 
 186         /* If the file was closed but still exists because the user
 187            told us to never free handles, then do an OBJ_RELEASE it
 188            and all is well.  Then get the value again and see if it's
 189            actually been freed. */
 190 
 191         if (NULL != file && ompi_debug_no_free_handles &&
 192             0 == (file->f_flags & OMPI_FILE_ISCLOSED)) {
 193             OBJ_RELEASE(file);
 194             file = (ompi_file_t *)opal_pointer_array_get_item(&ompi_file_f_to_c_table, i);
 195         }
 196 
 197         if (NULL != file) {
 198 
 199             /* If the user wanted warnings about MPI object leaks,
 200                print out a message */
 201 
 202             if (ompi_debug_show_handle_leaks) {
 203                 ++num_unnamed;
 204             }
 205 
 206             OBJ_RELEASE(file);
 207         }
 208         /* Don't bother setting each element back down to NULL; it
 209            would just take a lot of thread locks / unlocks and since
 210            we're destroying everything, it isn't worth it */
 211     }
 212     if (num_unnamed > 0) {
 213         opal_output(0, "WARNING: %lu unnamed MPI_File handles still allocated at MPI_FINALIZE", (unsigned long)num_unnamed);
 214     }
 215     OBJ_DESTRUCT(&ompi_file_f_to_c_table);
 216 
 217     /* All done */
 218 
 219     return OMPI_SUCCESS;
 220 }
 221 
 222 
 223 /*
 224  * Constructor
 225  */
 226 static void file_constructor(ompi_file_t *file)
 227 {
 228     /* Initialize the MPI_FILE_OPEN params */
 229 
 230     file->f_comm = NULL;
 231     file->f_filename = NULL;
 232     file->f_amode = 0;
 233 
 234     /* Initialize flags */
 235 
 236     file->f_flags = 0;
 237 
 238     /* Initialize the fortran <--> C translation index */
 239 
 240     file->f_f_to_c_index = opal_pointer_array_add(&ompi_file_f_to_c_table,
 241                                                   file);
 242 
 243     /* Initialize the error handler.  Per MPI-2:9.7 (p265), the
 244        default error handler on file handles is the error handler on
 245        MPI_FILE_NULL, which starts out as MPI_ERRORS_RETURN (but can
 246        be changed by invoking MPI_FILE_SET_ERRHANDLER on
 247        MPI_FILE_NULL). */
 248 
 249     file->errhandler_type = OMPI_ERRHANDLER_TYPE_FILE;
 250     if (file != &ompi_mpi_file_null.file) {
 251         file->error_handler = ompi_mpi_file_null.file.error_handler;
 252     } else {
 253         file->error_handler = &ompi_mpi_errors_return.eh;
 254     }
 255     OBJ_RETAIN(file->error_handler);
 256 
 257     /* Initialize the module */
 258 
 259     file->f_io_version = MCA_IO_BASE_V_NONE;
 260     memset(&(file->f_io_selected_module), 0,
 261            sizeof(file->f_io_selected_module));
 262     file->f_io_selected_data = NULL;
 263 
 264     /* If the user doesn't want us to ever free it, then add an extra
 265        RETAIN here */
 266 
 267     if (ompi_debug_no_free_handles) {
 268         OBJ_RETAIN(&(file->super));
 269     }
 270 }
 271 
 272 
 273 /*
 274  * Destructor
 275  */
 276 static void file_destructor(ompi_file_t *file)
 277 {
 278     /* Finalize the module */
 279 
 280     switch (file->f_io_version) {
 281     case MCA_IO_BASE_V_2_0_0:
 282         file->f_io_selected_module.v2_0_0.io_module_file_close(file);
 283         break;
 284     default:
 285         /* Should never get here */
 286         break;
 287     }
 288 
 289     /* Finalize the data members */
 290 
 291     if (NULL != file->f_comm) {
 292         OBJ_RELEASE(file->f_comm);
 293 #if OPAL_ENABLE_DEBUG
 294         file->f_comm = NULL;
 295 #endif
 296     }
 297 
 298     if (NULL != file->f_filename) {
 299         free(file->f_filename);
 300 #if OPAL_ENABLE_DEBUG
 301         file->f_filename = NULL;
 302 #endif
 303     }
 304 
 305     if (NULL != file->error_handler) {
 306         OBJ_RELEASE(file->error_handler);
 307 #if OPAL_ENABLE_DEBUG
 308         file->error_handler = NULL;
 309 #endif
 310     }
 311 
 312     if (NULL != file->super.s_info) {
 313         OBJ_RELEASE(file->super.s_info);
 314 #if OPAL_ENABLE_DEBUG
 315         file->super.s_info = NULL;
 316 #endif
 317     }
 318 
 319     /* Reset the f_to_c table entry */
 320 
 321     if (MPI_UNDEFINED != file->f_f_to_c_index &&
 322         NULL != opal_pointer_array_get_item(&ompi_file_f_to_c_table,
 323                                             file->f_f_to_c_index)) {
 324         opal_pointer_array_set_item(&ompi_file_f_to_c_table,
 325                                     file->f_f_to_c_index, NULL);
 326     }
 327 }

/* [<][>][^][v][top][bottom][index][help] */