xref: /netbsd-src/external/bsd/openldap/dist/servers/lloadd/monitor.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
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