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