]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/monitor.c
Use #ifdef SLAPD_MONITOR for monitor APIs
[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 #ifdef SLAPD_MONITOR
20
21 #include <stdio.h>
22 #include <ac/string.h>
23 #include <ac/unistd.h>
24 #include <ac/stdlib.h>
25 #include <ac/errno.h>
26 #include <sys/stat.h>
27 #include "lutil.h"
28 #include "back-bdb.h"
29 #include "../back-monitor/back-monitor.h"
30
31 static ObjectClass              *oc_olmBDBDatabase;
32
33 static AttributeDescription     *ad_olmBDBEntryCache,
34         *ad_olmBDBEntryInfo, *ad_olmBDBIDLCache,
35         *ad_olmDbDirectory;
36
37 /*
38  * NOTE: there's some confusion in monitor OID arc;
39  * by now, let's consider:
40  * 
41  * Subsystems monitor attributes        1.3.6.1.4.1.4203.666.1.55.0
42  * Databases monitor attributes         1.3.6.1.4.1.4203.666.1.55.0.1
43  * BDB database monitor attributes      1.3.6.1.4.1.4203.666.1.55.0.1.1
44  *
45  * Subsystems monitor objectclasses     1.3.6.1.4.1.4203.666.3.16.0
46  * Databases monitor objectclasses      1.3.6.1.4.1.4203.666.3.16.0.1
47  * BDB database monitor objectclasses   1.3.6.1.4.1.4203.666.3.16.0.1.1
48  */
49
50 static struct {
51         char                    *name;
52         char                    *oid;
53 }               s_oid[] = {
54         { "olmBDBAttributes",                   "olmDatabaseAttributes:1" },
55         { "olmBDBObjectClasses",                "olmDatabaseObjectClasses:1" },
56
57         { NULL }
58 };
59
60 static struct {
61         char                    *name;
62         char                    *desc;
63         AttributeDescription    **ad;
64 }               s_at[] = {
65         { "olmBDBEntryCache", "( olmBDBAttributes:1 "
66                 "NAME ( 'olmBDBEntryCache' ) "
67                 "DESC 'Number of items in Entry Cache' "
68                 "SUP monitorCounter "
69                 "NO-USER-MODIFICATION "
70                 "USAGE directoryOperation )",
71                 &ad_olmBDBEntryCache },
72
73         { "olmBDBEntryInfo", "( olmBDBAttributes:2 "
74                 "NAME ( 'olmBDBEntryInfo' ) "
75                 "DESC 'Number of items in EntryInfo Cache' "
76                 "SUP monitorCounter "
77                 "NO-USER-MODIFICATION "
78                 "USAGE directoryOperation )",
79                 &ad_olmBDBEntryInfo },
80
81         { "olmBDBIDLCache", "( olmBDBAttributes:3 "
82                 "NAME ( 'olmBDBIDLCache' ) "
83                 "DESC 'Number of items in IDL Cache' "
84                 "SUP monitorCounter "
85                 "NO-USER-MODIFICATION "
86                 "USAGE directoryOperation )",
87                 &ad_olmBDBIDLCache },
88
89         { "olmDbDirectory", "( olmBDBAttributes:4 "
90                 "NAME ( 'olmDbDirectory' ) "
91                 "DESC 'Path name of the directory "
92                         "where the database environment resides' "
93                 "SUP monitoredInfo "
94                 "NO-USER-MODIFICATION "
95                 "USAGE directoryOperation )",
96                 &ad_olmDbDirectory },
97
98         { NULL }
99 };
100
101 static struct {
102         char            *name;
103         char            *desc;
104         ObjectClass     **oc;
105 }               s_oc[] = {
106         /* augments an existing object, so it must be AUXILIARY
107          * FIXME: derive from some ABSTRACT "monitoredEntity"? */
108         { "olmBDBDatabase", "( olmBDBObjectClasses:1 "
109                 "NAME ( 'olmBDBDatabase' ) "
110                 "SUP top AUXILIARY "
111                 "MAY ( "
112                         "olmBDBEntryCache "
113                         "$ olmBDBEntryInfo "
114                         "$ olmBDBIDLCache "
115                         "$ olmDbDirectory "
116                         ") )",
117                 &oc_olmBDBDatabase },
118
119         { NULL }
120 };
121
122 static int
123 bdb_monitor_update(
124         Operation       *op,
125         SlapReply       *rs,
126         Entry           *e,
127         void            *priv )
128 {
129         struct bdb_info         *bdb = (struct bdb_info *) priv;
130         Attribute               *a;
131
132         char                    buf[ BUFSIZ ];
133         struct berval           bv;
134
135         assert( ad_olmBDBEntryCache != NULL );
136
137         a = attr_find( e->e_attrs, ad_olmBDBEntryCache );
138         assert( a != NULL );
139         bv.bv_val = buf;
140         bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_cache.c_cursize );
141         ber_bvreplace( &a->a_vals[ 0 ], &bv );
142
143         a = attr_find( e->e_attrs, ad_olmBDBEntryInfo );
144         assert( a != NULL );
145         bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_cache.c_eiused );
146         ber_bvreplace( &a->a_vals[ 0 ], &bv );
147
148         a = attr_find( e->e_attrs, ad_olmBDBIDLCache );
149         assert( a != NULL );
150         bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_idl_cache_size );
151         ber_bvreplace( &a->a_vals[ 0 ], &bv );
152         
153         return SLAP_CB_CONTINUE;
154 }
155
156 static int
157 bdb_monitor_modify(
158         Operation       *op,
159         SlapReply       *rs,
160         Entry           *e,
161         void            *priv )
162 {
163         struct bdb_info         *bdb = (struct bdb_info *) priv;
164         
165         return SLAP_CB_CONTINUE;
166 }
167
168 static int
169 bdb_monitor_free(
170         Entry           *e,
171         void            *priv )
172 {
173         struct bdb_info         *bdb = (struct bdb_info *) priv;
174
175         struct berval   values[ 2 ];
176         Modification    mod = { 0 };
177
178         const char      *text;
179         char            textbuf[ SLAP_TEXT_BUFLEN ];
180
181         int             i, rc;
182
183         /* Remove objectClass */
184         mod.sm_op = LDAP_MOD_DELETE;
185         mod.sm_desc = slap_schema.si_ad_objectClass;
186         mod.sm_values = values;
187         values[ 0 ] = oc_olmBDBDatabase->soc_cname;
188         BER_BVZERO( &values[ 1 ] );
189
190         rc = modify_delete_values( e, &mod, 1, &text,
191                 textbuf, sizeof( textbuf ) );
192         /* don't care too much about return code... */
193
194         /* remove attrs */
195         for ( i = 0; s_at[ i ].name != NULL; i++ ) {
196                 mod.sm_desc = *s_at[ i ].ad;
197                 mod.sm_values = NULL;
198                 rc = modify_delete_values( e, &mod, 1, &text,
199                         textbuf, sizeof( textbuf ) );
200                 /* don't care too much about return code... */
201         }
202         
203         return SLAP_CB_CONTINUE;
204 }
205
206 /*
207  * call from within bdb_initialize()
208  */
209 int
210 bdb_monitor_initialize( void )
211 {
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
326         return 0;
327 }
328
329 /*
330  * call from within bdb_db_init()
331  */
332 int
333 bdb_monitor_init( BackendDB *be )
334 {
335         SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_MONITORING;
336
337         return 0;
338 }
339
340 /*
341  * call from within bdb_db_open()
342  */
343 int
344 bdb_monitor_open( BackendDB *be )
345 {
346         struct bdb_info         *bdb = (struct bdb_info *) be->be_private;
347         Attribute               *a, *next;
348         monitor_callback_t      *cb = NULL;
349         struct berval           suffix, *filter, *base;
350         char                    *ptr;
351         int                     rc = 0;
352
353         if ( !SLAP_DBMONITORING( be ) ) {
354                 return 0;
355         }
356
357         /* don't bother if monitor is not configured */
358         if ( !monitor_back_is_configured() ) {
359                 static int warning = 0;
360
361                 if ( warning++ == 0 ) {
362                         Debug( LDAP_DEBUG_ANY, "bdb_monitor_open: "
363                                 "monitoring disabled; "
364                                 "configure monitor database to enable\n",
365                                 0, 0, 0 );
366                 }
367
368                 return 0;
369         }
370
371         bdb->bi_monitor.bdm_scope = LDAP_SCOPE_SUBORDINATE;
372         base = &bdb->bi_monitor.bdm_nbase;
373         BER_BVSTR( base, "cn=databases,cn=monitor" );
374         filter = &bdb->bi_monitor.bdm_filter;
375         BER_BVZERO( filter );
376
377         suffix.bv_len = ldap_bv2escaped_filter_value_len( &be->be_nsuffix[ 0 ] );
378         if ( suffix.bv_len == be->be_nsuffix[ 0 ].bv_len ) {
379                 suffix = be->be_nsuffix[ 0 ];
380
381         } else {
382                 ldap_bv2escaped_filter_value( &be->be_nsuffix[ 0 ], &suffix );
383         }
384         
385         filter->bv_len = STRLENOF( "(&(monitoredInfo=" )
386                 + strlen( be->bd_info->bi_type )
387                 + STRLENOF( ")(namingContexts:distinguishedNameMatch:=" )
388                 + suffix.bv_len + STRLENOF( "))" );
389         ptr = filter->bv_val = ch_malloc( filter->bv_len + 1 );
390         ptr = lutil_strcopy( ptr, "(&(monitoredInfo=" );
391         ptr = lutil_strcopy( ptr, be->bd_info->bi_type );
392         ptr = lutil_strcopy( ptr, ")(namingContexts:distinguishedNameMatch:=" );
393         ptr = lutil_strncopy( ptr, suffix.bv_val, suffix.bv_len );
394         ptr = lutil_strcopy( ptr, "))" );
395         ptr[ 0 ] = '\0';
396         assert( filter->bv_len == ptr - filter->bv_val );
397         
398         if ( suffix.bv_val != be->be_nsuffix[ 0 ].bv_val ) {
399                 ch_free( suffix.bv_val );
400         }
401
402         /* alloc as many as required (plus 1 for objectClass) */
403         a = attrs_alloc( 1 + 4 );
404         if ( a == NULL ) {
405                 rc = 1;
406                 goto cleanup;
407         }
408
409         a->a_desc = slap_schema.si_ad_objectClass;
410         value_add_one( &a->a_vals, &oc_olmBDBDatabase->soc_cname );
411         a->a_nvals = a->a_vals;
412         next = a->a_next;
413
414         {
415                 struct berval   bv = BER_BVC( "0" );
416
417                 next->a_desc = ad_olmBDBEntryCache;
418                 value_add_one( &next->a_vals, &bv );
419                 next->a_nvals = next->a_vals;
420                 next = next->a_next;
421
422                 next->a_desc = ad_olmBDBEntryInfo;
423                 value_add_one( &next->a_vals, &bv );
424                 next->a_nvals = next->a_vals;
425                 next = next->a_next;
426
427                 next->a_desc = ad_olmBDBIDLCache;
428                 value_add_one( &next->a_vals, &bv );
429                 next->a_nvals = next->a_vals;
430                 next = next->a_next;
431         }
432
433         {
434                 struct berval   bv, nbv;
435                 ber_len_t       pathlen = 0, len = 0;
436                 char            path[ PATH_MAX ] = { '\0' };
437                 char            *fname = bdb->bi_dbenv_home,
438                                 *ptr;
439
440                 len = strlen( fname );
441                 if ( fname[ 0 ] != '/' ) {
442                         /* get full path name */
443                         getcwd( path, sizeof( path ) );
444                         pathlen = strlen( path );
445
446                         if ( fname[ 0 ] == '.' && fname[ 1 ] == '/' ) {
447                                 fname += 2;
448                                 len -= 2;
449                         }
450                 }
451
452                 bv.bv_len = pathlen + STRLENOF( "/" ) + len;
453                 ptr = bv.bv_val = ch_malloc( bv.bv_len + STRLENOF( "/" ) + 1 );
454                 if ( pathlen ) {
455                         ptr = lutil_strncopy( ptr, path, pathlen );
456                         ptr[ 0 ] = '/';
457                         ptr++;
458                 }
459                 ptr = lutil_strncopy( ptr, fname, len );
460                 if ( ptr[ -1 ] != '/' ) {
461                         ptr[ 0 ] = '/';
462                         ptr++;
463                 }
464                 ptr[ 0 ] = '\0';
465                 
466                 attr_normalize_one( ad_olmDbDirectory, &bv, &nbv, NULL );
467
468                 next->a_desc = ad_olmDbDirectory;
469                 next->a_vals = ch_calloc( sizeof( struct berval ), 2 );
470                 next->a_vals[ 0 ] = bv;
471
472                 if ( BER_BVISNULL( &nbv ) ) {
473                         next->a_nvals = next->a_vals;
474
475                 } else {
476                         next->a_nvals = ch_calloc( sizeof( struct berval ), 2 );
477                         next->a_nvals[ 0 ] = nbv;
478                 }
479
480                 next = next->a_next;
481         }
482
483         cb = ch_calloc( sizeof( monitor_callback_t ), 1 );
484         cb->mc_update = bdb_monitor_update;
485         cb->mc_modify = bdb_monitor_modify;
486         cb->mc_free = bdb_monitor_free;
487         cb->mc_private = (void *)bdb;
488
489         rc = monitor_back_register_entry_attrs( NULL, a, cb,
490                 base, LDAP_SCOPE_SUBORDINATE, filter );
491
492 cleanup:;
493         if ( rc != 0 ) {
494                 if ( cb != NULL ) {
495                         ch_free( cb );
496                         cb = NULL;
497                 }
498
499                 if ( a != NULL ) {
500                         attrs_free( a );
501                         a = NULL;
502                 }
503
504                 if ( !BER_BVISNULL( filter ) ) {
505                         ch_free( filter->bv_val );
506                         BER_BVZERO( filter );
507                 }
508         }
509
510         /* store for cleanup */
511         bdb->bi_monitor.bdm_cb = (void *)cb;
512
513         /* we don't need to keep track of the attributes, because
514          * bdb_monitor_free() takes care of everything */
515         if ( a != NULL ) {
516                 attrs_free( a );
517         }
518
519         return rc;
520 }
521
522 /*
523  * call from within bdb_db_close()
524  */
525 int
526 bdb_monitor_close( BackendDB *be )
527 {
528         struct bdb_info         *bdb = (struct bdb_info *) be->be_private;
529
530         if ( !BER_BVISNULL( &bdb->bi_monitor.bdm_filter ) ) {
531                 monitor_back_unregister_entry_callback( NULL,
532                         (monitor_callback_t *)bdb->bi_monitor.bdm_cb,
533                         &bdb->bi_monitor.bdm_nbase,
534                         bdb->bi_monitor.bdm_scope,
535                         &bdb->bi_monitor.bdm_filter );
536
537                 if ( !BER_BVISNULL( &bdb->bi_monitor.bdm_filter ) ) {
538                         ch_free( bdb->bi_monitor.bdm_filter.bv_val );
539                 }
540
541                 memset( &bdb->bi_monitor, 0, sizeof( bdb->bi_monitor ) );
542         }
543
544         return 0;
545 }
546
547 /*
548  * call from within bdb_db_destroy()
549  */
550 int
551 bdb_monitor_destroy( BackendDB *be )
552 {
553         return 0;
554 }
555
556 #endif /* SLAPD_MONITOR */