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
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
 int
 saf_find_collections(SAF_ParMode pmode,         /* The parallel mode. */
                      SAF_Set *containing_set,   /* The containing set in which to search for collections. In SAF_ONE()
                                                  * parallel mode, all processes except the process identified by the
                                                  * rank argument of the SAF_ONE() macro are free to pass SAF_NULL_SET
                                                  * with the set's database handle. */
                      SAF_Role *role,            /* The role of the collection. Pass NULL if you do not wish to
                                                  * limit the search by this parameter. */
                      SAF_CellType cell_type,    /* The cell-type of the members of the collection.  Pass SAF_ANY_CELLTYPE if you
                                                  * do not wish to limit the search by this parameter. */
                      int topo_dim,              /* The topological dimension of the collection. Pass SAF_ANY_TOPODIM if you do not
                                                  * wish to limit the search by this parameter. */
                      SAF_DecompMode decomp_mode,/* Whether the found collections must be a decomposition of the containing set.
                                                  * Pass SAF_DECOMP_TORF if it does not matter. */
                      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_collections, SAF_PRECONDITION_ERROR);
     SAF_KEYMASK(SAF_Cat, cat_key, cat_mask);
     SAF_KEYMASK(SAF_Collection, coll_key, coll_mask);
     ss_catobj_t         *cat_mask_p=NULL, cat_mask_z;
     ss_collectionobj_t  *coll_mask_p=NULL, coll_mask_z;
     size_t              ncolls;                 /* Number of collections in CONTAINING_SET */
     size_t              nfound=0;               /* Number of matches found */
     size_t              limit=SS_NOSIZE;        /* Limit number of matches returned */
     size_t              i;
     ss_collection_t     coll;
     ss_cat_t            cat;

     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_SET(containing_set), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("CONTAINING_SET must be a valid set handle for participating processes"));
     SAF_REQUIRE(_saf_valid_memhints(num, (void**)found), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("NUM_COLLS and CATS 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 if supplied"));

     /* Fill in the collection and category keys with desired information */
     if (cell_type != SAF_CELLTYPE_ANY)
         SAF_SEARCH(SAF_Collection, coll_key, coll_mask, cell_type, cell_type);
     if (topo_dim != SAF_ANY_TOPODIM)
         SAF_SEARCH(SAF_Cat, cat_key, cat_mask, tdim, topo_dim);
     if (decomp_mode != SAF_DECOMP_TORF)
         SAF_SEARCH(SAF_Collection, coll_key, coll_mask, is_decomp, decomp_mode?TRUE:FALSE);

     /* Allocate return value. */
     ncolls = ss_array_nelmts(SS_SET_P(containing_set,colls));
     if (!found) {
         /* Only counting */
         assert(num);
         *num=0;
     } else if (!*found) {
         /* Library allocates results */
         *found = calloc(ncolls, sizeof **found);
         if (num) *num = 0;
     } else {
         /* Client allocated results */
         assert(num);
         assert(*num>=0);
         limit = *num;
         *num = 0;
     }

     /* If the collection or catetory masks are empty then we should pass null for the mask arguments in order to match
      * everything and avoid an error regarding an empty mask. */
     memset(&coll_mask_z, 0, sizeof coll_mask_z);
     memset(&cat_mask_z, 0, sizeof cat_mask_z);
     coll_mask_p = memcmp(&coll_mask, &coll_mask_z, sizeof coll_mask) ? &coll_mask : NULL;
     cat_mask_p = memcmp(&cat_mask, &cat_mask_z, sizeof cat_mask) ? &cat_mask : NULL;

     /* Scan through the collections associated with the containing_set */
     for (i=0; i<ncolls; i++) {
         ss_array_get(SS_SET_P(containing_set,colls), 0, i, 1, &coll);
         cat = SS_COLLECTION(&coll)->cat;

         /* If a role is specified then determine whether it is the same role as what is associated with the cat for this
          * collection for this set. Since  collections of the self category can be explicitly stored in the set's collection
          * list then we have to be prepared for the case when cat->role is a null object link (because the "self" collection
          * category isn't allowed to point to a particular role. */
         if (role) {
             if (SS_PERS_ISNULL(SS_CAT_P(&cat,role))) continue;
             if (!SS_PERS_EQUAL(role, SS_CAT_P(&cat,role))) continue;
         }

         /* Compare the collection and category with the keys we initialized above. */
         if (coll_mask_p && 0!=ss_pers_cmp((ss_pers_t*)&coll, (ss_pers_t*)coll_key, (ss_persobj_t*)coll_mask_p)) continue;
         if (cat_mask_p && 0!=ss_pers_cmp((ss_pers_t*)&cat, (ss_pers_t*)cat_key, (ss_persobj_t*)cat_mask_p)) continue;

         /* Found a match. */
         if (nfound>=limit)
             SAF_ERROR(SAF_CONSTRAINT_ERROR, _saf_errmsg("found too many matching objects"));
         if (found)
             (*found)[nfound] = cat;
         nfound++;
     }

     if (num) *num = nfound;
     SAF_LEAVE(SAF_SUCCESS);
 }