]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/monitor.c
Fallout from ITS#4986 - remove unused param of select_backend()
[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-2007 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 #include "config.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                    *desc;
63         AttributeDescription    **ad;
64 }               s_at[] = {
65         { "( olmBDBAttributes:1 "
66                 "NAME ( 'olmBDBEntryCache' ) "
67                 "DESC 'Number of items in Entry Cache' "
68                 "SUP monitorCounter "
69                 "NO-USER-MODIFICATION "
70                 "USAGE dSAOperation )",
71                 &ad_olmBDBEntryCache },
72
73         { "( olmBDBAttributes:2 "
74                 "NAME ( 'olmBDBEntryInfo' ) "
75                 "DESC 'Number of items in EntryInfo Cache' "
76                 "SUP monitorCounter "
77                 "NO-USER-MODIFICATION "
78                 "USAGE dSAOperation )",
79                 &ad_olmBDBEntryInfo },
80
81         { "( olmBDBAttributes:3 "
82                 "NAME ( 'olmBDBIDLCache' ) "
83                 "DESC 'Number of items in IDL Cache' "
84                 "SUP monitorCounter "
85                 "NO-USER-MODIFICATION "
86                 "USAGE dSAOperation )",
87                 &ad_olmBDBIDLCache },
88
89         { "( 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 dSAOperation )",
96                 &ad_olmDbDirectory },
97
98         { NULL }
99 };
100
101 static struct {
102         char            *desc;
103         ObjectClass     **oc;
104 }               s_oc[] = {
105         /* augments an existing object, so it must be AUXILIARY
106          * FIXME: derive from some ABSTRACT "monitoredEntity"? */
107         { "( olmBDBObjectClasses:1 "
108                 "NAME ( 'olmBDBDatabase' ) "
109                 "SUP top AUXILIARY "
110                 "MAY ( "
111                         "olmBDBEntryCache "
112                         "$ olmBDBEntryInfo "
113                         "$ olmBDBIDLCache "
114                         "$ olmDbDirectory "
115                         ") )",
116                 &oc_olmBDBDatabase },
117
118         { NULL }
119 };
120
121 static int
122 bdb_monitor_update(
123         Operation       *op,
124         SlapReply       *rs,
125         Entry           *e,
126         void            *priv )
127 {
128         struct bdb_info         *bdb = (struct bdb_info *) priv;
129         Attribute               *a;
130
131         char                    buf[ BUFSIZ ];
132         struct berval           bv;
133
134         assert( ad_olmBDBEntryCache != NULL );
135
136         a = attr_find( e->e_attrs, ad_olmBDBEntryCache );
137         assert( a != NULL );
138         bv.bv_val = buf;
139         bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_cache.c_cursize );
140         ber_bvreplace( &a->a_vals[ 0 ], &bv );
141
142         a = attr_find( e->e_attrs, ad_olmBDBEntryInfo );
143         assert( a != NULL );
144         bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_cache.c_eiused );
145         ber_bvreplace( &a->a_vals[ 0 ], &bv );
146
147         a = attr_find( e->e_attrs, ad_olmBDBIDLCache );
148         assert( a != NULL );
149         bv.bv_len = snprintf( buf, sizeof( buf ), "%d", bdb->bi_idl_cache_size );
150         ber_bvreplace( &a->a_vals[ 0 ], &bv );
151         
152         return SLAP_CB_CONTINUE;
153 }
154
155 #if 0   /* uncomment if required */
156 static int
157 bdb_monitor_modify(
158         Operation       *op,
159         SlapReply       *rs,
160         Entry           *e,
161         void            *priv )
162 {
163         return SLAP_CB_CONTINUE;
164 }
165 #endif
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         /* NOTE: if slap_shutdown != 0, priv might have already been freed */
181         *priv = NULL;
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 ].desc != 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 #define bdb_monitor_initialize  BDB_SYMBOL(monitor_initialize)
207
208 /*
209  * call from within bdb_initialize()
210  */
211 static int
212 bdb_monitor_initialize( void )
213 {
214         int             i, code;
215         ConfigArgs c;
216         char    *argv[ 3 ];
217
218         static int      bdb_monitor_initialized = 0;
219
220         if ( backend_info( "monitor" ) == NULL ) {
221                 return -1;
222         }
223
224         if ( bdb_monitor_initialized++ ) {
225                 return 0;
226         }
227
228         /* register schema here */
229
230         argv[ 0 ] = "back-bdb/back-hdb monitor";
231         c.argv = argv;
232         c.argc = 3;
233         c.fname = argv[0];
234
235         for ( i = 0; s_oid[ i ].name; i++ ) {
236                 c.lineno = i;
237                 argv[ 1 ] = s_oid[ i ].name;
238                 argv[ 2 ] = s_oid[ i ].oid;
239
240                 if ( parse_oidm( &c, 0, NULL ) != 0 ) {
241                         Debug( LDAP_DEBUG_ANY,
242                                 "bdb_monitor_initialize: unable to add "
243                                 "objectIdentifier \"%s=%s\"\n",
244                                 s_oid[ i ].name, s_oid[ i ].oid, 0 );
245                         return 1;
246                 }
247         }
248
249         for ( i = 0; s_at[ i ].desc != NULL; i++ ) {
250                 code = register_at( s_at[ i ].desc, s_at[ i ].ad, 1 );
251                 if ( code != LDAP_SUCCESS ) {
252                         Debug( LDAP_DEBUG_ANY,
253                                 "bdb_monitor_initialize: register_at failed\n",
254                                 0, 0, 0 );
255                 }
256         }
257
258         for ( i = 0; s_oc[ i ].desc != NULL; i++ ) {
259                 code = register_oc( s_oc[ i ].desc, s_oc[ i ].oc, 1 );
260                 if ( code != LDAP_SUCCESS ) {
261                         Debug( LDAP_DEBUG_ANY,
262                                 "bdb_monitor_initialize: register_oc failed\n",
263                                 0, 0, 0 );
264                 }
265         }
266
267         return 0;
268 }
269
270 /*
271  * call from within bdb_db_init()
272  */
273 int
274 bdb_monitor_db_init( BackendDB *be )
275 {
276         struct bdb_info         *bdb = (struct bdb_info *) be->be_private;
277
278         if ( SLAP_GLUE_SUBORDINATE( be ) ) {
279                 return 0;
280         }
281
282         if ( bdb_monitor_initialize() == LDAP_SUCCESS ) {
283                 /* monitoring in back-bdb is on by default */
284                 SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_MONITORING;
285         }
286
287         bdb->bi_monitor.bdm_scope = -1;
288
289         return 0;
290 }
291
292 /*
293  * call from within bdb_db_open()
294  */
295 int
296 bdb_monitor_db_open( BackendDB *be )
297 {
298         struct bdb_info         *bdb = (struct bdb_info *) be->be_private;
299         Attribute               *a, *next;
300         monitor_callback_t      *cb = NULL;
301         struct berval           suffix, *filter, *base;
302         char                    *ptr;
303         int                     rc = 0;
304         BackendInfo             *mi;
305         monitor_extra_t         *mbe;
306
307         if ( !SLAP_DBMONITORING( be ) ) {
308                 return 0;
309         }
310
311         if ( SLAP_GLUE_SUBORDINATE( be ) ) {
312                 return 0;
313         }
314
315         mi = backend_info( "monitor" );
316         if ( !mi || !mi->bi_extra ) {
317                 SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING;
318                 return 0;
319         }
320         mbe = mi->bi_extra;
321
322         /* don't bother if monitor is not configured */
323         if ( !mbe->is_configured() ) {
324                 static int warning = 0;
325
326                 if ( warning++ == 0 ) {
327                         Debug( LDAP_DEBUG_ANY, "bdb_monitor_open: "
328                                 "monitoring disabled; "
329                                 "configure monitor database to enable\n",
330                                 0, 0, 0 );
331                 }
332
333                 return 0;
334         }
335
336         if ( bdb->bi_monitor.bdm_scope == -1 ) {
337                 bdb->bi_monitor.bdm_scope = LDAP_SCOPE_ONELEVEL;
338         }
339         base = &bdb->bi_monitor.bdm_nbase;
340         BER_BVSTR( base, "cn=databases,cn=monitor" );
341         filter = &bdb->bi_monitor.bdm_filter;
342         BER_BVZERO( filter );
343
344         suffix.bv_len = ldap_bv2escaped_filter_value_len( &be->be_nsuffix[ 0 ] );
345         if ( suffix.bv_len == be->be_nsuffix[ 0 ].bv_len ) {
346                 suffix = be->be_nsuffix[ 0 ];
347
348         } else {
349                 ldap_bv2escaped_filter_value( &be->be_nsuffix[ 0 ], &suffix );
350         }
351
352         if ( BER_BVISEMPTY( &suffix ) ) {
353                 /* frontend also has empty suffix, sigh! */
354                 filter->bv_len = STRLENOF( "(&(namingContexts:distinguishedNameMatch:=" )
355                         + suffix.bv_len + STRLENOF( ")(!(cn=frontend)))" );
356                 ptr = filter->bv_val = ch_malloc( filter->bv_len + 1 );
357                 ptr = lutil_strcopy( ptr, "(&(namingContexts:distinguishedNameMatch:=" );
358                 ptr = lutil_strncopy( ptr, suffix.bv_val, suffix.bv_len );
359                 ptr = lutil_strcopy( ptr, ")(!(cn=frontend)))" );
360
361         } else {
362                 /* just look for the naming context */
363                 filter->bv_len = STRLENOF( "(namingContexts:distinguishedNameMatch:=" )
364                         + suffix.bv_len + STRLENOF( ")" );
365                 ptr = filter->bv_val = ch_malloc( filter->bv_len + 1 );
366                 ptr = lutil_strcopy( ptr, "(namingContexts:distinguishedNameMatch:=" );
367                 ptr = lutil_strncopy( ptr, suffix.bv_val, suffix.bv_len );
368                 ptr = lutil_strcopy( ptr, ")" );
369         }
370         ptr[ 0 ] = '\0';
371         assert( filter->bv_len == ptr - filter->bv_val );
372         
373         if ( suffix.bv_val != be->be_nsuffix[ 0 ].bv_val ) {
374                 ch_free( suffix.bv_val );
375         }
376
377         /* alloc as many as required (plus 1 for objectClass) */
378         a = attrs_alloc( 1 + 4 );
379         if ( a == NULL ) {
380                 rc = 1;
381                 goto cleanup;
382         }
383
384         a->a_desc = slap_schema.si_ad_objectClass;
385         value_add_one( &a->a_vals, &oc_olmBDBDatabase->soc_cname );
386         a->a_nvals = a->a_vals;
387         next = a->a_next;
388
389         {
390                 struct berval   bv = BER_BVC( "0" );
391
392                 next->a_desc = ad_olmBDBEntryCache;
393                 value_add_one( &next->a_vals, &bv );
394                 next->a_nvals = next->a_vals;
395                 next = next->a_next;
396
397                 next->a_desc = ad_olmBDBEntryInfo;
398                 value_add_one( &next->a_vals, &bv );
399                 next->a_nvals = next->a_vals;
400                 next = next->a_next;
401
402                 next->a_desc = ad_olmBDBIDLCache;
403                 value_add_one( &next->a_vals, &bv );
404                 next->a_nvals = next->a_vals;
405                 next = next->a_next;
406         }
407
408         {
409                 struct berval   bv, nbv;
410                 ber_len_t       pathlen = 0, len = 0;
411                 char            path[ PATH_MAX ] = { '\0' };
412                 char            *fname = bdb->bi_dbenv_home,
413                                 *ptr;
414
415                 len = strlen( fname );
416                 if ( fname[ 0 ] != '/' ) {
417                         /* get full path name */
418                         getcwd( path, sizeof( path ) );
419                         pathlen = strlen( path );
420
421                         if ( fname[ 0 ] == '.' && fname[ 1 ] == '/' ) {
422                                 fname += 2;
423                                 len -= 2;
424                         }
425                 }
426
427                 bv.bv_len = pathlen + STRLENOF( "/" ) + len;
428                 ptr = bv.bv_val = ch_malloc( bv.bv_len + STRLENOF( "/" ) + 1 );
429                 if ( pathlen ) {
430                         ptr = lutil_strncopy( ptr, path, pathlen );
431                         ptr[ 0 ] = '/';
432                         ptr++;
433                 }
434                 ptr = lutil_strncopy( ptr, fname, len );
435                 if ( ptr[ -1 ] != '/' ) {
436                         ptr[ 0 ] = '/';
437                         ptr++;
438                 }
439                 ptr[ 0 ] = '\0';
440                 
441                 attr_normalize_one( ad_olmDbDirectory, &bv, &nbv, NULL );
442
443                 next->a_desc = ad_olmDbDirectory;
444                 next->a_vals = ch_calloc( sizeof( struct berval ), 2 );
445                 next->a_vals[ 0 ] = bv;
446
447                 if ( BER_BVISNULL( &nbv ) ) {
448                         next->a_nvals = next->a_vals;
449
450                 } else {
451                         next->a_nvals = ch_calloc( sizeof( struct berval ), 2 );
452                         next->a_nvals[ 0 ] = nbv;
453                 }
454
455                 next = next->a_next;
456         }
457
458         cb = ch_calloc( sizeof( monitor_callback_t ), 1 );
459         cb->mc_update = bdb_monitor_update;
460 #if 0   /* uncomment if required */
461         cb->mc_modify = bdb_monitor_modify;
462 #endif
463         cb->mc_free = bdb_monitor_free;
464         cb->mc_private = (void *)bdb;
465
466         /* make sure the database is registered; then add monitor attributes */
467         rc = mbe->register_database( be );
468         if ( rc == 0 ) {
469                 rc = mbe->register_entry_attrs( NULL, a, cb,
470                         base, bdb->bi_monitor.bdm_scope, filter );
471         }
472
473 cleanup:;
474         if ( rc != 0 ) {
475                 if ( cb != NULL ) {
476                         ch_free( cb );
477                         cb = NULL;
478                 }
479
480                 if ( a != NULL ) {
481                         attrs_free( a );
482                         a = NULL;
483                 }
484
485                 if ( !BER_BVISNULL( filter ) ) {
486                         ch_free( filter->bv_val );
487                         BER_BVZERO( filter );
488                 }
489         }
490
491         /* store for cleanup */
492         bdb->bi_monitor.bdm_cb = (void *)cb;
493
494         /* we don't need to keep track of the attributes, because
495          * bdb_monitor_free() takes care of everything */
496         if ( a != NULL ) {
497                 attrs_free( a );
498         }
499
500         return rc;
501 }
502
503 /*
504  * call from within bdb_db_close()
505  */
506 int
507 bdb_monitor_db_close( BackendDB *be )
508 {
509         struct bdb_info         *bdb = (struct bdb_info *) be->be_private;
510
511         if ( SLAP_GLUE_SUBORDINATE( be ) ) {
512                 return 0;
513         }
514
515         if ( !BER_BVISNULL( &bdb->bi_monitor.bdm_filter ) ) {
516                 BackendInfo             *mi = backend_info( "monitor" );
517                 monitor_extra_t         *mbe;
518
519                 if ( mi && &mi->bi_extra ) {
520                         mbe = mi->bi_extra;
521                         mbe->unregister_entry_callback( NULL,
522                                 (monitor_callback_t *)bdb->bi_monitor.bdm_cb,
523                                 &bdb->bi_monitor.bdm_nbase,
524                                 bdb->bi_monitor.bdm_scope,
525                                 &bdb->bi_monitor.bdm_filter );
526                 }
527
528                 if ( !BER_BVISNULL( &bdb->bi_monitor.bdm_filter ) ) {
529                         ch_free( bdb->bi_monitor.bdm_filter.bv_val );
530                 }
531
532                 memset( &bdb->bi_monitor, 0, sizeof( bdb->bi_monitor ) );
533         }
534
535         return 0;
536 }
537
538 /*
539  * call from within bdb_db_destroy()
540  */
541 int
542 bdb_monitor_db_destroy( BackendDB *be )
543 {
544         if ( SLAP_GLUE_SUBORDINATE( be ) ) {
545                 return 0;
546         }
547
548         return 0;
549 }