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