herr_t
ss_init_func(MPI_Comm communicator /* Library communicator defining the maximal set of MPI tasks that can be involved in
* various collective SSlib function calls. However, many collective SSlib functions
* can operate on a subset of this communicator. If SSlib is implicitly initialized
* then MPI_COMM_WORLD is assumed. When SSlib is compiled without MPI support then the
* COMMUNICATOR argument is just an integer that's ignored by this function. */
)
{
SS_ENTER(ss_init_func, herr_t);
ss_prop_t *tfile_props=NULL;
MPI_Comm selfcomm=SS_COMM_SELF;
size_t nbits;
int self=0, ntasks=1;
/* This is `static' so that we can edit the default path directly in the library binary if necessary. */
static char cfile_name[2048] = SS_INSTALL_SYSCONFDIR "/include/sslib.conf\0"
"*** PRECEDING STRING IS 2048 BYTES TOTAL ***";
if (sslib_g.initialized) SS_ERROR_FMT(INIT, ("the library is already initialized"));
sslib_g.command_fd = -1;
sslib_g.warnings = fdopen(2, "w");
#ifdef HAVE_PARALLEL
MPI_Comm_rank(communicator, &self);
MPI_Comm_size(communicator, &ntasks);
if (MPI_Comm_dup(communicator, &(sslib_g.comm))) SS_ERROR(MPI);
#endif
/* Set the HDF5 automatic error reporting. We can't do this directly with H5Eset_auto() because the SS_LEAVE() macro will
* clobber that. */
SS_ASSERT(1==sslib_g.call_depth); /*not really necessary, but will catch any potential problems from changing SS_LEAVE() */
_efunc = ss_err_print;
_edata = &ss_err_cntl_g;
/* Initialize the job-wide serial numbers. The high order bits are the MPI rank number of this task within the library
* communicator and the low order bits are initialized to zero. Whenever you need a unique number, just increment the
* serial number. */
for (nbits=0; nbits<8*sizeof(sslib_g.serial) && (size_t)(ntasks-1)>>nbits!=0; nbits++) /*void*/;
sslib_g.serial = (size_t)self << (8*sizeof(sslib_g.serial) - nbits);
/* Configure the library first by reading the configuration file and then by processing the SSLIB_DEBUG environment
* variable. If the library isn't installed yet then the configuration file will be located in the source directory,
* so look in the installation directory first, then the source directory. If the file can't be found then complain but
* don't fail. */
if (access(cfile_name, F_OK)<0) {
strncpy(cfile_name, SS_INSTALL_SRCDIR "/sslib/lib/sslib.conf", sizeof cfile_name);
if (access(cfile_name, F_OK)<0) {
#ifndef PRODUCTION_COMPILE
fprintf(sslib_g.warnings, "SSlib-%d: unable to find sslib.conf file in %s or %s.\n",
self, SS_INSTALL_SYSCONFDIR "/include/", cfile_name);
fprintf(sslib_g.warnings, "SSlib-%d: The libss binary can be edited to fix the search path.\n", self);
#endif
cfile_name[0] = '\0';
}
}
if (cfile_name[0] && ss_config(communicator, cfile_name)<0) SS_ERROR(FAILED);
if (ss_debug_env(communicator, NULL)<0) SS_ERROR(FAILED);
#ifdef HAVE_PARALLEL
/* Create the MPI error handler and set it for this communicator. We save the error handler handle because we'll also use
* it when setting the error handler for other communicators, such as scope communicators. */
if (!sslib_g.ignore_mpierror) {
#if 1 /*from MPICH header file*/
MPI_Errhandler_create(ss_err_mpierror, &(sslib_g.ehandler));
MPI_Errhandler_set(sslib_g.comm, sslib_g.ehandler);
#else /*from "MPI: The Complete Reference: Vol 1" by Mark Snir et al*/
MPI_Comm_create_errhandler(ss_err_mpierror, &(sslib_g.ehandler));
MPI_Comm_set_errhandler(sslib_g.comm, sslib_g.ehandler);
#endif
}
#else
sslib_g.comm = SS_COMM_SELF;
#endif /*HAVE_PARALLEL*/
/* Initialize subsystems -- we can be pretty lazy here because most of them auto initialize properly. The only time they
* don't get initialized as they should is when a subsystem exports a global variable and that global variable is used by
* some other subsystem before any function of that subsystem is called. */
if (ss_mpi_init()<0) SS_ERROR(FAILED);
if (ss_pers_init()<0) SS_ERROR(FAILED);
if (ss_attr_init()<0) SS_ERROR(FAILED);
/* Initialize Library-Wide 2-Phase I/O Defaults and process the SSLIB_2PIO environment variable. */
if (ss_blob_set_2pio(NULL, NULL)<0) SS_ERROR(FAILED);
/* Create a transient file on each task */
if (NULL==(tfile_props=ss_prop_new(SS_PERTASK_FILENAME ".props"))) SS_ERROR(FAILED);
if (ss_prop_add(tfile_props, "comm", H5T_NATIVE_MPI_COMM, &selfcomm)<0) SS_ERROR(FAILED);
if (NULL==(sslib_g.temp.file=ss_file_create(SS_PERTASK_FILENAME, H5F_ACC_TRANSIENT, tfile_props))) SS_ERROR(FAILED);
if (NULL==(sslib_g.temp.tscope=ss_file_topscope(sslib_g.temp.file, NULL))) SS_ERROR(FAILED);
if (ss_prop_dest(tfile_props)<0) SS_ERROR(FAILED);
tfile_props = NULL;
/* Print the welcome banner */
if (sslib_g.banner && 0==ss_mpi_comm_rank(communicator)) fprintf(stderr, "SSlib-0: %s\n", sslib_g.banner);
/* All was successful. Consider the library initialized. Stuff after here uses the SSlib API. */
sslib_g.initialized = TRUE;
SS_CLEANUP:
if (tfile_props) ss_prop_dest(tfile_props);
SS_LEAVE(0);
}