2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2003 The OpenLDAP Foundation.
5 * Portions Copyright 2003 IBM Corporation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
17 * This work was initially developed by the Apurva Kumar for inclusion
18 * in OpenLDAP Software.
25 #include <ac/string.h>
26 #include <ac/socket.h>
29 #include "../back-ldap/back-ldap.h"
30 #include "back-meta.h"
32 #define MAX_ATTR_SETS 500
33 static void find_supersets( struct attr_set* attr_sets, int numsets );
34 static int compare_sets( struct attr_set* setA, int, int );
37 meta_back_cache_config(
45 struct metainfo *li = ( struct metainfo * )be->be_private;
47 cache_manager* cm = li->cm;
48 query_manager* qm = cm->qm;
50 AttributeName* attr_name;
52 AttributeName* attrarray;
53 const char* text=NULL;
59 fprintf( stderr, "%s: line %d: meta backend info is null!\n",
64 if ( strcasecmp( argv[0], "cacheparams" ) == 0 ) {
65 struct berval cache_suffix;
68 fprintf( stderr, "%s: line %d: missing arguments in \"cacheparams"
69 " <thresh_lo> <thresh_hi> <numattrsets> <entry limit> "
70 "<cycle_time>\" \n", fname, lineno );
75 cm->thresh_lo = atoi( argv[1] );
76 cm->thresh_hi = atoi( argv[2] );
77 if ( cm->thresh_hi <= cm->thresh_lo ) {
78 fprintf( stderr, "%s: line %d: <thresh_lo> must be < <thresh_hi> "
79 "in \"cacheparams <thresh_lo> <thresh_hi> <numattrsets> "
80 "<entry limit> <cycle_time>\" \n", fname, lineno );
84 cm->numattrsets = atoi( argv[3] );
85 if ( cm->numattrsets > MAX_ATTR_SETS ) {
86 fprintf( stderr, "%s: line %d: <numattrsets> must be <= %d in "
87 "\"cacheparams <thresh_lo> <thresh_hi> <numattrsets> "
88 "<entry limit> <cycle_time>\" \n",
89 fname, lineno, MAX_ATTR_SETS );
93 cm->num_entries_limit = atoi( argv[4] );
94 cm->cc_period = atoi( argv[5] );
96 LDAP_LOG( BACK_META, DETAIL1,
97 "Total # of attribute sets to be cached = %d\n",
98 cm->numattrsets, 0, 0 );
100 Debug( LDAP_DEBUG_ANY,
101 "Total # of attribute sets to be cached = %d\n",
102 cm->numattrsets, 0, 0 );
104 qm->attr_sets = ( struct attr_set * )malloc( cm->numattrsets *
105 sizeof( struct attr_set ));
106 for ( i = 0; i < cm->numattrsets; i++ ) {
107 qm->attr_sets[i].attrs = NULL;
109 rewrite_session( li->rwinfo, "cacheBase", be->be_nsuffix[0].bv_val,
110 0, &cache_suffix.bv_val );
111 if ( cache_suffix.bv_val != NULL ) {
112 cache_suffix.bv_len = strlen( cache_suffix.bv_val );
114 cache_suffix = be->be_nsuffix[0];
116 li->glue_be = select_backend( &cache_suffix, 0, 1 );
117 li->glue_be->be_flags |= SLAP_BFLAG_NO_SCHEMA_CHECK;
118 if ( cache_suffix.bv_val != be->be_nsuffix[0].bv_val ) {
119 ch_free( cache_suffix.bv_val );
122 } else if ( strcasecmp( argv[0], "attrset" ) == 0 ) {
124 fprintf( stderr, "%s: line %d: missing arguments in \"attr-set "
125 "<index> <attributes>\" line\n", fname, lineno );
129 LDAP_LOG( BACK_META, DETAIL1, "Attribute Set # %d\n",
130 atoi( argv[1] ), 0, 0 );
132 Debug( LDAP_DEBUG_ANY, "Attribute Set # %d\n",
133 atoi( argv[1] ), 0, 0 );
135 if (atoi(argv[1]) >= cm->numattrsets) {
136 fprintf( stderr, "%s; line %d index out of bounds \n",
140 index = atoi( argv[1] );
141 if ( argv[2] && ( strcmp( argv[2], "*" ) != 0 )) {
142 for ( i = 2; argv[i] != NULL; i++ ) {
144 LDAP_LOG( BACK_META, DETAIL1, "\t %s\n",
147 Debug( LDAP_DEBUG_ANY, "\t %s\n",
150 attrs = qm->attr_sets[index].attrs;
151 qm->attr_sets[index].attrs = (AttributeName*)realloc(
152 attrs, i * sizeof( AttributeName ));
153 attr_name = qm->attr_sets[index].attrs + ( i - 2 );
154 ber_str2bv( argv[i], strlen(argv[i]), 1,
155 &attr_name->an_name);
156 attr_name->an_desc = NULL;
157 slap_bv2ad( &attr_name->an_name,
158 &attr_name->an_desc, &text );
160 attr_name->an_name.bv_val = NULL;
161 attr_name->an_name.bv_len = 0;
163 qm->attr_sets[index].count = i - 2;
165 } else if ( strcasecmp( argv[0], "addtemplate" ) == 0 ) {
167 fprintf( stderr, "%s: line %d: missing argument(s) in "
168 "\"addtemplate <filter> <proj attr set> <TTL>\" line\n",
172 if (( i = atoi( argv[2] )) >= cm->numattrsets ) {
174 LDAP_LOG( BACK_META, DETAIL1,
175 "%s: line %d, template index invalid\n",
178 Debug( LDAP_DEBUG_ANY,
179 "%s: line %d, template index invalid\n",
184 num = cm->numtemplates;
186 find_supersets( qm->attr_sets, cm->numattrsets );
187 qm->templates = ( QueryTemplate* )realloc( qm->templates,
188 ( num + 2 ) * sizeof( QueryTemplate ));
189 temp = qm->templates + num;
190 ldap_pvt_thread_rdwr_init( &temp->t_rwlock );
191 temp->query = temp->query_last = NULL;
192 temp->ttl = atoi( argv[3] );
193 temp->no_of_queries = 0;
194 if ( argv[1] == NULL ) {
196 LDAP_LOG( BACK_META, DETAIL1,
197 "Templates string not specified "
198 "for template %d\n", num, 0, 0 );
200 Debug( LDAP_DEBUG_ANY,
201 "Templates string not specified "
202 "for template %d\n", num, 0, 0 );
206 temp->querystr = ch_strdup( argv[1] );
208 LDAP_LOG( BACK_META, DETAIL1, "Template:\n", 0, 0, 0 );
210 Debug( LDAP_DEBUG_ANY, "Template:\n", 0, 0, 0 );
213 LDAP_LOG( BACK_META, DETAIL1, " query template: %s\n",
214 temp->querystr, 0, 0 );
216 Debug( LDAP_DEBUG_ANY, " query template: %s\n",
217 temp->querystr, 0, 0 );
219 temp->attr_set_index = i;
221 LDAP_LOG( BACK_META, DETAIL1, " attributes: \n", 0, 0, 0 );
223 Debug( LDAP_DEBUG_ANY, " attributes: \n", 0, 0, 0 );
225 if ( ( attrarray = qm->attr_sets[i].attrs ) != NULL ) {
226 for ( i=0; attrarray[i].an_name.bv_val; i++ )
228 LDAP_LOG( BACK_META, DETAIL1, "\t%s\n",
229 attrarray[i].an_name.bv_val, 0, 0 );
231 Debug( LDAP_DEBUG_ANY, "\t%s\n",
232 attrarray[i].an_name.bv_val, 0, 0 );
236 temp->querystr = NULL;
241 fprintf( stderr, "%s: line %d: unknown directive \"%s\" in meta "
242 "database definition (ignored)\n",
243 fname, lineno, argv[0] );
249 find_supersets ( struct attr_set* attr_sets, int numsets )
251 int num[MAX_ATTR_SETS];
254 for ( i = 0; i < MAX_ATTR_SETS; i++ )
257 for ( i = 0; i < numsets; i++ ) {
258 attr_sets[i].ID_array = (int*) malloc( sizeof( int ) );
259 attr_sets[i].ID_array[0] = -1;
262 for ( i = 0; i < numsets; i++ ) {
263 for ( j=i+1; j < numsets; j++ ) {
264 res = compare_sets( attr_sets, i, j );
270 id_array = attr_sets[i].ID_array;
271 attr_sets[i].ID_array = (int *) realloc( id_array,
272 ( num[i] + 2 ) * sizeof( int ));
273 attr_sets[i].ID_array[num[i]] = j;
274 attr_sets[i].ID_array[num[i]+1] = -1;
279 id_array = attr_sets[j].ID_array;
280 attr_sets[j].ID_array = (int *) realloc( id_array,
281 ( num[j] + 2 ) * sizeof( int ));
282 attr_sets[j].ID_array[num[j]] = i;
283 attr_sets[j].ID_array[num[j]+1] = -1;
292 * compares two sets of attributes (indices i and j)
293 * returns 0: if neither set is contained in the other set
294 * 1: if set i is contained in set j
295 * 2: if set j is contained in set i
296 * 3: the sets are equivalent
300 compare_sets(struct attr_set* set, int i, int j)
306 if (( set[i].attrs == NULL ) && ( set[j].attrs == NULL ))
309 if ( set[i].attrs == NULL )
312 if ( set[j].attrs == NULL )
318 for ( l=0; l < numI; l++ ) {
319 for ( k = 0; k < numJ; k++ ) {
320 if ( strcmp( set[i].attrs[l].an_name.bv_val,
321 set[j].attrs[k].an_name.bv_val ) == 0 )
326 if ( common == numI )
329 if ( common == numJ )