herr_t
ss_scope_open(ss_scope_t *scope, /* A link to a scope object, probably the result of a /find/ operation. */
unsigned flags, /* Various bit flags to control common scope open switches. */
ss_prop_t *props /* Scope opening properties (see Scope Properties). */
)
{
SS_ENTER(ss_scope_open, herr_t);
MPI_Comm comm=SS_COMM_NULL;
hbool_t comm_duped=FALSE;
ss_gfile_t *gfile=NULL;
unsigned tableidx;
ss_table_t *table=NULL;
const char *scopename=NULL;
SS_ASSERT_MEM(scope, ss_scope_t);
if (NULL==(scopename = ss_string_ptr(SS_SCOPE_P(scope,name)))) scopename="NONAME";
/* Check that the scope is not already open. This will only catch an error if this task had the scope open, but
* quite often it is possible that the scope was opened only on some other task(s). The usual mistake is that all tasks
* open the file with MPI_COMM_SELF, in which case synchronizations don't work properly. */
if (SS_SCOPE(scope)->m.comm != SS_COMM_NULL) SS_ERROR_FMT(PERM, ("already open: %s", scopename));
#ifndef NDEBUG
{
/* These things should have been set when the scope was booted. */
SS_ASSERT(SS_SCOPE(scope)->m.gid>0);
SS_ASSERT(SS_SCOPE(scope)->m.strings);
for (tableidx=0; tableidx<SS_PERS_NCLASSES; tableidx++) {
if (tableidx!=SS_MAGIC_SEQUENCE(SS_MAGIC(ss_scope_t)) && NULL!=SS_PERS_CLASS(tableidx)) {
SS_ASSERT(SS_SCOPE(scope)->m.table[tableidx]);
}
}
}
#endif
/* Check FLAGS compatibility with the file */
if (NULL==(gfile=SS_GFILE_LINK(scope)) || !gfile->topscope) SS_ERROR(NOTFOUND);
SS_ASSERT(gfile && gfile->topscope);
flags &= (H5F_ACC_RDWR|H5F_ACC_DEBUG); /*weed out flags except those we support*/
flags |= (gfile->flags & H5F_ACC_TRANSIENT);
if ((flags & H5F_ACC_RDWR) && 0==(gfile->flags & H5F_ACC_RDWR))
SS_ERROR_FMT(PERM, ("scope cannot be writable in a read-only file: %s", scopename));
/* Obtain the communicator */
if (!props || NULL==ss_prop_get(props, "comm", H5T_NATIVE_MPI_COMM, &comm)) {
SS_STATUS_OK;
comm = SS_SCOPE(gfile->topscope)->m.comm;
comm_duped = FALSE;
} else if (NULL==ss_prop_get(props, "duped", H5T_NATIVE_HBOOL, &comm_duped)) {
SS_STATUS_OK;
comm_duped = FALSE;
}
/* Read all the table data for this scope. We could have delayed this but all tasks will need to have the data anyway when
* they synchronize, which will almost certainly happen before the file is closed. We also have the problem that MPI-IO
* doesn't guarantee that a reader task will see data that was recently written by some other task (some file systems such
* as POSIX do in fact garantee this, while others such as PVFS don't). If the file is read only, then we could easily
* delay the reading of the table until it's actually needed, but even then how often really is it that a scope will be
* opened on multiple tasks but some table not ever accessed? */
for (tableidx=0; tableidx<SS_PERS_NCLASSES; tableidx++) {
if (NULL==SS_PERS_CLASS(tableidx)) continue;
if (NULL==(table=ss_scope_table(scope, tableidx, NULL))) SS_ERROR_FMT(FAILED, ("scope=\"%s\"", scopename));
if (ss_table_read(table, scope)<0) SS_ERROR_FMT(FAILED, ("scope=\"%s\"", scopename));
}
/* Assign the communicator to the scope to mark it as being opened */
SS_SCOPE(scope)->m.comm = comm;
SS_SCOPE(scope)->m.comm_duped = comm_duped;
SS_SCOPE(scope)->m.flags = flags;
SS_CLEANUP:
if (comm_duped && comm!=SS_COMM_NULL) ss_mpi_comm_free(&comm);
SS_LEAVE(0);
}