1 /* $NetBSD: monitor.c,v 1.2 2021/08/14 16:14:58 christos Exp $ */
2
3 /* init.c - initialize various things */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 *
7 * Copyright 1998-2021 The OpenLDAP Foundation.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
12 * Public License.
13 *
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
17 */
18 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
19 * All rights reserved.
20 *
21 * Redistribution and use in source and binary forms are permitted
22 * provided that this notice is preserved and that due credit is given
23 * to the University of Michigan at Ann Arbor. The name of the University
24 * may not be used to endorse or promote products derived from this
25 * software without specific prior written permission. This software
26 * is provided ``as is'' without express or implied warranty.
27 */
28
29 #include <sys/cdefs.h>
30 __RCSID("$NetBSD: monitor.c,v 1.2 2021/08/14 16:14:58 christos Exp $");
31
32 #include "portable.h"
33
34 #include <stdio.h>
35
36 #include <ac/socket.h>
37 #include <ac/string.h>
38 #include <ac/time.h>
39
40 #include "lload.h"
41 #include "lber_pvt.h"
42
43 #include "ldap_rq.h"
44 #include "lload-config.h"
45 #include "../slapd/back-monitor/back-monitor.h"
46
47 #define LLOAD_MONITOR_BALANCER_NAME "Load Balancer"
48 #define LLOAD_MONITOR_BALANCER_RDN \
49 SLAPD_MONITOR_AT "=" LLOAD_MONITOR_BALANCER_NAME
50 #define LLOAD_MONITOR_BALANCER_DN \
51 LLOAD_MONITOR_BALANCER_RDN "," SLAPD_MONITOR_BACKEND_DN
52
53 #define LLOAD_MONITOR_INCOMING_NAME "Incoming Connections"
54 #define LLOAD_MONITOR_INCOMING_RDN \
55 SLAPD_MONITOR_AT "=" LLOAD_MONITOR_INCOMING_NAME
56 #define LLOAD_MONITOR_INCOMING_DN \
57 LLOAD_MONITOR_INCOMING_RDN "," LLOAD_MONITOR_BALANCER_DN
58
59 #define LLOAD_MONITOR_OPERATIONS_NAME "Operations"
60 #define LLOAD_MONITOR_OPERATIONS_RDN \
61 SLAPD_MONITOR_AT "=" LLOAD_MONITOR_OPERATIONS_NAME
62 #define LLOAD_MONITOR_OPERATIONS_DN \
63 LLOAD_MONITOR_OPERATIONS_RDN "," LLOAD_MONITOR_BALANCER_DN
64
65 #define LLOAD_MONITOR_BACKENDS_NAME "Backend Servers"
66 #define LLOAD_MONITOR_BACKENDS_RDN \
67 SLAPD_MONITOR_AT "=" LLOAD_MONITOR_BACKENDS_NAME
68 #define LLOAD_MONITOR_BACKENDS_DN \
69 LLOAD_MONITOR_BACKENDS_RDN "," LLOAD_MONITOR_BALANCER_DN
70
71 struct lload_monitor_ops_t {
72 struct berval rdn;
73 } lload_monitor_op[] = {
74 { BER_BVC("cn=Bind") },
75 { BER_BVC("cn=Other") },
76
77 { BER_BVNULL }
78 };
79
80 static ObjectClass *oc_olmBalancer;
81 static ObjectClass *oc_olmBalancerServer;
82 static ObjectClass *oc_olmBalancerConnection;
83 static ObjectClass *oc_olmBalancerOperation;
84
85 static ObjectClass *oc_monitorContainer;
86 static ObjectClass *oc_monitorCounterObject;
87
88 static AttributeDescription *ad_olmServerURI;
89 static AttributeDescription *ad_olmReceivedOps;
90 static AttributeDescription *ad_olmForwardedOps;
91 static AttributeDescription *ad_olmRejectedOps;
92 static AttributeDescription *ad_olmCompletedOps;
93 static AttributeDescription *ad_olmFailedOps;
94 static AttributeDescription *ad_olmConnectionType;
95 static AttributeDescription *ad_olmPendingOps;
96 static AttributeDescription *ad_olmPendingConnections;
97 static AttributeDescription *ad_olmActiveConnections;
98 static AttributeDescription *ad_olmIncomingConnections;
99 static AttributeDescription *ad_olmOutgoingConnections;
100
101 static struct {
102 char *name;
103 char *oid;
104 } s_oid[] = {
105 { "olmBalancerAttributes", "olmModuleAttributes:1" },
106 { "olmBalancerObjectClasses", "olmModuleObjectClasses:1" },
107
108 { NULL }
109 };
110
111 static struct {
112 char *desc;
113 AttributeDescription **ad;
114 } s_at[] = {
115 { "( olmBalancerAttributes:1 "
116 "NAME ( 'olmServerURI' ) "
117 "DESC 'URI of a backend server' "
118 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
119 "EQUALITY caseIgnoreMatch "
120 "NO-USER-MODIFICATION "
121 "USAGE dSAOperation )",
122 &ad_olmServerURI },
123 { "( olmBalancerAttributes:2 "
124 "NAME ( 'olmReceivedOps' ) "
125 "DESC 'monitor received operations' "
126 "SUP monitorCounter "
127 "NO-USER-MODIFICATION "
128 "USAGE dSAOperation )",
129 &ad_olmReceivedOps },
130 { "( olmBalancerAttributes:3 "
131 "NAME ( 'olmForwardedOps' ) "
132 "DESC 'monitor forwarded operations' "
133 "SUP monitorCounter "
134 "NO-USER-MODIFICATION "
135 "USAGE dSAOperation )",
136 &ad_olmForwardedOps },
137 { "( olmBalancerAttributes:4 "
138 "NAME ( 'olmRejectedOps' ) "
139 "DESC 'monitor rejected operations' "
140 "SUP monitorCounter "
141 "NO-USER-MODIFICATION "
142 "USAGE dSAOperation )",
143 &ad_olmRejectedOps },
144 { "( olmBalancerAttributes:5 "
145 "NAME ( 'olmCompletedOps' ) "
146 "DESC 'monitor completed operations' "
147 "SUP monitorCounter "
148 "NO-USER-MODIFICATION "
149 "USAGE dSAOperation )",
150 &ad_olmCompletedOps },
151 { "( olmBalancerAttributes:6 "
152 "NAME ( 'olmFailedOps' ) "
153 "DESC 'monitor failed operations' "
154 "SUP monitorCounter "
155 "NO-USER-MODIFICATION "
156 "USAGE dSAOperation )",
157 &ad_olmFailedOps },
158 { "( olmBalancerAttributes:7 "
159 "NAME ( 'olmPendingOps' ) "
160 "DESC 'monitor number of pending operations' "
161 "EQUALITY integerMatch "
162 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 "
163 "NO-USER-MODIFICATION "
164 "USAGE dSAOperation )",
165 &ad_olmPendingOps },
166 { "( olmBalancerAttributes:8 "
167 "NAME ( 'olmPendingConnections' ) "
168 "DESC 'monitor number of pending connections' "
169 "EQUALITY integerMatch "
170 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 "
171 "NO-USER-MODIFICATION "
172 "USAGE dSAOperation )",
173 &ad_olmPendingConnections },
174 { "( olmBalancerAttributes:9 "
175 "NAME ( 'olmActiveConnections' ) "
176 "DESC 'monitor number of active connections' "
177 "EQUALITY integerMatch "
178 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 "
179 "NO-USER-MODIFICATION "
180 "USAGE dSAOperation )",
181 &ad_olmActiveConnections },
182 { "( olmBalancerAttributes:10 "
183 "NAME ( 'olmConnectionType' ) "
184 "DESC 'Connection type' "
185 "EQUALITY caseIgnoreMatch "
186 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
187 "NO-USER-MODIFICATION "
188 "USAGE dSAOperation )",
189 &ad_olmConnectionType },
190 { "( olmBalancerAttributes:11 "
191 "NAME ( 'olmIncomingConnections' ) "
192 "DESC 'monitor number of incoming connections' "
193 "EQUALITY integerMatch "
194 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 "
195 "NO-USER-MODIFICATION "
196 "USAGE dSAOperation )",
197 &ad_olmIncomingConnections },
198 { "( olmBalancerAttributes:12 "
199 "NAME ( 'olmOutgoingConnections' ) "
200 "DESC 'monitor number of active connections' "
201 "EQUALITY integerMatch "
202 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 "
203 "NO-USER-MODIFICATION "
204 "USAGE dSAOperation )",
205 &ad_olmOutgoingConnections },
206
207 { NULL }
208 };
209
210 static struct {
211 char *name;
212 ObjectClass **oc;
213 } s_moc[] = {
214 { "monitorContainer", &oc_monitorContainer },
215 { "monitorCounterObject", &oc_monitorCounterObject },
216
217 { NULL }
218 };
219
220 static struct {
221 char *desc;
222 ObjectClass **oc;
223 } s_oc[] = {
224 { "( olmBalancerObjectClasses:1 "
225 "NAME ( 'olmBalancer' ) "
226 "SUP top STRUCTURAL "
227 "MAY ( "
228 "olmIncomingConnections "
229 "$ olmOutgoingConnections "
230 ") )",
231 &oc_olmBalancer },
232 { "( olmBalancerObjectClasses:2 "
233 "NAME ( 'olmBalancerServer' ) "
234 "SUP top STRUCTURAL "
235 "MAY ( "
236 "olmServerURI "
237 "$ olmActiveConnections "
238 "$ olmPendingConnections "
239 "$ olmPendingOps"
240 "$ olmReceivedOps "
241 "$ olmCompletedOps "
242 "$ olmFailedOps "
243 ") )",
244 &oc_olmBalancerServer },
245
246 { "( olmBalancerObjectClasses:3 "
247 "NAME ( 'olmBalancerOperation' ) "
248 "SUP top STRUCTURAL "
249 "MAY ( "
250 "olmReceivedOps "
251 "$ olmForwardedOps "
252 "$ olmRejectedOps "
253 "$ olmCompletedOps "
254 "$ olmFailedOps "
255 ") )",
256 &oc_olmBalancerOperation },
257 { "( olmBalancerObjectClasses:4 "
258 "NAME ( 'olmBalancerConnection' ) "
259 "SUP top STRUCTURAL "
260 "MAY ( "
261 "olmConnectionType "
262 "$ olmPendingOps "
263 "$ olmReceivedOps "
264 "$ olmCompletedOps "
265 "$ olmFailedOps "
266 ") )",
267 &oc_olmBalancerConnection },
268 { NULL }
269 };
270
271 static int
lload_monitor_subsystem_destroy(BackendDB * be,monitor_subsys_t * ms)272 lload_monitor_subsystem_destroy( BackendDB *be, monitor_subsys_t *ms )
273 {
274 return LDAP_SUCCESS;
275 }
276
277 static int
lload_monitor_backend_destroy(BackendDB * be,monitor_subsys_t * ms)278 lload_monitor_backend_destroy( BackendDB *be, monitor_subsys_t *ms )
279 {
280 LloadBackend *b = ms->mss_private;
281 monitor_extra_t *mbe;
282 int rc = LDAP_SUCCESS;
283
284 mbe = (monitor_extra_t *)be->bd_info->bi_extra;
285 if ( b->b_monitor ) {
286 ms->mss_destroy = lload_monitor_subsystem_destroy;
287
288 assert( b->b_monitor == ms );
289 b->b_monitor = NULL;
290
291 rc = mbe->unregister_entry( &ms->mss_ndn );
292 ber_memfree( ms->mss_dn.bv_val );
293 ber_memfree( ms->mss_ndn.bv_val );
294 }
295
296 return rc;
297 }
298
299 static void
lload_monitor_balancer_dispose(void ** priv)300 lload_monitor_balancer_dispose( void **priv )
301 {
302 return;
303 }
304
305 static int
lload_monitor_balancer_free(Entry * e,void ** priv)306 lload_monitor_balancer_free( Entry *e, void **priv )
307 {
308 return LDAP_SUCCESS;
309 }
310
311 static int
lload_monitor_balancer_update(Operation * op,SlapReply * rs,Entry * e,void * priv)312 lload_monitor_balancer_update(
313 Operation *op,
314 SlapReply *rs,
315 Entry *e,
316 void *priv )
317 {
318 Attribute *a;
319
320 a = attr_find( e->e_attrs, ad_olmIncomingConnections );
321 assert( a != NULL );
322
323 UI2BV( &a->a_vals[0], lload_stats.global_incoming );
324
325 a = attr_find( e->e_attrs, ad_olmOutgoingConnections );
326 assert( a != NULL );
327
328 UI2BV( &a->a_vals[0], lload_stats.global_outgoing );
329 return SLAP_CB_CONTINUE;
330 }
331
332 static int
lload_monitor_ops_update(Operation * op,SlapReply * rs,Entry * e,void * priv)333 lload_monitor_ops_update( Operation *op, SlapReply *rs, Entry *e, void *priv )
334 {
335 Attribute *a;
336 lload_counters_t *counters = (lload_counters_t *)priv;
337
338 a = attr_find( e->e_attrs, ad_olmReceivedOps );
339 assert( a != NULL );
340 UI2BV( &a->a_vals[0], counters->lc_ops_received );
341
342 a = attr_find( e->e_attrs, ad_olmForwardedOps );
343 assert( a != NULL );
344 UI2BV( &a->a_vals[0], counters->lc_ops_forwarded );
345
346 a = attr_find( e->e_attrs, ad_olmRejectedOps );
347 assert( a != NULL );
348 UI2BV( &a->a_vals[0], counters->lc_ops_rejected );
349
350 a = attr_find( e->e_attrs, ad_olmCompletedOps );
351 assert( a != NULL );
352 UI2BV( &a->a_vals[0], counters->lc_ops_completed );
353
354 a = attr_find( e->e_attrs, ad_olmFailedOps );
355 assert( a != NULL );
356 UI2BV( &a->a_vals[0], counters->lc_ops_failed );
357
358 return SLAP_CB_CONTINUE;
359 }
360
361 static void
lload_monitor_ops_dispose(void ** priv)362 lload_monitor_ops_dispose( void **priv )
363 {
364 return;
365 }
366
367 static int
lload_monitor_ops_free(Entry * e,void ** priv)368 lload_monitor_ops_free( Entry *e, void **priv )
369 {
370 return LDAP_SUCCESS;
371 }
372
373 static int
lload_monitor_balancer_init(BackendDB * be,monitor_subsys_t * ms)374 lload_monitor_balancer_init( BackendDB *be, monitor_subsys_t *ms )
375 {
376 monitor_extra_t *mbe;
377 Entry *e;
378 int rc;
379 monitor_callback_t *cb;
380 struct berval value = BER_BVC("0");
381
382 assert( be != NULL );
383
384 mbe = (monitor_extra_t *)be->bd_info->bi_extra;
385
386 dnNormalize( 0, NULL, NULL, &ms->mss_dn, &ms->mss_ndn, NULL );
387
388 e = mbe->entry_stub( &ms->mss_dn, &ms->mss_ndn, &ms->mss_rdn,
389 oc_olmBalancer, NULL, NULL );
390 if ( e == NULL ) {
391 Debug( LDAP_DEBUG_ANY, "lload_monitor_balancer_init: "
392 "unable to create entry \"%s,%s\"\n",
393 ms->mss_rdn.bv_val, ms->mss_ndn.bv_val );
394 return -1;
395 }
396
397 ch_free( ms->mss_ndn.bv_val );
398 ber_dupbv( &ms->mss_dn, &e->e_name );
399 ber_dupbv( &ms->mss_ndn, &e->e_nname );
400
401 cb = ch_calloc( sizeof(monitor_callback_t), 1 );
402 cb->mc_update = lload_monitor_balancer_update;
403 cb->mc_free = lload_monitor_balancer_free;
404 cb->mc_dispose = lload_monitor_balancer_dispose;
405 cb->mc_private = NULL;
406
407 attr_merge_normalize_one( e, ad_olmIncomingConnections, &value, NULL );
408 attr_merge_normalize_one( e, ad_olmOutgoingConnections, &value, NULL );
409
410 rc = mbe->register_entry( e, cb, ms, 0 );
411 if ( rc != LDAP_SUCCESS ) {
412 Debug( LDAP_DEBUG_ANY, "lload_monitor_balancer_init: "
413 "unable to register entry \"%s\" for monitoring\n",
414 e->e_name.bv_val );
415 goto done;
416 }
417
418 done:
419 entry_free( e );
420
421 return rc;
422 }
423
424 static int
lload_monitor_ops_init(BackendDB * be,monitor_subsys_t * ms)425 lload_monitor_ops_init( BackendDB *be, monitor_subsys_t *ms )
426 {
427 monitor_extra_t *mbe;
428 Entry *e, *parent;
429 int rc;
430 int i;
431 struct berval value = BER_BVC("0");
432
433 assert( be != NULL );
434
435 mbe = (monitor_extra_t *)be->bd_info->bi_extra;
436
437 dnNormalize( 0, NULL, NULL, &ms->mss_dn, &ms->mss_ndn, NULL );
438 ms->mss_destroy = lload_monitor_subsystem_destroy;
439
440 parent = mbe->entry_stub( &ms->mss_dn, &ms->mss_ndn, &ms->mss_rdn,
441 oc_monitorContainer, NULL, NULL );
442 if ( parent == NULL ) {
443 Debug( LDAP_DEBUG_ANY, "lload_monitor_ops_init: "
444 "unable to create entry \"%s,%s\"\n",
445 ms->mss_rdn.bv_val, ms->mss_ndn.bv_val );
446 return -1;
447 }
448 ch_free( ms->mss_ndn.bv_val );
449 ber_dupbv( &ms->mss_dn, &parent->e_name );
450 ber_dupbv( &ms->mss_ndn, &parent->e_nname );
451
452 rc = mbe->register_entry( parent, NULL, ms, MONITOR_F_PERSISTENT_CH );
453 if ( rc != LDAP_SUCCESS ) {
454 Debug( LDAP_DEBUG_ANY, "lload_monitor_ops_init: "
455 "unable to register entry \"%s\" for monitoring\n",
456 parent->e_name.bv_val );
457 goto done;
458 }
459
460 for ( i = 0; lload_monitor_op[i].rdn.bv_val != NULL; i++ ) {
461 monitor_callback_t *cb;
462 e = mbe->entry_stub( &parent->e_name, &parent->e_nname,
463 &lload_monitor_op[i].rdn, oc_olmBalancerOperation, NULL, NULL );
464 if ( e == NULL ) {
465 Debug( LDAP_DEBUG_ANY, "lload_monitor_ops_init: "
466 "unable to create entry \"%s,%s\"\n",
467 lload_monitor_op[i].rdn.bv_val, parent->e_nname.bv_val );
468 return -1;
469 }
470
471 /* attr_merge_normalize_one( e, ad_olmDbOperations, &value, NULL ); */
472
473 /*
474 * We cannot share a single callback between entries.
475 *
476 * monitor_cache_destroy() tries to free all callbacks and it's called
477 * before mss_destroy() so we have no chance of handling it ourselves
478 */
479 cb = ch_calloc( sizeof(monitor_callback_t), 1 );
480 cb->mc_update = lload_monitor_ops_update;
481 cb->mc_free = lload_monitor_ops_free;
482 cb->mc_dispose = lload_monitor_ops_dispose;
483 cb->mc_private = &lload_stats.counters[i];
484
485 attr_merge_normalize_one( e, ad_olmReceivedOps, &value, NULL );
486 attr_merge_normalize_one( e, ad_olmForwardedOps, &value, NULL );
487 attr_merge_normalize_one( e, ad_olmRejectedOps, &value, NULL );
488 attr_merge_normalize_one( e, ad_olmCompletedOps, &value, NULL );
489 attr_merge_normalize_one( e, ad_olmFailedOps, &value, NULL );
490
491 rc = mbe->register_entry( e, cb, ms, 0 );
492
493 entry_free( e );
494
495 if ( rc != LDAP_SUCCESS ) {
496 Debug( LDAP_DEBUG_ANY, "lload_monitor_ops_init: "
497 "unable to register entry \"%s\" for monitoring\n",
498 e->e_name.bv_val );
499 ch_free( cb );
500 break;
501 }
502 }
503
504 done:
505 entry_free( parent );
506 return rc;
507 }
508
509 static int
lload_monitor_in_conn_entry(LloadConnection * conn,void * argv)510 lload_monitor_in_conn_entry( LloadConnection *conn, void *argv )
511 {
512 Entry *e;
513 monitor_entry_t *mp;
514 struct lload_monitor_conn_arg *arg = argv;
515 monitor_extra_t *mbe = arg->op->o_bd->bd_info->bi_extra;
516 char buf[SLAP_TEXT_BUFLEN];
517 struct berval bv;
518
519 bv.bv_val = buf;
520 bv.bv_len = snprintf(
521 bv.bv_val, SLAP_TEXT_BUFLEN, "cn=Connection %lu", conn->c_connid );
522
523 e = mbe->entry_stub( &arg->ms->mss_dn, &arg->ms->mss_ndn, &bv,
524 oc_olmBalancerConnection, NULL, NULL );
525
526 mp = mbe->entrypriv_create();
527 e->e_private = mp;
528 mp->mp_info = arg->ms;
529 mp->mp_flags = MONITOR_F_SUB | MONITOR_F_VOLATILE;
530
531 *arg->ep = e;
532 arg->ep = &mp->mp_next;
533
534 return 0;
535 }
536
537 static int
lload_monitor_in_conn_create(Operation * op,SlapReply * rs,struct berval * ndn,Entry * e_parent,Entry ** ep)538 lload_monitor_in_conn_create(
539 Operation *op,
540 SlapReply *rs,
541 struct berval *ndn,
542 Entry *e_parent,
543 Entry **ep )
544 {
545 monitor_entry_t *mp_parent;
546 struct lload_monitor_conn_arg arg = {
547 .op = op,
548 .ep = ep,
549 };
550
551 assert( e_parent->e_private != NULL );
552
553 mp_parent = e_parent->e_private;
554 arg.ms = (monitor_subsys_t *)mp_parent->mp_info;
555
556 checked_lock( &clients_mutex );
557 connections_walk(
558 &clients_mutex, &clients, lload_monitor_in_conn_entry, &arg );
559 checked_unlock( &clients_mutex );
560
561 return 0;
562 }
563
564 static int
lload_monitor_up_conn_entry(LloadConnection * c,void * argv)565 lload_monitor_up_conn_entry( LloadConnection *c, void *argv )
566 {
567 Entry *e;
568 monitor_entry_t *mp;
569 struct lload_monitor_conn_arg *arg = argv;
570 monitor_extra_t *mbe = arg->op->o_bd->bd_info->bi_extra;
571 char buf[SLAP_TEXT_BUFLEN];
572 struct berval bv_rdn,
573 bv_type = BER_BVNULL,
574 bv_pending = BER_BVNULL,
575 bv_received = BER_BVNULL,
576 bv_completed = BER_BVNULL,
577 bv_failed = BER_BVNULL;
578
579 bv_rdn.bv_val = buf;
580 bv_rdn.bv_len = snprintf(
581 bv_rdn.bv_val, SLAP_TEXT_BUFLEN, "cn=Connection %lu", c->c_connid );
582
583 e = mbe->entry_stub( &arg->ms->mss_dn, &arg->ms->mss_ndn, &bv_rdn,
584 oc_olmBalancerConnection, NULL, NULL );
585
586 switch ( c->c_type ) {
587 case LLOAD_C_OPEN: {
588 struct berval bv = BER_BVC("regular");
589 bv_type = bv;
590 } break;
591 case LLOAD_C_PREPARING: {
592 struct berval bv = BER_BVC("preparing");
593 bv_type = bv;
594 } break;
595 case LLOAD_C_BIND: {
596 struct berval bv = BER_BVC("bind");
597 bv_type = bv;
598 } break;
599 case LLOAD_C_PRIVILEGED: {
600 struct berval bv = BER_BVC("privileged");
601 bv_type = bv;
602 } break;
603 default: {
604 struct berval bv = BER_BVC("unknown");
605 bv_type = bv;
606 } break;
607 }
608
609 UI2BV( &bv_pending, (long long unsigned int)c->c_n_ops_executing );
610 UI2BV( &bv_received, c->c_counters.lc_ops_received );
611 UI2BV( &bv_completed, c->c_counters.lc_ops_completed );
612 UI2BV( &bv_failed, c->c_counters.lc_ops_failed );
613
614 attr_merge_normalize_one( e, ad_olmConnectionType, &bv_type, NULL );
615 attr_merge_normalize_one( e, ad_olmPendingOps, &bv_pending, NULL );
616 attr_merge_normalize_one( e, ad_olmReceivedOps, &bv_received, NULL );
617 attr_merge_normalize_one( e, ad_olmCompletedOps, &bv_completed, NULL );
618 attr_merge_normalize_one( e, ad_olmFailedOps, &bv_failed, NULL );
619
620 ch_free( bv_pending.bv_val );
621 ch_free( bv_received.bv_val );
622 ch_free( bv_completed.bv_val );
623 ch_free( bv_failed.bv_val );
624 mp = mbe->entrypriv_create();
625 e->e_private = mp;
626 mp->mp_info = arg->ms;
627 mp->mp_flags = MONITOR_F_SUB | MONITOR_F_VOLATILE;
628
629 *arg->ep = e;
630 arg->ep = &mp->mp_next;
631
632 return 0;
633 }
634
635 static int
lload_monitor_up_conn_create(Operation * op,SlapReply * rs,struct berval * ndn,Entry * e_parent,Entry ** ep)636 lload_monitor_up_conn_create(
637 Operation *op,
638 SlapReply *rs,
639 struct berval *ndn,
640 Entry *e_parent,
641 Entry **ep )
642 {
643 monitor_entry_t *mp_parent;
644 monitor_subsys_t *ms;
645 LloadBackend *b;
646 struct lload_monitor_conn_arg arg = {
647 .op = op,
648 .ep = ep,
649 };
650
651 assert( e_parent->e_private != NULL );
652
653 mp_parent = e_parent->e_private;
654 ms = (monitor_subsys_t *)mp_parent->mp_info;
655 b = ms->mss_private;
656
657 if ( !b ) {
658 return -1;
659 }
660
661 arg.ms = ms;
662
663 checked_lock( &b->b_mutex );
664 connections_walk_last( &b->b_mutex, &b->b_conns, b->b_last_conn,
665 lload_monitor_up_conn_entry, &arg );
666
667 connections_walk_last( &b->b_mutex, &b->b_bindconns, b->b_last_bindconn,
668 lload_monitor_up_conn_entry, &arg );
669 checked_unlock( &b->b_mutex );
670
671 return 0;
672 }
673
674 int
lload_monitor_incoming_conn_init(BackendDB * be,monitor_subsys_t * ms)675 lload_monitor_incoming_conn_init( BackendDB *be, monitor_subsys_t *ms )
676 {
677 monitor_extra_t *mbe;
678 Entry *e;
679 int rc;
680
681 assert( be != NULL );
682 mbe = (monitor_extra_t *)be->bd_info->bi_extra;
683
684 ms->mss_create = lload_monitor_in_conn_create;
685 ms->mss_destroy = lload_monitor_subsystem_destroy;
686
687 dnNormalize( 0, NULL, NULL, &ms->mss_dn, &ms->mss_ndn, NULL );
688
689 e = mbe->entry_stub( &ms->mss_dn, &ms->mss_ndn, &ms->mss_rdn,
690 oc_monitorContainer, NULL, NULL );
691 if ( e == NULL ) {
692 Debug( LDAP_DEBUG_ANY, "lload_monitor_incoming_conn_init: "
693 "unable to create entry \"%s,%s\"\n",
694 ms->mss_rdn.bv_val, ms->mss_ndn.bv_val );
695 return -1;
696 }
697 ch_free( ms->mss_ndn.bv_val );
698 ber_dupbv( &ms->mss_dn, &e->e_name );
699 ber_dupbv( &ms->mss_ndn, &e->e_nname );
700
701 rc = mbe->register_entry( e, NULL, ms, MONITOR_F_VOLATILE_CH );
702
703 if ( rc != LDAP_SUCCESS ) {
704 Debug( LDAP_DEBUG_ANY, "lload_monitor_incoming_conn_init: "
705 "unable to register entry \"%s\" for monitoring\n",
706 e->e_name.bv_val );
707 goto done;
708 }
709 done:
710 entry_free( e );
711
712 return rc;
713 }
714
715 static int
lload_monitor_server_update(Operation * op,SlapReply * rs,Entry * e,void * priv)716 lload_monitor_server_update(
717 Operation *op,
718 SlapReply *rs,
719 Entry *e,
720 void *priv )
721 {
722 Attribute *a;
723 LloadBackend *b = priv;
724 LloadConnection *c;
725 LloadPendingConnection *pc;
726 ldap_pvt_mp_t active = 0, pending = 0, received = 0, completed = 0,
727 failed = 0;
728 int i;
729
730 checked_lock( &b->b_mutex );
731 active = b->b_active + b->b_bindavail;
732
733 LDAP_CIRCLEQ_FOREACH ( c, &b->b_preparing, c_next ) {
734 pending++;
735 }
736
737 LDAP_LIST_FOREACH( pc, &b->b_connecting, next ) {
738 pending++;
739 }
740
741 for ( i = 0; i < LLOAD_STATS_OPS_LAST; i++ ) {
742 received += b->b_counters[i].lc_ops_received;
743 completed += b->b_counters[i].lc_ops_completed;
744 failed += b->b_counters[i].lc_ops_failed;
745 }
746
747 a = attr_find( e->e_attrs, ad_olmPendingOps );
748 assert( a != NULL );
749 UI2BV( &a->a_vals[0], (long long unsigned int)b->b_n_ops_executing );
750
751 checked_unlock( &b->b_mutex );
752
753 /* Right now, there is no way to retrieve the entry from monitor's
754 * cache to replace URI at the moment it is modified */
755 a = attr_find( e->e_attrs, ad_olmServerURI );
756 assert( a != NULL );
757 ber_bvreplace( &a->a_vals[0], &b->b_uri );
758
759 a = attr_find( e->e_attrs, ad_olmActiveConnections );
760 assert( a != NULL );
761 UI2BV( &a->a_vals[0], active );
762
763 a = attr_find( e->e_attrs, ad_olmPendingConnections );
764 assert( a != NULL );
765 UI2BV( &a->a_vals[0], pending );
766
767 a = attr_find( e->e_attrs, ad_olmReceivedOps );
768 assert( a != NULL );
769 UI2BV( &a->a_vals[0], received );
770
771 a = attr_find( e->e_attrs, ad_olmCompletedOps );
772 assert( a != NULL );
773 UI2BV( &a->a_vals[0], completed );
774
775 a = attr_find( e->e_attrs, ad_olmFailedOps );
776 assert( a != NULL );
777 UI2BV( &a->a_vals[0], failed );
778
779 return SLAP_CB_CONTINUE;
780 }
781
782 static int
lload_monitor_backend_open(BackendDB * be,monitor_subsys_t * ms)783 lload_monitor_backend_open( BackendDB *be, monitor_subsys_t *ms )
784 {
785 Entry *e;
786 struct berval value = BER_BVC("0");
787 monitor_extra_t *mbe;
788 monitor_callback_t *cb;
789 LloadBackend *b = ms->mss_private;
790 int rc;
791
792 assert( be != NULL );
793 mbe = (monitor_extra_t *)be->bd_info->bi_extra;
794
795 dnNormalize( 0, NULL, NULL, &ms->mss_dn, &ms->mss_ndn, NULL );
796 e = mbe->entry_stub( &ms->mss_dn, &ms->mss_ndn, &ms->mss_rdn,
797 oc_olmBalancerServer, NULL, NULL );
798 if ( e == NULL ) {
799 Debug( LDAP_DEBUG_ANY, "lload_monitor_backend_open: "
800 "unable to create entry \"%s,%s\"\n",
801 ms->mss_rdn.bv_val, ms->mss_ndn.bv_val );
802 return -1;
803 }
804
805 ch_free( ms->mss_ndn.bv_val );
806 ber_dupbv( &ms->mss_dn, &e->e_name );
807 ber_dupbv( &ms->mss_ndn, &e->e_nname );
808
809 cb = ch_calloc( sizeof(monitor_callback_t), 1 );
810 cb->mc_update = lload_monitor_server_update;
811 cb->mc_free = NULL;
812 cb->mc_dispose = NULL;
813 cb->mc_private = b;
814
815 attr_merge_normalize_one( e, ad_olmServerURI, &b->b_uri, NULL );
816 attr_merge_normalize_one( e, ad_olmActiveConnections, &value, NULL );
817 attr_merge_normalize_one( e, ad_olmPendingConnections, &value, NULL );
818 attr_merge_normalize_one( e, ad_olmPendingOps, &value, NULL );
819 attr_merge_normalize_one( e, ad_olmReceivedOps, &value, NULL );
820 attr_merge_normalize_one( e, ad_olmCompletedOps, &value, NULL );
821 attr_merge_normalize_one( e, ad_olmFailedOps, &value, NULL );
822
823 rc = mbe->register_entry( e, cb, ms, MONITOR_F_VOLATILE_CH );
824
825 if ( rc != LDAP_SUCCESS ) {
826 Debug( LDAP_DEBUG_ANY, "lload_monitor_backend_open: "
827 "unable to register entry \"%s\" for monitoring\n",
828 e->e_name.bv_val );
829 goto done;
830 }
831
832 b->b_monitor = ms;
833 ms->mss_destroy = lload_monitor_backend_destroy;
834
835 done:
836 entry_free( e );
837 return rc;
838 }
839
840 int
lload_monitor_backend_init(BackendInfo * bi,LloadBackend * b)841 lload_monitor_backend_init( BackendInfo *bi, LloadBackend *b )
842 {
843 monitor_extra_t *mbe;
844 monitor_subsys_t *bk_mss;
845
846 mbe = (monitor_extra_t *)bi->bi_extra;
847
848 /* FIXME: With back-monitor as it works now, there is no way to know when
849 * this can be safely freed so we leak it on shutdown */
850 bk_mss = ch_calloc( 1, sizeof(monitor_subsys_t) );
851 bk_mss->mss_rdn.bv_len = sizeof("cn=") + b->b_name.bv_len;
852 bk_mss->mss_rdn.bv_val = ch_malloc( bk_mss->mss_rdn.bv_len );
853 bk_mss->mss_rdn.bv_len = snprintf( bk_mss->mss_rdn.bv_val,
854 bk_mss->mss_rdn.bv_len, "cn=%s", b->b_name.bv_val );
855
856 ber_str2bv( LLOAD_MONITOR_BACKENDS_DN, 0, 0, &bk_mss->mss_dn );
857 bk_mss->mss_name = b->b_name.bv_val;
858 bk_mss->mss_flags = MONITOR_F_VOLATILE_CH;
859 bk_mss->mss_open = lload_monitor_backend_open;
860 bk_mss->mss_create = lload_monitor_up_conn_create;
861 bk_mss->mss_destroy = lload_monitor_subsystem_destroy;
862 bk_mss->mss_update = NULL;
863 bk_mss->mss_private = b;
864
865 if ( mbe->register_subsys_late( bk_mss ) ) {
866 Debug( LDAP_DEBUG_ANY, "lload_monitor_backend_init: "
867 "failed to register backend %s\n",
868 bk_mss->mss_name );
869 return -1;
870 }
871 return LDAP_SUCCESS;
872 }
873
874 int
lload_monitor_backends_init(BackendDB * be,monitor_subsys_t * ms)875 lload_monitor_backends_init( BackendDB *be, monitor_subsys_t *ms )
876 {
877 monitor_extra_t *mbe;
878 Entry *e;
879 int rc;
880 LloadBackend *b;
881
882 assert( be != NULL );
883 mbe = (monitor_extra_t *)be->bd_info->bi_extra;
884
885 dnNormalize( 0, NULL, NULL, &ms->mss_dn, &ms->mss_ndn, NULL );
886
887 e = mbe->entry_stub( &ms->mss_dn, &ms->mss_ndn, &ms->mss_rdn,
888 oc_monitorContainer, NULL, NULL );
889 if ( e == NULL ) {
890 Debug( LDAP_DEBUG_ANY, "lload_monitor_incoming_conn_init: "
891 "unable to create entry \"%s,%s\"\n",
892 ms->mss_rdn.bv_val, ms->mss_ndn.bv_val );
893 return -1;
894 }
895 ch_free( ms->mss_ndn.bv_val );
896 ber_dupbv( &ms->mss_dn, &e->e_name );
897 ber_dupbv( &ms->mss_ndn, &e->e_nname );
898
899 rc = mbe->register_entry( e, NULL, ms, MONITOR_F_PERSISTENT_CH );
900
901 if ( rc != LDAP_SUCCESS ) {
902 Debug( LDAP_DEBUG_ANY, "lload_monitor_backends_init: "
903 "unable to register entry \"%s\" for monitoring\n",
904 e->e_name.bv_val );
905 goto done;
906 }
907
908 LDAP_CIRCLEQ_FOREACH ( b, &backend, b_next ) {
909 if ( (rc = lload_monitor_backend_init( be->bd_info, b )) ) {
910 break;
911 }
912 }
913 done:
914 entry_free( e );
915
916 return rc;
917 }
918
919 static int
lload_monitor_incoming_count(LloadConnection * conn,void * argv)920 lload_monitor_incoming_count( LloadConnection *conn, void *argv )
921 {
922 lload_global_stats_t *tmp_stats = argv;
923 tmp_stats->global_incoming++;
924 return 0;
925 }
926
927 /*
928 * Update all global statistics other than rejected and received,
929 * which are updated in real time
930 */
931 void *
lload_monitor_update_global_stats(void * ctx,void * arg)932 lload_monitor_update_global_stats( void *ctx, void *arg )
933 {
934 struct re_s *rtask = arg;
935 lload_global_stats_t tmp_stats = {};
936 LloadBackend *b;
937 int i;
938
939 Debug( LDAP_DEBUG_TRACE, "lload_monitor_update_global_stats: "
940 "updating stats\n" );
941
942 /* count incoming connections */
943 checked_lock( &clients_mutex );
944 connections_walk( &clients_mutex, &clients, lload_monitor_incoming_count,
945 &tmp_stats );
946 checked_unlock( &clients_mutex );
947
948 LDAP_CIRCLEQ_FOREACH ( b, &backend, b_next ) {
949 checked_lock( &b->b_mutex );
950 tmp_stats.global_outgoing += b->b_active + b->b_bindavail;
951
952 /* merge completed and failed stats */
953 for ( i = 0; i < LLOAD_STATS_OPS_LAST; i++ ) {
954 tmp_stats.counters[i].lc_ops_completed +=
955 b->b_counters[i].lc_ops_completed;
956 tmp_stats.counters[i].lc_ops_failed +=
957 b->b_counters[i].lc_ops_failed;
958 }
959 checked_unlock( &b->b_mutex );
960 }
961
962 /* update lload_stats */
963 lload_stats.global_outgoing = tmp_stats.global_outgoing;
964 lload_stats.global_incoming = tmp_stats.global_incoming;
965 for ( i = 0; i < LLOAD_STATS_OPS_LAST; i++ ) {
966 lload_stats.counters[i].lc_ops_completed =
967 tmp_stats.counters[i].lc_ops_completed;
968 lload_stats.counters[i].lc_ops_failed =
969 tmp_stats.counters[i].lc_ops_failed;
970 }
971
972 /* reschedule */
973 checked_lock( &slapd_rq.rq_mutex );
974 ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );
975 checked_unlock( &slapd_rq.rq_mutex );
976 return NULL;
977 }
978
979 static char *lload_subsys_rdn[] = {
980 LLOAD_MONITOR_BALANCER_RDN,
981 LLOAD_MONITOR_INCOMING_RDN,
982 LLOAD_MONITOR_OPERATIONS_RDN,
983 LLOAD_MONITOR_BACKENDS_RDN,
984 NULL
985 };
986
987 static struct monitor_subsys_t balancer_subsys[] = {
988 {
989 LLOAD_MONITOR_BALANCER_NAME,
990 BER_BVNULL,
991 BER_BVC(SLAPD_MONITOR_BACKEND_DN),
992 BER_BVNULL,
993 { BER_BVC("Load Balancer information"),
994 BER_BVNULL },
995 MONITOR_F_PERSISTENT_CH,
996 lload_monitor_balancer_init,
997 lload_monitor_subsystem_destroy, /* destroy */
998 NULL, /* update */
999 NULL, /* create */
1000 NULL /* modify */
1001 },
1002 {
1003 LLOAD_MONITOR_INCOMING_NAME,
1004 BER_BVNULL,
1005 BER_BVC(LLOAD_MONITOR_BALANCER_DN),
1006 BER_BVNULL,
1007 { BER_BVC("Load Balancer incoming connections"),
1008 BER_BVNULL },
1009 MONITOR_F_VOLATILE_CH,
1010 lload_monitor_incoming_conn_init,
1011 lload_monitor_subsystem_destroy, /* destroy */
1012 NULL, /* update */
1013 NULL, /* create */
1014 NULL /* modify */
1015 },
1016 {
1017 LLOAD_MONITOR_OPERATIONS_NAME,
1018 BER_BVNULL,
1019 BER_BVC(LLOAD_MONITOR_BALANCER_DN),
1020 BER_BVNULL,
1021 { BER_BVC("Load Balancer global operation statistics"),
1022 BER_BVNULL },
1023 MONITOR_F_PERSISTENT_CH,
1024 lload_monitor_ops_init,
1025 lload_monitor_subsystem_destroy, /* destroy */
1026 NULL, /* update */
1027 NULL, /* create */
1028 NULL /* modify */
1029 },
1030 {
1031 LLOAD_MONITOR_BACKENDS_NAME,
1032 BER_BVNULL,
1033 BER_BVC(LLOAD_MONITOR_BALANCER_DN),
1034 BER_BVNULL,
1035 { BER_BVC("Load Balancer Backends information"),
1036 BER_BVNULL },
1037 MONITOR_F_PERSISTENT_CH,
1038 lload_monitor_backends_init,
1039 lload_monitor_subsystem_destroy, /* destroy */
1040 NULL, /* update */
1041 NULL, /* create */
1042 NULL /* modify */
1043 },
1044 { NULL }
1045 };
1046
1047 int
lload_monitor_open(void)1048 lload_monitor_open( void )
1049 {
1050 static int lload_monitor_initialized_failure = 1;
1051 static int lload_monitor_initialized = 0;
1052 BackendInfo *mi;
1053 monitor_extra_t *mbe;
1054 monitor_subsys_t *mss;
1055 ConfigArgs c;
1056 char *argv[3], **rdn;
1057 int i, rc;
1058
1059 /* check if monitor is configured and usable */
1060 mi = backend_info( "monitor" );
1061 if ( !mi || !mi->bi_extra ) {
1062 Debug( LDAP_DEBUG_CONFIG, "lload_monitor_open: "
1063 "monitor backend not available, monitoring disabled\n" );
1064 return 0;
1065 }
1066 mbe = mi->bi_extra;
1067
1068 /* don't bother if monitor is not configured */
1069 if ( !mbe->is_configured() ) {
1070 static int warning = 0;
1071
1072 if ( warning++ == 0 ) {
1073 Debug( LDAP_DEBUG_CONFIG, "lload_monitor_open: "
1074 "monitoring disabled; "
1075 "configure monitor database to enable\n" );
1076 }
1077
1078 return 0;
1079 }
1080
1081 if ( lload_monitor_initialized++ ) {
1082 return lload_monitor_initialized_failure;
1083 }
1084
1085 argv[0] = "lload monitor";
1086 c.argv = argv;
1087 c.argc = 3;
1088 c.fname = argv[0];
1089 for ( i = 0; s_oid[i].name; i++ ) {
1090 argv[1] = s_oid[i].name;
1091 argv[2] = s_oid[i].oid;
1092
1093 if ( parse_oidm( &c, 0, NULL ) != 0 ) {
1094 Debug( LDAP_DEBUG_ANY, "lload_monitor_open: "
1095 "unable to add objectIdentifier \"%s=%s\"\n",
1096 s_oid[i].name, s_oid[i].oid );
1097 return 2;
1098 }
1099 }
1100
1101 for ( i = 0; s_at[i].desc != NULL; i++ ) {
1102 rc = register_at( s_at[i].desc, s_at[i].ad, 1 );
1103 if ( rc != LDAP_SUCCESS ) {
1104 Debug( LDAP_DEBUG_ANY, "lload_monitor_open: "
1105 "register_at failed for attributeType (%s)\n",
1106 s_at[i].desc );
1107 return 3;
1108
1109 } else {
1110 (*s_at[i].ad)->ad_type->sat_flags |= SLAP_AT_HIDE;
1111 }
1112 }
1113
1114 for ( i = 0; s_oc[i].desc != NULL; i++ ) {
1115 rc = register_oc( s_oc[i].desc, s_oc[i].oc, 1 );
1116 if ( rc != LDAP_SUCCESS ) {
1117 Debug( LDAP_DEBUG_ANY, "lload_monitor_open: "
1118 "register_oc failed for objectClass (%s)\n",
1119 s_oc[i].desc );
1120 return 4;
1121
1122 } else {
1123 (*s_oc[i].oc)->soc_flags |= SLAP_OC_HIDE;
1124 }
1125 }
1126
1127 for ( i = 0; s_moc[i].name != NULL; i++ ) {
1128 *s_moc[i].oc = oc_find( s_moc[i].name );
1129 if ( !*s_moc[i].oc ) {
1130 Debug( LDAP_DEBUG_ANY, "lload_monitor_open: "
1131 "failed to find objectClass (%s)\n",
1132 s_moc[i].name );
1133 return 5;
1134 }
1135 }
1136
1137 /* register the subsystems - Servers are registered in backends_init */
1138 for ( mss = balancer_subsys, rdn = lload_subsys_rdn; mss->mss_name;
1139 mss++, rdn++ ) {
1140 ber_str2bv( *rdn, 0, 1, &mss->mss_rdn );
1141 if ( mbe->register_subsys_late( mss ) ) {
1142 Debug( LDAP_DEBUG_ANY, "lload_monitor_open: "
1143 "failed to register %s subsystem\n",
1144 mss->mss_name );
1145 return -1;
1146 }
1147 }
1148
1149 checked_lock( &slapd_rq.rq_mutex );
1150 ldap_pvt_runqueue_insert( &slapd_rq, 1, lload_monitor_update_global_stats,
1151 NULL, "lload_monitor_update_global_stats", "lloadd" );
1152 checked_unlock( &slapd_rq.rq_mutex );
1153
1154 return (lload_monitor_initialized_failure = LDAP_SUCCESS);
1155 }
1156