]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/monitor.c
return structuralObjectClass errors
[openldap] / servers / slapd / back-bdb / monitor.c
1 /* monitor.c - monitor bdb backend */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2000-2006 The OpenLDAP Foundation.
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
17 #include "portable.h"
18
19 #include <stdio.h>
20 #include <ac/string.h>
21 #include <ac/unistd.h>
22 #include <ac/stdlib.h>
23 #include <ac/errno.h>
24 #include <sys/stat.h>
25 #include "lutil.h"
26 #include "back-bdb.h"
27
28 #include "../back-monitor/back-monitor.h"
29
30 static ObjectClass              *oc_olmBDBDatabase;
31
32 static AttributeDescription     *ad_olmBDBEntryCache,
33         *ad_olmBDBEntryInfo, *ad_olmBDBIDLCache,
34         *ad_olmDbDirectory;
35
36 /*
37  * NOTE: there's some confusion in monitor OID arc;
38  * by now, let's consider:
39  * 
40  * Subsystems monitor attributes        1.3.6.1.4.1.4203.666.1.55.0
41  * Databases monitor attributes         1.3.6.1.4.1.4203.666.1.55.0.1
42  * BDB database monitor attributes      1.3.6.1.4.1.4203.666.1.55.0.1.1
43  *
44  * Subsystems monitor objectclasses     1.3.6.1.4.1.4203.666.3.16.0
45  * Databases monitor objectclasses      1.3.6.1.4.1.4203.666.3.16.0.1
46  * BDB database monitor objectclasses   1.3.6.1.4.1.4203.666.3.16.0.1.1
47  */
48
49 static struct {
50         char                    *name;
51         char                    *oid;
52 }               s_oid[] = {
53         { "olmBDBAttributes",                   "olmDatabaseAttributes:1" },
54         { "olmBDBObjectClasses",                "olmDatabaseObjectClasses:1" },
55
56         { NULL }
57 };
58
59 static struct {
60         char                    *desc;
61         AttributeDescription    **ad;
62 }               s_at[] = {
63         { "( olmBDBAttributes:1 "
64                 "NAME ( 'olmBDBEntryCache' ) "
65                 "DESC 'Number of items in Entry Cache' "
66                 "SUP monitorCounter "
67                 "NO-USER-MODIFICATION "
68                 "USAGE directoryOperation )",
69                 &ad_olmBDBEntryCache },
70
71         { "( olmBDBAttributes:2 "
72                 "NAME ( 'olmBDBEntryInfo' ) "
73                 "DESC 'Number of items in EntryInfo Cache' "
74                 "SUP monitorCounter "
75                 "NO-USER-MODIFICATION "
76                 "USAGE directoryOperation )",
77                 &ad_olmBDBEntryInfo },
78
79         { "( olmBDBAttributes:3 "
80                 "NAME ( 'olmBDBIDLCache' ) "
81                 "DESC 'Number of items in IDL Cache' "
82                 "SUP monitorCounter "
83                 "NO-USER-MODIFICATION "
84                 "USAGE directoryOperation )",
85                 &ad_olmBDBIDLCache },
86
87         { "( olmBDBAttributes:4 "
88                 "NAME ( 'olmDbDirectory' ) "
89                 "DESC 'Path name of the directory "
90                         "where the database environment resides' "
91                 "SUP monitoredInfo "
92                 "NO-USER-MODIFICATION "
93                 "USAGE directoryOperation )",
94                 &ad_olmDbDirectory },
95
96         { NULL }
97 };
98
99 static struct {
100         char            *desc;
101         ObjectClass     **oc;
102 }               s_oc[] = {
103         /* augments an existing object, so it must be AUXILIARY
104          * FIXME: derive from some ABSTRACT "monitoredEntity"? */
105         { "( olmBDBObjectClasses:1 "
106                 "NAME ( 'olmBDBDatabase' ) "
107                 "SUP top AUXILIARY "
108                 "MAY ( "
109                         "olmBDBEntryCache "
110                         "$ olmBDBEntryInfo "
111                         "$ olmBDBIDLCache "
112                         "$ olmDbDirectory "
113                         ") )",
114                 &oc_olmBDBDatabase },
115
116         { NULL }
117 };
118
119 static int
120 bdb_monitor_update(
121         Operation       *op,
122         SlapReply       *rs,
123         Entry           *e,
124         void            *priv )
125 {
126         struct bdb_info         *bdb = (struct bdb_info *) priv;
127         Attribute               *a;
128
129         char                    buf[ BUFSIZ ];
130         struct berval           bv;
131
132         assert( ad_olmBDBEntryCache != NULL );
133
134         a = attr_find( e->e_attrs, ad_olmBDBEntryCache );
135         assert( a != NULL );
136         bv.bv_val = buf;
137         bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_cache.c_cursize );
138         ber_bvreplace( &a->a_vals[ 0 ], &bv );
139
140         a = attr_find( e->e_attrs, ad_olmBDBEntryInfo );
141         assert( a != NULL );
142         bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_cache.c_eiused );
143         ber_bvreplace( &a->a_vals[ 0 ], &bv );
144
145         a = attr_find( e->e_attrs, ad_olmBDBIDLCache );
146         assert( a != NULL );
147         bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_idl_cache_size );
148         ber_bvreplace( &a->a_vals[ 0 ], &bv );
149         
150         return SLAP_CB_CONTINUE;
151 }
152
153 static int
154 bdb_monitor_modify(
155         Operation       *op,
156         SlapReply       *rs,
157         Entry           *e,
158         void            *priv )
159 {
160         return SLAP_CB_CONTINUE;
161 }
162
163 static int
164 bdb_monitor_free(
165         Entry           *e,
166         void            *priv )
167 {
168         struct berval   values[ 2 ];
169         Modification    mod = { 0 };
170
171         const char      *text;
172         char            textbuf[ SLAP_TEXT_BUFLEN ];
173
174         int             i, rc;
175
176         /* NOTE: if slap_shutdown != 0, priv might have already been freed */
177
178         /* Remove objectClass */
179         mod.sm_op = LDAP_MOD_DELETE;
180         mod.sm_desc = slap_schema.si_ad_objectClass;
181         mod.sm_values = values;
182         values[ 0 ] = oc_olmBDBDatabase->soc_cname;
183         BER_BVZERO( &values[ 1 ] );
184
185         rc = modify_delete_values( e, &mod, 1, &text,
186                 textbuf, sizeof( textbuf ) );
187         /* don't care too much about return code... */
188
189         /* remove attrs */
190         for ( i = 0; s_at[ i ].desc != NULL; i++ ) {
191                 mod.sm_desc = *s_at[ i ].ad;
192                 mod.sm_values = NULL;
193                 rc = modify_delete_values( e, &mod, 1, &text,
194                         textbuf, sizeof( textbuf ) );
195                 /* don't care too much about return code... */
196         }
197         
198         return SLAP_CB_CONTINUE;
199 }
200
201 /*
202  * call from within bdb_initialize()
203  */
204 static int
205 bdb_monitor_initialize( void )
206 {
207         int             i, code;
208
209         static int      bdb_monitor_initialized = 0;
210
211         if ( backend_info( "monitor" ) == NULL ) {
212                 return -1;
213         }
214
215         if ( bdb_monitor_initialized++ ) {
216                 return 0;
217         }
218
219         /* register schema here */
220
221         for ( i = 0; s_oid[ i ].name; i++ ) {
222                 char    *argv[ 3 ];
223         
224                 argv[ 0 ] = "back-bdb/back-hdb monitor";
225                 argv[ 1 ] = s_oid[ i ].name;
226                 argv[ 2 ] = s_oid[ i ].oid;
227
228                 if ( parse_oidm( argv[ 0 ], i, 3, argv, 0, NULL ) != 0 ) {
229                         Debug( LDAP_DEBUG_ANY,
230                                 "bdb_monitor_initialize: unable to add "
231                                 "objectIdentifier \"%s=%s\"\n",
232                                 s_oid[ i ].name, s_oid[ i ].oid, 0 );
233                         return 1;
234                 }
235         }
236
237         for ( i = 0; s_at[ i ].desc != NULL; i++ ) {
238                 code = register_at( s_at[ i ].desc, s_at[ i ].ad, 1 );
239                 if ( code != LDAP_SUCCESS ) {
240                         Debug( LDAP_DEBUG_ANY,
241                                 "bdb_monitor_initialize: register_at failed\n",
242                                 0, 0, 0 );
243                 }
244         }
245
246         for ( i = 0; s_oc[ i ].desc != NULL; i++ ) {
247                 code = register_oc( s_oc[ i ].desc, s_oc[ i ].oc, 1 );
248                 if ( code != LDAP_SUCCESS ) {
249                         Debug( LDAP_DEBUG_ANY,
250                                 "bdb_monitor_initialize: register_oc failed\n",
251                                 0, 0, 0 );
252                 }
253         }
254
255         return 0;
256 }
257
258 /*
259  * call from within bdb_db_init()
260  */
261 int
262 bdb_monitor_db_init( BackendDB *be )
263 {
264         struct bdb_info         *bdb = (struct bdb_info *) be->be_private;
265
266         if ( bdb_monitor_initialize() == LDAP_SUCCESS ) {
267                 /* monitoring in back-bdb is on by default */
268                 SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_MONITORING;
269         }
270
271         bdb->bi_monitor.bdm_scope = -1;
272
273         return 0;
274 }
275
276 /*
277  * call from within bdb_db_open()
278  */
279 int
280 bdb_monitor_db_open( BackendDB *be )
281 {
282         struct bdb_info         *bdb = (struct bdb_info *) be->be_private;
283         Attribute               *a, *next;
284         monitor_callback_t      *cb = NULL;
285         struct berval           suffix, *filter, *base;
286         char                    *ptr;
287         int                     rc = 0;
288         BackendInfo             *mi;
289         monitor_extra_t         *mbe;
290
291         if ( !SLAP_DBMONITORING( be ) ) {
292                 return 0;
293         }
294
295         mi = backend_info( "monitor" );
296         if ( !mi || !mi->bi_extra ) {
297                 SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING;
298                 return 0;
299         }
300         mbe = mi->bi_extra;
301
302         /* don't bother if monitor is not configured */
303         if ( !mbe->is_configured() ) {
304                 static int warning = 0;
305
306                 if ( warning++ == 0 ) {
307                         Debug( LDAP_DEBUG_ANY, "bdb_monitor_open: "
308                                 "monitoring disabled; "
309                                 "configure monitor database to enable\n",
310                                 0, 0, 0 );
311                 }
312
313                 return 0;
314         }
315
316         if ( bdb->bi_monitor.bdm_scope == -1 ) {
317                 bdb->bi_monitor.bdm_scope = LDAP_SCOPE_ONELEVEL;
318         }
319         base = &bdb->bi_monitor.bdm_nbase;
320         BER_BVSTR( base, "cn=databases,cn=monitor" );
321         filter = &bdb->bi_monitor.bdm_filter;
322         BER_BVZERO( filter );
323
324         suffix.bv_len = ldap_bv2escaped_filter_value_len( &be->be_nsuffix[ 0 ] );
325         if ( suffix.bv_len == be->be_nsuffix[ 0 ].bv_len ) {
326                 suffix = be->be_nsuffix[ 0 ];
327
328         } else {
329                 ldap_bv2escaped_filter_value( &be->be_nsuffix[ 0 ], &suffix );
330         }
331
332         /* just look for the naming context */
333         filter->bv_len = STRLENOF( "(namingContexts:distinguishedNameMatch:=" )
334                 + suffix.bv_len + STRLENOF( ")" );
335         ptr = filter->bv_val = ch_malloc( filter->bv_len + 1 );
336         ptr = lutil_strcopy( ptr, "(namingContexts:distinguishedNameMatch:=" );
337         ptr = lutil_strncopy( ptr, suffix.bv_val, suffix.bv_len );
338         ptr = lutil_strcopy( ptr, ")" );
339         ptr[ 0 ] = '\0';
340         assert( filter->bv_len == ptr - filter->bv_val );
341         
342         if ( suffix.bv_val != be->be_nsuffix[ 0 ].bv_val ) {
343                 ch_free( suffix.bv_val );
344         }
345
346         /* alloc as many as required (plus 1 for objectClass) */
347         a = attrs_alloc( 1 + 4 );
348         if ( a == NULL ) {
349                 rc = 1;
350                 goto cleanup;
351         }
352
353         a->a_desc = slap_schema.si_ad_objectClass;
354         value_add_one( &a->a_vals, &oc_olmBDBDatabase->soc_cname );
355         a->a_nvals = a->a_vals;
356         next = a->a_next;
357
358         {
359                 struct berval   bv = BER_BVC( "0" );
360
361                 next->a_desc = ad_olmBDBEntryCache;
362                 value_add_one( &next->a_vals, &bv );
363                 next->a_nvals = next->a_vals;
364                 next = next->a_next;
365
366                 next->a_desc = ad_olmBDBEntryInfo;
367                 value_add_one( &next->a_vals, &bv );
368                 next->a_nvals = next->a_vals;
369                 next = next->a_next;
370
371                 next->a_desc = ad_olmBDBIDLCache;
372                 value_add_one( &next->a_vals, &bv );
373                 next->a_nvals = next->a_vals;
374                 next = next->a_next;
375         }
376
377         {
378                 struct berval   bv, nbv;
379                 ber_len_t       pathlen = 0, len = 0;
380                 char            path[ PATH_MAX ] = { '\0' };
381                 char            *fname = bdb->bi_dbenv_home,
382                                 *ptr;
383
384                 len = strlen( fname );
385                 if ( fname[ 0 ] != '/' ) {
386                         /* get full path name */
387                         getcwd( path, sizeof( path ) );
388                         pathlen = strlen( path );
389
390                         if ( fname[ 0 ] == '.' && fname[ 1 ] == '/' ) {
391                                 fname += 2;
392                                 len -= 2;
393                         }
394                 }
395
396                 bv.bv_len = pathlen + STRLENOF( "/" ) + len;
397                 ptr = bv.bv_val = ch_malloc( bv.bv_len + STRLENOF( "/" ) + 1 );
398                 if ( pathlen ) {
399                         ptr = lutil_strncopy( ptr, path, pathlen );
400                         ptr[ 0 ] = '/';
401                         ptr++;
402                 }
403                 ptr = lutil_strncopy( ptr, fname, len );
404                 if ( ptr[ -1 ] != '/' ) {
405                         ptr[ 0 ] = '/';
406                         ptr++;
407                 }
408                 ptr[ 0 ] = '\0';
409                 
410                 attr_normalize_one( ad_olmDbDirectory, &bv, &nbv, NULL );
411
412                 next->a_desc = ad_olmDbDirectory;
413                 next->a_vals = ch_calloc( sizeof( struct berval ), 2 );
414                 next->a_vals[ 0 ] = bv;
415
416                 if ( BER_BVISNULL( &nbv ) ) {
417                         next->a_nvals = next->a_vals;
418
419                 } else {
420                         next->a_nvals = ch_calloc( sizeof( struct berval ), 2 );
421                         next->a_nvals[ 0 ] = nbv;
422                 }
423
424                 next = next->a_next;
425         }
426
427         cb = ch_calloc( sizeof( monitor_callback_t ), 1 );
428         cb->mc_update = bdb_monitor_update;
429 #if 0   /* uncomment if required */
430         cb->mc_modify = bdb_monitor_modify;
431 #endif
432         cb->mc_free = bdb_monitor_free;
433         cb->mc_private = (void *)bdb;
434
435         rc = mbe->register_entry_attrs( NULL, a, cb,
436                 base, bdb->bi_monitor.bdm_scope, filter );
437
438 cleanup:;
439         if ( rc != 0 ) {
440                 if ( cb != NULL ) {
441                         ch_free( cb );
442                         cb = NULL;
443                 }
444
445                 if ( a != NULL ) {
446                         attrs_free( a );
447                         a = NULL;
448                 }
449
450                 if ( !BER_BVISNULL( filter ) ) {
451                         ch_free( filter->bv_val );
452                         BER_BVZERO( filter );
453                 }
454         }
455
456         /* store for cleanup */
457         bdb->bi_monitor.bdm_cb = (void *)cb;
458
459         /* we don't need to keep track of the attributes, because
460          * bdb_monitor_free() takes care of everything */
461         if ( a != NULL ) {
462                 attrs_free( a );
463         }
464
465         return rc;
466 }
467
468 /*
469  * call from within bdb_db_close()
470  */
471 int
472 bdb_monitor_db_close( BackendDB *be )
473 {
474         struct bdb_info         *bdb = (struct bdb_info *) be->be_private;
475
476         if ( !BER_BVISNULL( &bdb->bi_monitor.bdm_filter ) ) {
477                 BackendInfo             *mi = backend_info( "monitor" );
478                 monitor_extra_t         *mbe;
479
480                 if ( mi && &mi->bi_extra ) {
481                         mbe = mi->bi_extra;
482                         mbe->unregister_entry_callback( NULL,
483                                 (monitor_callback_t *)bdb->bi_monitor.bdm_cb,
484                                 &bdb->bi_monitor.bdm_nbase,
485                                 bdb->bi_monitor.bdm_scope,
486                                 &bdb->bi_monitor.bdm_filter );
487                 }
488
489                 if ( !BER_BVISNULL( &bdb->bi_monitor.bdm_filter ) ) {
490                         ch_free( bdb->bi_monitor.bdm_filter.bv_val );
491                 }
492
493                 memset( &bdb->bi_monitor, 0, sizeof( bdb->bi_monitor ) );
494         }
495
496         return 0;
497 }
498
499 /*
500  * call from within bdb_db_destroy()
501  */
502 int
503 bdb_monitor_db_destroy( BackendDB *be )
504 {
505         return 0;
506 }