1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
 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);
 }