1 /* Copyright (c) 2003 by International Business Machines, Inc.
3 * International Business Machines, Inc. (hereinafter called IBM) grants
4 * permission under its copyrights to use, copy, modify, and distribute this
5 * Software with or without fee, provided that the above copyright notice and
6 * all paragraphs of this notice appear in all copies, and that the name of IBM
7 * not be used in connection with the marketing of any product incorporating
8 * the Software or modifications thereof, without specific, written prior
11 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
12 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
13 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
14 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
15 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
16 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
23 #include <ac/string.h>
24 #include <ac/socket.h>
27 #include "../back-ldap/back-ldap.h"
28 #include "back-meta.h"
31 #define MAX_ATTR_SETS 500
32 static void find_supersets( struct attr_set* attr_sets, int numsets );
33 static int compare_sets( struct attr_set* setA, int, int );
36 meta_back_cache_config(
44 struct metainfo *li = ( struct metainfo * )be->be_private;
46 cache_manager* cm = li->cm;
47 query_manager* qm = cm->qm;
49 AttributeName* attr_name;
51 AttributeName* attrarray;
52 const char* text=NULL;
58 fprintf( stderr, "%s: line %d: meta backend info is null!\n",
63 if ( strcasecmp( argv[0], "cacheparams" ) == 0 ) {
64 struct berval cache_suffix;
67 fprintf( stderr, "%s: line %d: missing arguments in \"cacheparams"
68 " <thresh_lo> <thresh_hi> <numattrsets> <entry limit> "
69 "<cycle_time>\" \n", fname, lineno );
74 cm->thresh_lo = atoi( argv[1] );
75 cm->thresh_hi = atoi( argv[2] );
76 if ( cm->thresh_hi <= cm->thresh_lo ) {
77 fprintf( stderr, "%s: line %d: <thresh_lo> must be < <thresh_hi> "
78 "in \"cacheparams <thresh_lo> <thresh_hi> <numattrsets> "
79 "<entry limit> <cycle_time>\" \n", fname, lineno );
83 cm->numattrsets = atoi( argv[3] );
84 if ( cm->numattrsets > MAX_ATTR_SETS ) {
85 fprintf( stderr, "%s: line %d: <numattrsets> must be <= %d in "
86 "\"cacheparams <thresh_lo> <thresh_hi> <numattrsets> "
87 "<entry limit> <cycle_time>\" \n",
88 fname, lineno, MAX_ATTR_SETS );
92 cm->num_entries_limit = atoi( argv[4] );
93 cm->consistency_cycle_time = atoi( argv[5] );
95 LDAP_LOG( BACK_META, DETAIL1,
96 "Total # of attribute sets to be cached = %d\n",
97 cm->numattrsets, 0, 0 );
99 Debug( LDAP_DEBUG_ANY,
100 "Total # of attribute sets to be cached = %d\n",
101 cm->numattrsets, 0, 0 );
103 qm->attr_sets = ( struct attr_set * )malloc( cm->numattrsets *
104 sizeof( struct attr_set ));
105 for ( i = 0; i < cm->numattrsets; i++ ) {
106 qm->attr_sets[i].attrs = NULL;
108 rewrite_session( li->rwinfo, "cacheBase", be->be_nsuffix[0].bv_val,
109 0, &cache_suffix.bv_val );
110 if ( cache_suffix.bv_val != NULL ) {
111 cache_suffix.bv_len = strlen( cache_suffix.bv_val );
113 cache_suffix = be->be_nsuffix[0];
115 li->glue_be = select_backend( &cache_suffix, 0, 1 );
116 if ( cache_suffix.bv_val != be->be_nsuffix[0].bv_val ) {
117 ch_free( cache_suffix.bv_val );
120 } else if ( strcasecmp( argv[0], "attrset" ) == 0 ) {
122 fprintf( stderr, "%s: line %d: missing arguments in \"attr-set "
123 "<index> <attributes>\" line\n", fname, lineno );
127 LDAP_LOG( BACK_META, DETAIL1, "Attribute Set # %d\n",
128 atoi( argv[1] ), 0, 0 );
130 Debug( LDAP_DEBUG_ANY, "Attribute Set # %d\n",
131 atoi( argv[1] ), 0, 0 );
133 if (atoi(argv[1]) >= cm->numattrsets) {
134 fprintf( stderr, "%s; line %d index out of bounds \n",
138 index = atoi( argv[1] );
139 if ( argv[2] && ( strcmp( argv[2], "*" ) != 0 )) {
140 for ( i = 2; argv[i] != NULL; i++ ) {
142 LDAP_LOG( BACK_META, DETAIL1, "\t %s\n",
145 Debug( LDAP_DEBUG_ANY, "\t %s\n",
148 attrs = qm->attr_sets[index].attrs;
149 qm->attr_sets[index].attrs = (AttributeName*)realloc(
150 attrs, i * sizeof( AttributeName ));
151 attr_name = qm->attr_sets[index].attrs + ( i - 2 );
152 ber_str2bv( argv[i], strlen(argv[i]), 1,
153 &attr_name->an_name);
154 attr_name->an_desc = NULL;
155 slap_bv2ad( &attr_name->an_name,
156 &attr_name->an_desc, &text );
158 attr_name->an_name.bv_val = NULL;
159 attr_name->an_name.bv_len = 0;
161 qm->attr_sets[index].count = i - 2;
163 } else if ( strcasecmp( argv[0], "addtemplate" ) == 0 ) {
165 fprintf( stderr, "%s: line %d: missing argument(s) in "
166 "\"addtemplate <filter> <proj attr set> <TTL>\" line\n",
170 if (( i = atoi( argv[2] )) >= cm->numattrsets ) {
172 LDAP_LOG( BACK_META, DETAIL1,
173 "%s: line %d, template index invalid\n",
176 Debug( LDAP_DEBUG_ANY,
177 "%s: line %d, template index invalid\n",
182 num = cm->numtemplates;
184 find_supersets( qm->attr_sets, cm->numattrsets );
185 qm->templates = ( QueryTemplate* )realloc( qm->templates,
186 ( num + 2 ) * sizeof( QueryTemplate ));
187 temp = qm->templates + num;
188 ldap_pvt_thread_rdwr_init( &temp->t_rwlock );
189 temp->query = temp->query_last = NULL;
190 temp->ttl = atoi( argv[3] );
191 temp->no_of_queries = 0;
192 if ( argv[1] == NULL ) {
194 LDAP_LOG( BACK_META, DETAIL1,
195 "Templates string not specified "
196 "for template %d\n", num, 0, 0 );
198 Debug( LDAP_DEBUG_ANY,
199 "Templates string not specified "
200 "for template %d\n", num, 0, 0 );
204 temp->querystr = ch_strdup( argv[1] );
206 LDAP_LOG( BACK_META, DETAIL1, "Template:\n", 0, 0, 0 );
208 Debug( LDAP_DEBUG_ANY, "Template:\n", 0, 0, 0 );
211 LDAP_LOG( BACK_META, DETAIL1, " query template: %s\n",
212 temp->querystr, 0, 0 );
214 Debug( LDAP_DEBUG_ANY, " query template: %s\n",
215 temp->querystr, 0, 0 );
217 temp->attr_set_index = i;
219 LDAP_LOG( BACK_META, DETAIL1, " attributes: \n", 0, 0, 0 );
221 Debug( LDAP_DEBUG_ANY, " attributes: \n", 0, 0, 0 );
223 if ( attrarray = qm->attr_sets[i].attrs ) {
224 for ( i=0; attrarray[i].an_name.bv_val; i++ )
226 LDAP_LOG( BACK_META, DETAIL1, "\t%s\n",
227 attrarray[i].an_name.bv_val, 0, 0 );
229 Debug( LDAP_DEBUG_ANY, "\t%s\n",
230 attrarray[i].an_name.bv_val, 0, 0 );
234 temp->querystr = NULL;
239 fprintf( stderr, "%s: line %d: unknown directive \"%s\" in meta "
240 "database definition (ignored)\n",
241 fname, lineno, argv[0] );
247 find_supersets ( struct attr_set* attr_sets, int numsets )
249 int num[MAX_ATTR_SETS];
252 for ( i = 0; i < MAX_ATTR_SETS; i++ )
255 for ( i = 0; i < numsets; i++ ) {
256 attr_sets[i].ID_array = (int*) malloc( sizeof( int ) );
257 attr_sets[i].ID_array[0] = -1;
260 for ( i = 0; i < numsets; i++ ) {
261 for ( j=i+1; j < numsets; j++ ) {
262 res = compare_sets( attr_sets, i, j );
268 id_array = attr_sets[i].ID_array;
269 attr_sets[i].ID_array = (int *) realloc( id_array,
270 ( num[i] + 2 ) * sizeof( int ));
271 attr_sets[i].ID_array[num[i]] = j;
272 attr_sets[i].ID_array[num[i]+1] = -1;
277 id_array = attr_sets[j].ID_array;
278 attr_sets[j].ID_array = (int *) realloc( id_array,
279 ( num[j] + 2 ) * sizeof( int ));
280 attr_sets[j].ID_array[num[j]] = i;
281 attr_sets[j].ID_array[num[j]+1] = -1;
290 * compares two sets of attributes (indices i and j)
291 * returns 0: if neither set is contained in the other set
292 * 1: if set i is contained in set j
293 * 2: if set j is contained in set i
294 * 3: the sets are equivalent
298 compare_sets(struct attr_set* set, int i, int j)
304 if (( set[i].attrs == NULL ) && ( set[j].attrs == NULL ))
307 if ( set[i].attrs == NULL )
310 if ( set[j].attrs == NULL )
316 for ( l=0; l < numI; l++ ) {
317 for ( k = 0; k < numJ; k++ ) {
318 if ( strcmp( set[i].attrs[l].an_name.bv_val,
319 set[j].attrs[k].an_name.bv_val ) == 0 )
324 if ( common == numI )
327 if ( common == numJ )