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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
 int
 saf_find_subset_relations(SAF_ParMode pmode,    /* The parallel mode. */
                           SAF_Db *db,           /* Database in which to limit the search. */
                           SAF_Set *sup,         /* The superset to limit search to. */
                           SAF_Set *sub,         /* The subset to limit search to. */
                           SAF_Cat *sup_cat,     /* The collection category on the superset to limit search to. Pass
                                                  * SAF_ANY_CAT if you do not want to limit the search to any particular
                                                  * category. */
                           SAF_Cat *sub_cat,     /* The collection category on the subset to limit search to. Pass SAF_ANY_CAT
                                                  * if you do not want to limit the search to any particular category. */
                           SAF_BoundMode sbmode, /* If SAF_BOUNDARY_TRUE, limit search to relations in which the subset is the
                                                  * boundary of the superset. */
                           SAF_BoundMode cbmode, /* If SAF_BOUNDARY_TRUE, limit search to relations in which the members of the
                                                  * subset are on the boundaries of the members of the superset. */
                           int *num,             /* For this and the succeeding argument, (see Returned Handles). */
                           SAF_Rel **found       /* For this and the preceding argument, (see Returned Handles). */
                           )
 {
     SAF_ENTER(saf_find_subset_relations, SAF_PRECONDITION_ERROR);
     SAF_KEYMASK(SAF_Rel, key, mask);
     size_t      nfound;
     ss_scope_t  scope=SS_SCOPE_NULL;

     SAF_REQUIRE(_saf_valid_pmode(pmode), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("PMODE must be valid"));
     if (!_saf_is_participating_proc(pmode)) SAF_RETURN(-1);
     SAF_REQUIRE(ss_file_isopen(db, NULL)>0, SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("DB must be a valid database"));
     SAF_REQUIRE(!sup_cat || SS_CAT(sup_cat), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("SUP_CAT must either be a valid category handle or SAF_ANY_CAT"));
     SAF_REQUIRE(!sub_cat || SS_CAT(sub_cat), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("SUB_CAT must either be a valid category handle or SAF_ANY_CAT"));
     SAF_REQUIRE(SS_SET(sub), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("SUB must be a valid set handle"));
     SAF_REQUIRE(SS_SET(sup), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("SUP must be a valid set handle"));
     SAF_REQUIRE(_saf_valid_memhints(num, (void**)found), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("NUM and FOUND must be compatible for the return value allocation"));

     ss_file_topscope(db, &scope);

     /* See if the superset's bnd_set matches the sbmode search criteria. */
     if ((sbmode==SAF_BOUNDARY_TRUE && SAF_EQUIV(SS_SET_P(sup,bnd_set),sub)) || sbmode==SAF_BOUNDARY_FALSE) {
         /* The sbmode search criteria matches.  Continue to find the subset relations matching the other criteria. */
         SAF_SEARCH(SAF_Rel, key, mask, sub, *sub);
         SAF_SEARCH(SAF_Rel, key, mask, sup, *sup);
         if (sup_cat) SAF_SEARCH(SAF_Rel, key, mask, sup_cat, *sup_cat);
         if (sub_cat) SAF_SEARCH(SAF_Rel, key, mask, sub_cat, *sub_cat);
         SAF_SEARCH(SAF_Rel, key, mask, kind, cbmode==SAF_BOUNDARY_TRUE?SAF_RELKIND_BOUND:SAF_RELKIND_EQUAL);

         if (!found) {
             /* Count the matches */
             assert(num);
             nfound = SS_NOSIZE;
             ss_pers_find(&scope, (ss_pers_t*)key, mask_count?(ss_persobj_t*)&mask:NULL, 0, &nfound, SS_PERS_TEST, NULL);
             *num = nfound;
         } else if (!*found) {
             /* Find all matches; library allocates results */
             nfound = SS_NOSIZE;
             *found = (ss_rel_t*)ss_pers_find(&scope, (ss_pers_t*)key, mask_count?(ss_persobj_t*)&mask:NULL, 0, &nfound,
                                              NULL, NULL);
             if (num) *num = nfound;
         } else {
             /* Find limited matches; client allocates result buffer */
             assert(num);
             nfound = *num;
             if (NULL==ss_pers_find(&scope, (ss_pers_t*)key, mask_count?(ss_persobj_t*)&mask:NULL, 0, &nfound, (ss_pers_t*)*found,
                                    _SAF_GLOBALS.find_detect_overflow)) {
                 SAF_ERROR(SAF_CONSTRAINT_ERROR, _saf_errmsg("found too many matching objects"));
             }
             *num = nfound;
         }
     } else {
         if (!found || *found) {
             /* Count the matches or client allocates result buffer */
             assert(num);
             *num = 0;
         } else {
             /* library allocates results */
             if (num) *num = nfound;
         }
     }
     SAF_LEAVE(SAF_SUCCESS);
 }