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
 int
 saf_find_alternate_indexspecs(SAF_ParMode pmode,        /* The parallel mode */
                               SAF_Set *containing_set,  /* The containing set of the collection.*/
                               SAF_Cat *cat,             /* The collection category. */
                               const char *name_grep,    /* The name of the alt index spec you wish to search for. Pass NULL if
                                                          * you do not wish to limit the search via a name. */
                               int *num,                 /* For this and the succeeding argument [see Returned Handles]. */
                               SAF_AltIndexSpec **found  /* For this and the preceding argument [see Returned Handles]. */
                               )
 {
     SAF_ENTER(saf_find_alternate_indexspecs, SAF_PRECONDITION_ERROR);
     SAF_KEYMASK(SAF_AltIndexSpec, key, mask);
     ss_collection_t     coll=SS_COLLECTION_NULL;
     ss_indexspec_t      *ispec=NULL;
     size_t              nispecs=0, i;

     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(_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"));

     if (!_saf_is_self_decomp(cat)) {
         /* Get the array of index specifications for the collection. Skip the first one, which is the default index spec. */
         if (NULL==_saf_getCollection_set(containing_set, cat, &coll))
             SAF_ERROR(SAF_FILE_ERROR, _saf_errmsg("unable to get collection"));
         nispecs = ss_array_nelmts(SS_COLLECTION_P(&coll,indexing));
         nispecs -= 1;
         ispec = ss_array_get(SS_COLLECTION_P(&coll,indexing), ss_pers_tm, (size_t)1, nispecs, NULL);

         /* If a name is supplied then prune the return value according to that name (or regular expression). Prune in such a
          * way as to keep the index specs in their definition order. */
         if (name_grep) {
             if ('@'==*name_grep) {
                 SAF_SEARCH_RE(SAF_AltIndexSpec, key, mask, name, name_grep+1);
             } else {
                 SAF_SEARCH_S(SAF_AltIndexSpec, key, mask, name, name_grep);
             }
             i=0;
             while (i<nispecs) {
                 if (0==ss_pers_cmp((ss_pers_t*)ispec+i, (ss_pers_t*)key, (ss_persobj_t*)&mask)) {
                     i++;
                 } else {
                     --nispecs;
                     memmove(ispec+i, ispec+i+1, (nispecs-i)*sizeof(*ispec));
                 }
             }
         }
     }

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

     SS_FREE(ispec);
     SAF_LEAVE(SAF_SUCCESS);
 }