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 272 lload_monitor_subsystem_destroy( BackendDB *be, monitor_subsys_t *ms ) 273 { 274 return LDAP_SUCCESS; 275 } 276 277 static int 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 300 lload_monitor_balancer_dispose( void **priv ) 301 { 302 return; 303 } 304 305 static int 306 lload_monitor_balancer_free( Entry *e, void **priv ) 307 { 308 return LDAP_SUCCESS; 309 } 310 311 static int 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 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 362 lload_monitor_ops_dispose( void **priv ) 363 { 364 return; 365 } 366 367 static int 368 lload_monitor_ops_free( Entry *e, void **priv ) 369 { 370 return LDAP_SUCCESS; 371 } 372 373 static int 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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