]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/monitor.c
Add register_at / register_oc helpers.
[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         /* Remove objectClass */
177         mod.sm_op = LDAP_MOD_DELETE;
178         mod.sm_desc = slap_schema.si_ad_objectClass;
179         mod.sm_values = values;
180         values[ 0 ] = oc_olmBDBDatabase->soc_cname;
181         BER_BVZERO( &values[ 1 ] );
182
183         rc = modify_delete_values( e, &mod, 1, &text,
184                 textbuf, sizeof( textbuf ) );
185         /* don't care too much about return code... */
186
187         /* remove attrs */
188         for ( i = 0; s_at[ i ].desc != NULL; i++ ) {
189                 mod.sm_desc = *s_at[ i ].ad;
190                 mod.sm_values = NULL;
191                 rc = modify_delete_values( e, &mod, 1, &text,
192                         textbuf, sizeof( textbuf ) );
193                 /* don't care too much about return code... */
194         }
195         
196         return SLAP_CB_CONTINUE;
197 }
198
199 /*
200  * call from within bdb_initialize()
201  */
202 int
203 bdb_monitor_initialize( void )
204 {
205         int             i, code;
206         BackendInfo *bi;
207
208         static int      bdb_monitor_initialized = 0;
209
210         bi = backend_info("monitor");
211         if ( !bi )
212                 return -1;
213
214         /* register schema here */
215
216         if ( bdb_monitor_initialized++ ) {
217                 return 0;
218         }
219
220         for ( i = 0; s_oid[ i ].name; i++ ) {
221                 char    *argv[ 3 ];
222         
223                 argv[ 0 ] = "back-bdb/back-hdb monitor";
224                 argv[ 1 ] = s_oid[ i ].name;
225                 argv[ 2 ] = s_oid[ i ].oid;
226
227                 if ( parse_oidm( argv[ 0 ], i, 3, argv, 0, NULL ) != 0 ) {
228                         Debug( LDAP_DEBUG_ANY,
229                                 "bdb_monitor_initialize: unable to add "
230                                 "objectIdentifier \"%s=%s\"\n",
231                                 s_oid[ i ].name, s_oid[ i ].oid, 0 );
232                         return 1;
233                 }
234         }
235
236         for ( i = 0; s_at[ i ].desc != NULL; i++ ) {
237                 code = register_at( s_at[ i ].desc, s_at[ i ].ad, 1 );
238                 if ( code != LDAP_SUCCESS ) {
239                         Debug( LDAP_DEBUG_ANY,
240                                 "bdb_monitor_initialize: register_at failed\n",
241                                 0, 0, 0 );
242                 }
243         }
244
245         for ( i = 0; s_oc[ i ].desc != NULL; i++ ) {
246                 code = register_oc( s_oc[ i ].desc, s_oc[ i ].oc, 1 );
247                 if ( code != LDAP_SUCCESS ) {
248                         Debug( LDAP_DEBUG_ANY,
249                                 "bdb_monitor_initialize: register_oc failed\n",
250                                 0, 0, 0 );
251                 }
252         }
253
254         return 0;
255 }
256
257 /*
258  * call from within bdb_db_init()
259  */
260 int
261 bdb_monitor_init( BackendDB *be )
262 {
263         if ( bdb_monitor_initialize() == LDAP_SUCCESS ) {
264                 SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_MONITORING;
265         }
266
267         return 0;
268 }
269
270 /*
271  * call from within bdb_db_open()
272  */
273 int
274 bdb_monitor_open( BackendDB *be )
275 {
276         struct bdb_info         *bdb = (struct bdb_info *) be->be_private;
277         Attribute               *a, *next;
278         monitor_callback_t      *cb = NULL;
279         struct berval           suffix, *filter, *base;
280         char                    *ptr;
281         int                     rc = 0;
282         monitor_extra_t *mbe;
283
284         if ( !SLAP_DBMONITORING( be ) ) {
285                 return 0;
286         }
287
288         {
289                 BackendInfo *mi = backend_info( "monitor" );
290                 if ( !mi || !mi->bi_extra ) {
291                         SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING;
292                         return 0;
293                 }
294                 mbe = mi->bi_extra;
295         }
296
297         /* don't bother if monitor is not configured */
298         if ( !mbe->is_configured() ) {
299                 static int warning = 0;
300
301                 if ( warning++ == 0 ) {
302                         Debug( LDAP_DEBUG_ANY, "bdb_monitor_open: "
303                                 "monitoring disabled; "
304                                 "configure monitor database to enable\n",
305                                 0, 0, 0 );
306                 }
307
308                 return 0;
309         }
310
311         bdb->bi_monitor.bdm_scope = LDAP_SCOPE_SUBORDINATE;
312         base = &bdb->bi_monitor.bdm_nbase;
313         BER_BVSTR( base, "cn=databases,cn=monitor" );
314         filter = &bdb->bi_monitor.bdm_filter;
315         BER_BVZERO( filter );
316
317         suffix.bv_len = ldap_bv2escaped_filter_value_len( &be->be_nsuffix[ 0 ] );
318         if ( suffix.bv_len == be->be_nsuffix[ 0 ].bv_len ) {
319                 suffix = be->be_nsuffix[ 0 ];
320
321         } else {
322                 ldap_bv2escaped_filter_value( &be->be_nsuffix[ 0 ], &suffix );
323         }
324         
325         filter->bv_len = STRLENOF( "(&(monitoredInfo=" )
326                 + strlen( be->bd_info->bi_type )
327                 + STRLENOF( ")(namingContexts:distinguishedNameMatch:=" )
328                 + suffix.bv_len + STRLENOF( "))" );
329         ptr = filter->bv_val = ch_malloc( filter->bv_len + 1 );
330         ptr = lutil_strcopy( ptr, "(&(monitoredInfo=" );
331         ptr = lutil_strcopy( ptr, be->bd_info->bi_type );
332         ptr = lutil_strcopy( ptr, ")(namingContexts:distinguishedNameMatch:=" );
333         ptr = lutil_strncopy( ptr, suffix.bv_val, suffix.bv_len );
334         ptr = lutil_strcopy( ptr, "))" );
335         ptr[ 0 ] = '\0';
336         assert( filter->bv_len == ptr - filter->bv_val );
337         
338         if ( suffix.bv_val != be->be_nsuffix[ 0 ].bv_val ) {
339                 ch_free( suffix.bv_val );
340         }
341
342         /* alloc as many as required (plus 1 for objectClass) */
343         a = attrs_alloc( 1 + 4 );
344         if ( a == NULL ) {
345                 rc = 1;
346                 goto cleanup;
347         }
348
349         a->a_desc = slap_schema.si_ad_objectClass;
350         value_add_one( &a->a_vals, &oc_olmBDBDatabase->soc_cname );
351         a->a_nvals = a->a_vals;
352         next = a->a_next;
353
354         {
355                 struct berval   bv = BER_BVC( "0" );
356
357                 next->a_desc = ad_olmBDBEntryCache;
358                 value_add_one( &next->a_vals, &bv );
359                 next->a_nvals = next->a_vals;
360                 next = next->a_next;
361
362                 next->a_desc = ad_olmBDBEntryInfo;
363                 value_add_one( &next->a_vals, &bv );
364                 next->a_nvals = next->a_vals;
365                 next = next->a_next;
366
367                 next->a_desc = ad_olmBDBIDLCache;
368                 value_add_one( &next->a_vals, &bv );
369                 next->a_nvals = next->a_vals;
370                 next = next->a_next;
371         }
372
373         {
374                 struct berval   bv, nbv;
375                 ber_len_t       pathlen = 0, len = 0;
376                 char            path[ PATH_MAX ] = { '\0' };
377                 char            *fname = bdb->bi_dbenv_home,
378                                 *ptr;
379
380                 len = strlen( fname );
381                 if ( fname[ 0 ] != '/' ) {
382                         /* get full path name */
383                         getcwd( path, sizeof( path ) );
384                         pathlen = strlen( path );
385
386                         if ( fname[ 0 ] == '.' && fname[ 1 ] == '/' ) {
387                                 fname += 2;
388                                 len -= 2;
389                         }
390                 }
391
392                 bv.bv_len = pathlen + STRLENOF( "/" ) + len;
393                 ptr = bv.bv_val = ch_malloc( bv.bv_len + STRLENOF( "/" ) + 1 );
394                 if ( pathlen ) {
395                         ptr = lutil_strncopy( ptr, path, pathlen );
396                         ptr[ 0 ] = '/';
397                         ptr++;
398                 }
399                 ptr = lutil_strncopy( ptr, fname, len );
400                 if ( ptr[ -1 ] != '/' ) {
401                         ptr[ 0 ] = '/';
402                         ptr++;
403                 }
404                 ptr[ 0 ] = '\0';
405                 
406                 attr_normalize_one( ad_olmDbDirectory, &bv, &nbv, NULL );
407
408                 next->a_desc = ad_olmDbDirectory;
409                 next->a_vals = ch_calloc( sizeof( struct berval ), 2 );
410                 next->a_vals[ 0 ] = bv;
411
412                 if ( BER_BVISNULL( &nbv ) ) {
413                         next->a_nvals = next->a_vals;
414
415                 } else {
416                         next->a_nvals = ch_calloc( sizeof( struct berval ), 2 );
417                         next->a_nvals[ 0 ] = nbv;
418                 }
419
420                 next = next->a_next;
421         }
422
423         cb = ch_calloc( sizeof( monitor_callback_t ), 1 );
424         cb->mc_update = bdb_monitor_update;
425         cb->mc_modify = bdb_monitor_modify;
426         cb->mc_free = bdb_monitor_free;
427         cb->mc_private = (void *)bdb;
428
429         rc = mbe->register_entry_attrs( NULL, a, cb,
430                 base, LDAP_SCOPE_SUBORDINATE, filter );
431
432 cleanup:;
433         if ( rc != 0 ) {
434                 if ( cb != NULL ) {
435                         ch_free( cb );
436                         cb = NULL;
437                 }
438
439                 if ( a != NULL ) {
440                         attrs_free( a );
441                         a = NULL;
442                 }
443
444                 if ( !BER_BVISNULL( filter ) ) {
445                         ch_free( filter->bv_val );
446                         BER_BVZERO( filter );
447                 }
448         }
449
450         /* store for cleanup */
451         bdb->bi_monitor.bdm_cb = (void *)cb;
452
453         /* we don't need to keep track of the attributes, because
454          * bdb_monitor_free() takes care of everything */
455         if ( a != NULL ) {
456                 attrs_free( a );
457         }
458
459         return rc;
460 }
461
462 /*
463  * call from within bdb_db_close()
464  */
465 int
466 bdb_monitor_close( BackendDB *be )
467 {
468         struct bdb_info         *bdb = (struct bdb_info *) be->be_private;
469
470         if ( !BER_BVISNULL( &bdb->bi_monitor.bdm_filter ) ) {
471                 BackendInfo *mi = backend_info( "monitor" );
472                 monitor_extra_t *mbe;
473
474                 if ( !mi || !mi->bi_extra )
475                         return 0;
476                 mbe = mi->bi_extra;
477                 mbe->unregister_entry_callback( NULL,
478                         (monitor_callback_t *)bdb->bi_monitor.bdm_cb,
479                         &bdb->bi_monitor.bdm_nbase,
480                         bdb->bi_monitor.bdm_scope,
481                         &bdb->bi_monitor.bdm_filter );
482
483                 if ( !BER_BVISNULL( &bdb->bi_monitor.bdm_filter ) ) {
484                         ch_free( bdb->bi_monitor.bdm_filter.bv_val );
485                 }
486
487                 memset( &bdb->bi_monitor, 0, sizeof( bdb->bi_monitor ) );
488         }
489
490         return 0;
491 }
492
493 /*
494  * call from within bdb_db_destroy()
495  */
496 int
497 bdb_monitor_destroy( BackendDB *be )
498 {
499         return 0;
500 }