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
85
86
87
88
89
90
 int
 saf_find_categories(SAF_ParMode pmode,
                     SAF_Db *db,                 /* Database on which to restrict the search. */
                     SAF_Set *containing_set,    /* The set upon which to restrict the search. The special macro SAF_UNIVERSE(db)
                                                  * (which takes a database handle as an argument) allows the search to span
                                                  * all categories of the specified database. */
                     const char *name,           /* The name of the categories upon which to restrict the search. The constant
                                                  * SAF_ANY_NAME allows the search to span categories with any name. */
                     SAF_Role *role,             /* The role of the categories upon which to restrict the search. A null pointer
                                                  * allows the search to span categories with any role (see
                                                  * Collection Roles). */
                     int tdim,                   /* The topological dimension of the categories upon which to restrict the
                                                  * search. The constant SAF_ANY_TOPODIM allows the search to span categories
                                                  * with any topological dimension. */
                     int *num,                   /* For this and the succeeding argument [see Returned Handles]. */
                     SAF_Cat **found             /* For this and the preceding  argument [see Returned Handles]. */
                     )
 {
   SAF_ENTER(saf_find_categories, SAF_PRECONDITION_ERROR);
   SAF_KEYMASK(SAF_Cat, key, mask);
   size_t                nfound=SS_NOSIZE;
   ss_scope_t            scope=SS_SCOPE_NULL;
   size_t                i, j;
   ss_collection_t       coll;
   SAF_Cat               *cats=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(_saf_valid_memhints(num, (void**)found), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
               _saf_errmsg("NUM and FOUND must be compatible for return value allocation"));
   SAF_REQUIRE(!role || SS_ROLE(role), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
               _saf_errmsg("ROLE must be a valid role handle or NULL"));
   SAF_REQUIRE(!containing_set || SS_SET(containing_set), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
               _saf_errmsg("CONTAINING_SET must be a valid set handle or NULL"));

   /* fill in appropriate members for the find call */
   if (name)
       SAF_SEARCH_S(SAF_Cat, key, mask, name, name);
   if (tdim != SAF_ANY_TOPODIM)
       SAF_SEARCH(SAF_Cat, key, mask, tdim, tdim);
   if (role)
       SAF_SEARCH_LINK(SAF_Cat, key, mask, role, *role); /*search with `equal' not `eq', thus SAF_SEARCH_LINK() not SAF_SEARCH() */

   /* Get all categories that match (do not limit the results) because we'll need to prune that list against the CONTAINING_SET
    * if there was one. */
   ss_file_topscope(db, &scope);
   cats = (ss_cat_t*)ss_pers_find(&scope, (ss_pers_t*)key, mask_count?(ss_persobj_t*)&mask:NULL, 0, &nfound, NULL, NULL);
   if (!cats) SAF_ERROR(SAF_FILE_ERROR, _saf_errmsg("find failed"));

   /*If containing_set is an actual set (and not SAF_UNIVERSE(db)), then remove all
     categories from the list that are not in collections on the set*/
   if (containing_set && !_saf_is_universe(containing_set)) {
       for (i=j=0; i<nfound; i++) {
           if (_saf_getCollection_set(containing_set, cats+i, &coll)) {
               if (i!=j) cats[j] = cats[i];
               j++;
           }
       }
       nfound = j;
   }

   /*   Return only what the caller asked for...
    */
   if (!found) {
       /* Count the matches */
       assert(num);
       *num = nfound;
   } else if (!*found) {
       /* Library allocates results */
       *found = cats;
       cats = NULL;
       if (num) *num = nfound;
   } else {
       /* Find limited matches; client allocates result buffer */
       assert(num);
       if (nfound>(size_t)*num)
           SAF_ERROR(SAF_CONSTRAINT_ERROR, _saf_errmsg("found too many matching objects"));
       memcpy(*found, cats, nfound*sizeof(*cats));
       *num = nfound;
   }

   /*  Cleanup...
    *  ...file handles if they wern't passed back
    */
   cats = SS_FREE(cats);
   SAF_LEAVE(SAF_SUCCESS);
 }