]> git.sur5r.net Git - openldap/blob - servers/slapd/back-meta/cache-config.c
Notices and acknowledgements
[openldap] / servers / slapd / back-meta / cache-config.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2003 The OpenLDAP Foundation.
5  * Portions Copyright 2003 IBM Corporation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
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>.
15  */
16 /* ACKNOWLEDGEMENTS:
17  * This work was initially developed by the Apurva Kumar for inclusion
18  * in OpenLDAP Software.
19  */
20
21 #include "portable.h"
22
23 #include <stdio.h>
24
25 #include <ac/string.h>
26 #include <ac/socket.h>
27
28 #include "slap.h"
29 #include "../back-ldap/back-ldap.h"
30 #include "back-meta.h"
31
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 );
35
36 int
37 meta_back_cache_config(
38         BackendDB       *be,
39         const char      *fname,
40         int             lineno,
41         int             argc,
42         char            **argv
43 )
44 {
45         struct metainfo *li = ( struct metainfo * )be->be_private;
46
47         cache_manager*  cm = li->cm; 
48         query_manager*  qm = cm->qm;
49         QueryTemplate*  temp;
50         AttributeName*  attr_name; 
51         AttributeName*  attrs;
52         AttributeName*  attrarray;
53         const char*     text=NULL; 
54
55         int             index, i; 
56         int             num; 
57
58         if ( li == NULL ) {
59                 fprintf( stderr, "%s: line %d: meta backend info is null!\n",
60                                 fname, lineno );
61                 return 1;
62         }
63
64         if ( strcasecmp( argv[0], "cacheparams" ) == 0 ) {
65                 struct berval cache_suffix; 
66
67                 if ( argc < 6 ) {
68                         fprintf( stderr, "%s: line %d: missing arguments in \"cacheparams"
69                                 " <thresh_lo> <thresh_hi> <numattrsets> <entry limit> "
70                                 "<cycle_time>\" \n", fname, lineno );
71                         return( 1 );
72                 }
73
74                 cm->caching = 1;  
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 );
81                         return( 1 );
82                 }
83
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 );
90                         return( 1 );
91                 }
92
93                 cm->num_entries_limit = atoi( argv[4] ); 
94                 cm->cc_period = atoi( argv[5] ); 
95 #ifdef NEW_LOGGING
96                 LDAP_LOG( BACK_META, DETAIL1,
97                                 "Total # of attribute sets to be cached = %d\n",
98                                 cm->numattrsets, 0, 0 ); 
99 #else
100                 Debug( LDAP_DEBUG_ANY,
101                                 "Total # of attribute sets to be cached = %d\n",
102                                 cm->numattrsets, 0, 0 ); 
103 #endif
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; 
108                 }
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 );
113                 } else {
114                         cache_suffix = be->be_nsuffix[0];
115                 }
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 );
120                 }
121
122         } else if ( strcasecmp( argv[0], "attrset" ) == 0 ) {
123                 if ( argc < 3 ) {
124                         fprintf( stderr, "%s: line %d: missing arguments in \"attr-set "
125                                 "<index> <attributes>\" line\n", fname, lineno );
126                         return( 1 );
127                 }
128 #ifdef NEW_LOGGING
129                 LDAP_LOG( BACK_META, DETAIL1, "Attribute Set # %d\n",
130                                 atoi( argv[1] ), 0, 0 ); 
131 #else
132                 Debug( LDAP_DEBUG_ANY, "Attribute Set # %d\n",
133                                 atoi( argv[1] ), 0, 0 ); 
134 #endif
135                 if (atoi(argv[1]) >= cm->numattrsets) {
136                         fprintf( stderr, "%s; line %d index out of bounds \n",
137                                         fname, lineno );
138                         return 1; 
139                 } 
140                 index = atoi( argv[1] );
141                 if ( argv[2] && ( strcmp( argv[2], "*" ) != 0 )) {
142                         for ( i = 2; argv[i] != NULL; i++ ) {
143 #ifdef NEW_LOGGING
144                                 LDAP_LOG( BACK_META, DETAIL1, "\t %s\n",
145                                                 argv[i], 0, 0 );
146 #else
147                                 Debug( LDAP_DEBUG_ANY, "\t %s\n",
148                                                 argv[i], 0, 0 );
149 #endif
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 );
159                                 attr_name++; 
160                                 attr_name->an_name.bv_val = NULL; 
161                                 attr_name->an_name.bv_len = 0; 
162                         }
163                         qm->attr_sets[index].count = i - 2; 
164                 }
165         } else if ( strcasecmp( argv[0], "addtemplate" ) == 0 ) {
166                 if ( argc != 4 ) {
167                         fprintf( stderr, "%s: line %d: missing argument(s) in "
168                                 "\"addtemplate <filter> <proj attr set> <TTL>\" line\n",
169                                 fname, lineno );
170                         return( 1 );
171                 }
172                 if (( i = atoi( argv[2] )) >= cm->numattrsets ) {
173 #ifdef NEW_LOGGING
174                         LDAP_LOG( BACK_META, DETAIL1,
175                                         "%s: line %d, template index invalid\n",
176                                         fname, lineno, 0 );  
177 #else
178                         Debug( LDAP_DEBUG_ANY,
179                                         "%s: line %d, template index invalid\n",
180                                         fname, lineno, 0 );  
181 #endif
182                         return 1; 
183                 }
184                 num = cm->numtemplates; 
185                 if ( num == 0 )
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 ) {
195 #ifdef NEW_LOGGING
196                         LDAP_LOG( BACK_META, DETAIL1,
197                                         "Templates string not specified "
198                                         "for template %d\n", num, 0, 0 ); 
199 #else
200                         Debug( LDAP_DEBUG_ANY,
201                                         "Templates string not specified "
202                                         "for template %d\n", num, 0, 0 ); 
203 #endif
204                         return 1; 
205                 }
206                 temp->querystr = ch_strdup( argv[1] );
207 #ifdef NEW_LOGGING
208                 LDAP_LOG( BACK_META, DETAIL1, "Template:\n", 0, 0, 0 );
209 #else
210                 Debug( LDAP_DEBUG_ANY, "Template:\n", 0, 0, 0 );
211 #endif
212 #ifdef NEW_LOGGING
213                 LDAP_LOG( BACK_META, DETAIL1, "  query template: %s\n",
214                                 temp->querystr, 0, 0 );
215 #else
216                 Debug( LDAP_DEBUG_ANY, "  query template: %s\n",
217                                 temp->querystr, 0, 0 );
218 #endif
219                 temp->attr_set_index = i; 
220 #ifdef NEW_LOGGING
221                 LDAP_LOG( BACK_META, DETAIL1, "  attributes: \n", 0, 0, 0 );
222 #else
223                 Debug( LDAP_DEBUG_ANY, "  attributes: \n", 0, 0, 0 );
224 #endif
225                 if ( ( attrarray = qm->attr_sets[i].attrs ) != NULL ) {
226                         for ( i=0; attrarray[i].an_name.bv_val; i++ ) 
227 #ifdef NEW_LOGGING
228                                 LDAP_LOG( BACK_META, DETAIL1, "\t%s\n",
229                                         attrarray[i].an_name.bv_val, 0, 0 );
230 #else
231                                 Debug( LDAP_DEBUG_ANY, "\t%s\n",
232                                         attrarray[i].an_name.bv_val, 0, 0 );
233 #endif
234                 }
235                 temp++;         
236                 temp->querystr = NULL; 
237                 cm->numtemplates++;
238         } 
239         /* anything else */
240         else {
241                 fprintf( stderr, "%s: line %d: unknown directive \"%s\" in meta "
242                                 "database definition (ignored)\n",
243                                 fname, lineno, argv[0] );
244         }
245         return 0;
246 }
247
248 void
249 find_supersets ( struct attr_set* attr_sets, int numsets )
250 {
251         int num[MAX_ATTR_SETS];
252         int i, j, res;
253         int* id_array;
254         for ( i = 0; i < MAX_ATTR_SETS; i++ )
255                 num[i] = 0;
256
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; 
260         } 
261
262         for ( i = 0; i < numsets; i++ ) {
263                 for ( j=i+1; j < numsets; j++ ) {
264                         res = compare_sets( attr_sets, i, j ); 
265                         switch ( res ) {
266                         case 0:
267                                 break;
268                         case 3: 
269                         case 1: 
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; 
275                                 num[i]++;
276                                 if (res == 1) 
277                                         break;
278                         case 2: 
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; 
284                                 num[j]++;
285                                 break;
286                         }
287                 }
288         }
289 }
290
291 /* 
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 
297  */
298
299 int 
300 compare_sets(struct attr_set* set, int i, int j)
301 {
302         int k,l,numI,numJ;
303         int common=0;
304         int result=0;
305
306         if (( set[i].attrs == NULL ) && ( set[j].attrs == NULL ))
307                 return 3;       
308
309         if ( set[i].attrs == NULL )
310                 return 2; 
311
312         if ( set[j].attrs == NULL )
313                 return 1; 
314    
315         numI = set[i].count; 
316         numJ = set[j].count; 
317
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 )
322                                 common++;       
323                 }
324         }
325
326         if ( common == numI )
327                 result = 1; 
328
329         if ( common == numJ )
330                 result += 2;
331
332         return result; 
333 }