herr_t
ss_file_synchronize(ss_file_t *file, /* The file to synchronize. */
ss_prop_t *props /* Optional synchronization properties. */
)
{
SS_ENTER(ss_file_synchronize, herr_t);
ss_scope_sync_t sync_data; /* Stuff to pass through ss_table_scan() */
ss_table_t *scopetab=NULL; /* The top-scope's scope table */
unsigned tableidx; /* Counter through valid tables of each scope */
ss_scope_t topscope; /* Top scope of FILE */
static ss_prop_t *syncprops=NULL;
int pass=0, old_transient_errors=0;
if (!syncprops) {
if (NULL==(syncprops=ss_prop_new(_func))) SS_ERROR(FAILED);
if (ss_prop_add(syncprops, "err_newptrs", H5T_NATIVE_INT, NULL)<0) SS_ERROR(FAILED);
}
if (!props) props = syncprops;
if (ss_file_isopen(file, NULL)<=0) SS_ERROR_FMT(PERM, ("FILE is not open"));
/* If the file is read-only there should be nothing to do. However, it is still possible that the client modified the
* object anyway and the only possible way to detect that is to attempt to synchronize. So if the library is compiled for
* debugging then we'll descend, otherwise we'll return now. */
#ifdef NDEBUG
if (!ss_file_iswritable(file)) goto done;
#endif
/* Synchronize the top scope's scope table. This is file-collective because the top scope's communicator is the file
* communicator. */
if (NULL==ss_file_topscope(file, &topscope)) SS_ERROR(FAILED);
if (ss_scope_synchronize(&topscope, SS_MAGIC(ss_scope_t), props)<0) SS_ERROR(FAILED);
if (NULL==(scopetab=ss_scope_table(&topscope, SS_MAGIC(ss_scope_t), NULL))) SS_ERROR(FAILED);
/* Now synchronize the rest of the tables. The outer loop is per table while the inner loop is per scope. This will
* minimize the number of references to unsynchronized objects when one scope points to objects in another scope. */
memset(&sync_data, 0, sizeof sync_data);
sync_data.props = props;
while (pass++<10) {
sync_data.transient_errors = 0;
for (tableidx=0; tableidx<SS_PERS_NCLASSES; tableidx++) {
if (!SS_PERS_CLASS(tableidx)) continue;
if (tableidx==SS_MAGIC_SEQUENCE(SS_MAGIC(ss_scopeobj_t))) continue; /*already synced*/
sync_data.tableidx = tableidx;
if (ss_table_scan(scopetab, &topscope, 0, ss_scope_synchronize_cb, &sync_data)<0) SS_ERROR(FAILED);
}
if (0==sync_data.transient_errors) break;
if (pass>0 && sync_data.transient_errors==old_transient_errors)
SS_ERROR_FMT(FAILED, ("unable to resolve inter-file cycles in the object graph"));
old_transient_errors = sync_data.transient_errors;
}
#ifdef NDEBUG
done:
#endif
SS_CLEANUP:
SS_LEAVE(0);
}