]> git.sur5r.net Git - openldap/blob - servers/slapd/back-meta/cache-config.c
Berkeley DB 4.2 support (DB 4.2 required by default)
[openldap] / servers / slapd / back-meta / cache-config.c
1 /* Copyright (c) 2003 by International Business Machines, Inc.
2  *
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
9  * permission.
10  *
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.
17  */
18
19 #include "portable.h"
20
21 #include <stdio.h>
22
23 #include <ac/string.h>
24 #include <ac/socket.h>
25
26 #include "slap.h"
27 #include "../back-ldap/back-ldap.h"
28 #include "back-meta.h"
29
30 #define MAX_ATTR_SETS 500 
31 static void find_supersets( struct attr_set* attr_sets, int numsets ); 
32 static int compare_sets( struct attr_set* setA, int, int );
33
34 int
35 meta_back_cache_config(
36         BackendDB       *be,
37         const char      *fname,
38         int             lineno,
39         int             argc,
40         char            **argv
41 )
42 {
43         struct metainfo *li = ( struct metainfo * )be->be_private;
44
45         cache_manager*  cm = li->cm; 
46         query_manager*  qm = cm->qm;
47         QueryTemplate*  temp;
48         AttributeName*  attr_name; 
49         AttributeName*  attrs;
50         AttributeName*  attrarray;
51         const char*     text=NULL; 
52
53         int             index, i; 
54         int             num; 
55
56         if ( li == NULL ) {
57                 fprintf( stderr, "%s: line %d: meta backend info is null!\n",
58                                 fname, lineno );
59                 return 1;
60         }
61
62         if ( strcasecmp( argv[0], "cacheparams" ) == 0 ) {
63                 struct berval cache_suffix; 
64
65                 if ( argc < 6 ) {
66                         fprintf( stderr, "%s: line %d: missing arguments in \"cacheparams"
67                                 " <thresh_lo> <thresh_hi> <numattrsets> <entry limit> "
68                                 "<cycle_time>\" \n", fname, lineno );
69                         return( 1 );
70                 }
71
72                 cm->caching = 1;  
73                 cm->thresh_lo = atoi( argv[1] );
74                 cm->thresh_hi = atoi( argv[2] );
75                 if ( cm->thresh_hi <= cm->thresh_lo ) {
76                         fprintf( stderr, "%s: line %d: <thresh_lo> must be < <thresh_hi> "
77                                 "in \"cacheparams <thresh_lo> <thresh_hi> <numattrsets> "
78                                 "<entry limit> <cycle_time>\" \n", fname, lineno );
79                         return( 1 );
80                 }
81
82                 cm->numattrsets = atoi( argv[3] );
83                 if ( cm->numattrsets > MAX_ATTR_SETS ) {
84                         fprintf( stderr, "%s: line %d: <numattrsets> must be <= %d in "
85                                 "\"cacheparams <thresh_lo> <thresh_hi> <numattrsets> "
86                                 "<entry limit> <cycle_time>\" \n",
87                                 fname, lineno, MAX_ATTR_SETS );
88                         return( 1 );
89                 }
90
91                 cm->num_entries_limit = atoi( argv[4] ); 
92                 cm->cc_period = atoi( argv[5] ); 
93 #ifdef NEW_LOGGING
94                 LDAP_LOG( BACK_META, DETAIL1,
95                                 "Total # of attribute sets to be cached = %d\n",
96                                 cm->numattrsets, 0, 0 ); 
97 #else
98                 Debug( LDAP_DEBUG_ANY,
99                                 "Total # of attribute sets to be cached = %d\n",
100                                 cm->numattrsets, 0, 0 ); 
101 #endif
102                 qm->attr_sets = ( struct attr_set * )malloc( cm->numattrsets *
103                                                 sizeof( struct attr_set ));
104                 for ( i = 0; i < cm->numattrsets; i++ ) {
105                         qm->attr_sets[i].attrs = NULL; 
106                 }
107                 rewrite_session( li->rwinfo, "cacheBase", be->be_nsuffix[0].bv_val,
108                                         0, &cache_suffix.bv_val );
109                 if ( cache_suffix.bv_val != NULL ) {
110                         cache_suffix.bv_len = strlen( cache_suffix.bv_val );
111                 } else {
112                         cache_suffix = be->be_nsuffix[0];
113                 }
114                 li->glue_be = select_backend( &cache_suffix, 0, 1 );
115                 li->glue_be->be_flags |= SLAP_BFLAG_NO_SCHEMA_CHECK;
116                 if ( cache_suffix.bv_val != be->be_nsuffix[0].bv_val ) {
117                         ch_free( cache_suffix.bv_val );
118                 }
119
120         } else if ( strcasecmp( argv[0], "attrset" ) == 0 ) {
121                 if ( argc < 3 ) {
122                         fprintf( stderr, "%s: line %d: missing arguments in \"attr-set "
123                                 "<index> <attributes>\" line\n", fname, lineno );
124                         return( 1 );
125                 }
126 #ifdef NEW_LOGGING
127                 LDAP_LOG( BACK_META, DETAIL1, "Attribute Set # %d\n",
128                                 atoi( argv[1] ), 0, 0 ); 
129 #else
130                 Debug( LDAP_DEBUG_ANY, "Attribute Set # %d\n",
131                                 atoi( argv[1] ), 0, 0 ); 
132 #endif
133                 if (atoi(argv[1]) >= cm->numattrsets) {
134                         fprintf( stderr, "%s; line %d index out of bounds \n",
135                                         fname, lineno );
136                         return 1; 
137                 } 
138                 index = atoi( argv[1] );
139                 if ( argv[2] && ( strcmp( argv[2], "*" ) != 0 )) {
140                         for ( i = 2; argv[i] != NULL; i++ ) {
141 #ifdef NEW_LOGGING
142                                 LDAP_LOG( BACK_META, DETAIL1, "\t %s\n",
143                                                 argv[i], 0, 0 );
144 #else
145                                 Debug( LDAP_DEBUG_ANY, "\t %s\n",
146                                                 argv[i], 0, 0 );
147 #endif
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 );
157                                 attr_name++; 
158                                 attr_name->an_name.bv_val = NULL; 
159                                 attr_name->an_name.bv_len = 0; 
160                         }
161                         qm->attr_sets[index].count = i - 2; 
162                 }
163         } else if ( strcasecmp( argv[0], "addtemplate" ) == 0 ) {
164                 if ( argc != 4 ) {
165                         fprintf( stderr, "%s: line %d: missing argument(s) in "
166                                 "\"addtemplate <filter> <proj attr set> <TTL>\" line\n",
167                                 fname, lineno );
168                         return( 1 );
169                 }
170                 if (( i = atoi( argv[2] )) >= cm->numattrsets ) {
171 #ifdef NEW_LOGGING
172                         LDAP_LOG( BACK_META, DETAIL1,
173                                         "%s: line %d, template index invalid\n",
174                                         fname, lineno, 0 );  
175 #else
176                         Debug( LDAP_DEBUG_ANY,
177                                         "%s: line %d, template index invalid\n",
178                                         fname, lineno, 0 );  
179 #endif
180                         return 1; 
181                 }
182                 num = cm->numtemplates; 
183                 if ( num == 0 )
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 ) {
193 #ifdef NEW_LOGGING
194                         LDAP_LOG( BACK_META, DETAIL1,
195                                         "Templates string not specified "
196                                         "for template %d\n", num, 0, 0 ); 
197 #else
198                         Debug( LDAP_DEBUG_ANY,
199                                         "Templates string not specified "
200                                         "for template %d\n", num, 0, 0 ); 
201 #endif
202                         return 1; 
203                 }
204                 temp->querystr = ch_strdup( argv[1] );
205 #ifdef NEW_LOGGING
206                 LDAP_LOG( BACK_META, DETAIL1, "Template:\n", 0, 0, 0 );
207 #else
208                 Debug( LDAP_DEBUG_ANY, "Template:\n", 0, 0, 0 );
209 #endif
210 #ifdef NEW_LOGGING
211                 LDAP_LOG( BACK_META, DETAIL1, "  query template: %s\n",
212                                 temp->querystr, 0, 0 );
213 #else
214                 Debug( LDAP_DEBUG_ANY, "  query template: %s\n",
215                                 temp->querystr, 0, 0 );
216 #endif
217                 temp->attr_set_index = i; 
218 #ifdef NEW_LOGGING
219                 LDAP_LOG( BACK_META, DETAIL1, "  attributes: \n", 0, 0, 0 );
220 #else
221                 Debug( LDAP_DEBUG_ANY, "  attributes: \n", 0, 0, 0 );
222 #endif
223                 if ( ( attrarray = qm->attr_sets[i].attrs ) != NULL ) {
224                         for ( i=0; attrarray[i].an_name.bv_val; i++ ) 
225 #ifdef NEW_LOGGING
226                                 LDAP_LOG( BACK_META, DETAIL1, "\t%s\n",
227                                         attrarray[i].an_name.bv_val, 0, 0 );
228 #else
229                                 Debug( LDAP_DEBUG_ANY, "\t%s\n",
230                                         attrarray[i].an_name.bv_val, 0, 0 );
231 #endif
232                 }
233                 temp++;         
234                 temp->querystr = NULL; 
235                 cm->numtemplates++;
236         } 
237         /* anything else */
238         else {
239                 fprintf( stderr, "%s: line %d: unknown directive \"%s\" in meta "
240                                 "database definition (ignored)\n",
241                                 fname, lineno, argv[0] );
242         }
243         return 0;
244 }
245
246 void
247 find_supersets ( struct attr_set* attr_sets, int numsets )
248 {
249         int num[MAX_ATTR_SETS];
250         int i, j, res;
251         int* id_array;
252         for ( i = 0; i < MAX_ATTR_SETS; i++ )
253                 num[i] = 0;
254
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; 
258         } 
259
260         for ( i = 0; i < numsets; i++ ) {
261                 for ( j=i+1; j < numsets; j++ ) {
262                         res = compare_sets( attr_sets, i, j ); 
263                         switch ( res ) {
264                         case 0:
265                                 break;
266                         case 3: 
267                         case 1: 
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; 
273                                 num[i]++;
274                                 if (res == 1) 
275                                         break;
276                         case 2: 
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; 
282                                 num[j]++;
283                                 break;
284                         }
285                 }
286         }
287 }
288
289 /* 
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 
295  */
296
297 int 
298 compare_sets(struct attr_set* set, int i, int j)
299 {
300         int k,l,numI,numJ;
301         int common=0;
302         int result=0;
303
304         if (( set[i].attrs == NULL ) && ( set[j].attrs == NULL ))
305                 return 3;       
306
307         if ( set[i].attrs == NULL )
308                 return 2; 
309
310         if ( set[j].attrs == NULL )
311                 return 1; 
312    
313         numI = set[i].count; 
314         numJ = set[j].count; 
315
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 )
320                                 common++;       
321                 }
322         }
323
324         if ( common == numI )
325                 result = 1; 
326
327         if ( common == numJ )
328                 result += 2;
329
330         return result; 
331 }