1 /* $NetBSD: monitor.c,v 1.3 2025/09/05 21:16:24 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-2024 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.3 2025/09/05 21:16:24 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 #include "lutil.h" 43 44 #include "ldap_rq.h" 45 #include "lload-config.h" 46 #include "../slapd/back-monitor/back-monitor.h" 47 48 #define LLOAD_MONITOR_BALANCER_NAME "Load Balancer" 49 #define LLOAD_MONITOR_BALANCER_RDN \ 50 SLAPD_MONITOR_AT "=" LLOAD_MONITOR_BALANCER_NAME 51 #define LLOAD_MONITOR_BALANCER_DN \ 52 LLOAD_MONITOR_BALANCER_RDN "," SLAPD_MONITOR_BACKEND_DN 53 54 #define LLOAD_MONITOR_INCOMING_NAME "Incoming Connections" 55 #define LLOAD_MONITOR_INCOMING_RDN \ 56 SLAPD_MONITOR_AT "=" LLOAD_MONITOR_INCOMING_NAME 57 #define LLOAD_MONITOR_INCOMING_DN \ 58 LLOAD_MONITOR_INCOMING_RDN "," LLOAD_MONITOR_BALANCER_DN 59 60 #define LLOAD_MONITOR_OPERATIONS_NAME "Operations" 61 #define LLOAD_MONITOR_OPERATIONS_RDN \ 62 SLAPD_MONITOR_AT "=" LLOAD_MONITOR_OPERATIONS_NAME 63 #define LLOAD_MONITOR_OPERATIONS_DN \ 64 LLOAD_MONITOR_OPERATIONS_RDN "," LLOAD_MONITOR_BALANCER_DN 65 66 #define LLOAD_MONITOR_TIERS_NAME "Backend Tiers" 67 #define LLOAD_MONITOR_TIERS_RDN SLAPD_MONITOR_AT "=" LLOAD_MONITOR_TIERS_NAME 68 #define LLOAD_MONITOR_TIERS_DN \ 69 LLOAD_MONITOR_TIERS_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_olmConnectionState; 96 static AttributeDescription *ad_olmPendingOps; 97 static AttributeDescription *ad_olmPendingConnections; 98 static AttributeDescription *ad_olmActiveConnections; 99 static AttributeDescription *ad_olmIncomingConnections; 100 static AttributeDescription *ad_olmOutgoingConnections; 101 102 monitor_subsys_t *lload_monitor_client_subsys; 103 104 static struct { 105 char *name; 106 char *oid; 107 } s_oid[] = { 108 { "olmBalancerAttributes", "olmModuleAttributes:1" }, 109 { "olmBalancerObjectClasses", "olmModuleObjectClasses:1" }, 110 111 { NULL } 112 }; 113 114 static struct { 115 char *desc; 116 AttributeDescription **ad; 117 } s_at[] = { 118 { "( olmBalancerAttributes:1 " 119 "NAME ( 'olmServerURI' ) " 120 "DESC 'URI of a backend server' " 121 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 " 122 "EQUALITY caseIgnoreMatch " 123 "NO-USER-MODIFICATION " 124 "USAGE dSAOperation )", 125 &ad_olmServerURI }, 126 { "( olmBalancerAttributes:2 " 127 "NAME ( 'olmReceivedOps' ) " 128 "DESC 'monitor received operations' " 129 "SUP monitorCounter " 130 "NO-USER-MODIFICATION " 131 "USAGE dSAOperation )", 132 &ad_olmReceivedOps }, 133 { "( olmBalancerAttributes:3 " 134 "NAME ( 'olmForwardedOps' ) " 135 "DESC 'monitor forwarded operations' " 136 "SUP monitorCounter " 137 "NO-USER-MODIFICATION " 138 "USAGE dSAOperation )", 139 &ad_olmForwardedOps }, 140 { "( olmBalancerAttributes:4 " 141 "NAME ( 'olmRejectedOps' ) " 142 "DESC 'monitor rejected operations' " 143 "SUP monitorCounter " 144 "NO-USER-MODIFICATION " 145 "USAGE dSAOperation )", 146 &ad_olmRejectedOps }, 147 { "( olmBalancerAttributes:5 " 148 "NAME ( 'olmCompletedOps' ) " 149 "DESC 'monitor completed operations' " 150 "SUP monitorCounter " 151 "NO-USER-MODIFICATION " 152 "USAGE dSAOperation )", 153 &ad_olmCompletedOps }, 154 { "( olmBalancerAttributes:6 " 155 "NAME ( 'olmFailedOps' ) " 156 "DESC 'monitor failed operations' " 157 "SUP monitorCounter " 158 "NO-USER-MODIFICATION " 159 "USAGE dSAOperation )", 160 &ad_olmFailedOps }, 161 { "( olmBalancerAttributes:7 " 162 "NAME ( 'olmPendingOps' ) " 163 "DESC 'monitor number of pending operations' " 164 "EQUALITY integerMatch " 165 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 " 166 "NO-USER-MODIFICATION " 167 "USAGE dSAOperation )", 168 &ad_olmPendingOps }, 169 { "( olmBalancerAttributes:8 " 170 "NAME ( 'olmPendingConnections' ) " 171 "DESC 'monitor number of pending connections' " 172 "EQUALITY integerMatch " 173 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 " 174 "NO-USER-MODIFICATION " 175 "USAGE dSAOperation )", 176 &ad_olmPendingConnections }, 177 { "( olmBalancerAttributes:9 " 178 "NAME ( 'olmActiveConnections' ) " 179 "DESC 'monitor number of active connections' " 180 "EQUALITY integerMatch " 181 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 " 182 "NO-USER-MODIFICATION " 183 "USAGE dSAOperation )", 184 &ad_olmActiveConnections }, 185 { "( olmBalancerAttributes:10 " 186 "NAME ( 'olmConnectionType' ) " 187 "DESC 'Connection type' " 188 "EQUALITY caseIgnoreMatch " 189 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 " 190 "NO-USER-MODIFICATION " 191 "USAGE dSAOperation )", 192 &ad_olmConnectionType }, 193 { "( olmBalancerAttributes:11 " 194 "NAME ( 'olmIncomingConnections' ) " 195 "DESC 'monitor number of incoming connections' " 196 "EQUALITY integerMatch " 197 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 " 198 "NO-USER-MODIFICATION " 199 "USAGE dSAOperation )", 200 &ad_olmIncomingConnections }, 201 { "( olmBalancerAttributes:12 " 202 "NAME ( 'olmOutgoingConnections' ) " 203 "DESC 'monitor number of active connections' " 204 "EQUALITY integerMatch " 205 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 " 206 "NO-USER-MODIFICATION " 207 "USAGE dSAOperation )", 208 &ad_olmOutgoingConnections }, 209 { "( olmBalancerAttributes:13 " 210 "NAME ( 'olmConnectionState' ) " 211 "DESC 'Connection state' " 212 "EQUALITY caseIgnoreMatch " 213 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 " 214 "USAGE dSAOperation )", 215 &ad_olmConnectionState }, 216 217 { NULL } 218 }; 219 220 static struct { 221 char *name; 222 ObjectClass **oc; 223 } s_moc[] = { 224 { "monitorContainer", &oc_monitorContainer }, 225 { "monitorCounterObject", &oc_monitorCounterObject }, 226 227 { NULL } 228 }; 229 230 static struct { 231 char *desc; 232 ObjectClass **oc; 233 } s_oc[] = { 234 { "( olmBalancerObjectClasses:1 " 235 "NAME ( 'olmBalancer' ) " 236 "SUP top STRUCTURAL " 237 "MAY ( " 238 "olmIncomingConnections " 239 "$ olmOutgoingConnections " 240 ") )", 241 &oc_olmBalancer }, 242 { "( olmBalancerObjectClasses:2 " 243 "NAME ( 'olmBalancerServer' ) " 244 "SUP top STRUCTURAL " 245 "MAY ( " 246 "olmServerURI " 247 "$ olmActiveConnections " 248 "$ olmPendingConnections " 249 "$ olmPendingOps" 250 "$ olmReceivedOps " 251 "$ olmCompletedOps " 252 "$ olmFailedOps " 253 ") )", 254 &oc_olmBalancerServer }, 255 256 { "( olmBalancerObjectClasses:3 " 257 "NAME ( 'olmBalancerOperation' ) " 258 "SUP top STRUCTURAL " 259 "MAY ( " 260 "olmReceivedOps " 261 "$ olmForwardedOps " 262 "$ olmRejectedOps " 263 "$ olmCompletedOps " 264 "$ olmFailedOps " 265 ") )", 266 &oc_olmBalancerOperation }, 267 { "( olmBalancerObjectClasses:4 " 268 "NAME ( 'olmBalancerConnection' ) " 269 "SUP top STRUCTURAL " 270 "MAY ( " 271 "olmConnectionType " 272 "$ olmConnectionState " 273 "$ olmPendingOps " 274 "$ olmReceivedOps " 275 "$ olmCompletedOps " 276 "$ olmFailedOps " 277 ") )", 278 &oc_olmBalancerConnection }, 279 { NULL } 280 }; 281 282 static int 283 lload_monitor_subsystem_destroy( BackendDB *be, monitor_subsys_t *ms ) 284 { 285 ch_free( ms->mss_dn.bv_val ); 286 ch_free( ms->mss_ndn.bv_val ); 287 return LDAP_SUCCESS; 288 } 289 290 static int 291 lload_monitor_subsystem_free( BackendDB *be, monitor_subsys_t *ms ) 292 { 293 lload_monitor_subsystem_destroy( be, ms ); 294 ch_free( ms ); 295 return LDAP_SUCCESS; 296 } 297 298 static int 299 lload_monitor_backend_destroy( BackendDB *be, monitor_subsys_t *ms ) 300 { 301 LloadBackend *b = ms->mss_private; 302 monitor_extra_t *mbe; 303 int rc = LDAP_SUCCESS; 304 305 ms->mss_destroy = lload_monitor_subsystem_free; 306 307 mbe = (monitor_extra_t *)be->bd_info->bi_extra; 308 if ( b->b_monitor ) { 309 assert( b->b_monitor == ms ); 310 b->b_monitor = NULL; 311 312 rc = mbe->unregister_entry( &ms->mss_ndn ); 313 } 314 315 return rc; 316 } 317 318 static int 319 lload_monitor_tier_destroy( BackendDB *be, monitor_subsys_t *ms ) 320 { 321 LloadTier *tier = ms->mss_private; 322 323 assert( slapd_shutdown || ( tier && tier->t_monitor == ms ) ); 324 325 ms->mss_destroy = lload_monitor_subsystem_free; 326 327 if ( !slapd_shutdown ) { 328 monitor_extra_t *mbe; 329 330 tier->t_monitor = NULL; 331 332 mbe = (monitor_extra_t *)be->bd_info->bi_extra; 333 return mbe->unregister_entry( &ms->mss_ndn ); 334 } 335 336 return ms->mss_destroy( be, ms ); 337 } 338 339 static void 340 lload_monitor_balancer_dispose( void **priv ) 341 { 342 return; 343 } 344 345 static int 346 lload_monitor_balancer_free( Entry *e, void **priv ) 347 { 348 return LDAP_SUCCESS; 349 } 350 351 static int 352 lload_monitor_balancer_update( 353 Operation *op, 354 SlapReply *rs, 355 Entry *e, 356 void *priv ) 357 { 358 Attribute *a; 359 360 a = attr_find( e->e_attrs, ad_olmIncomingConnections ); 361 assert( a != NULL ); 362 363 UI2BV( &a->a_vals[0], lload_stats.global_incoming ); 364 365 a = attr_find( e->e_attrs, ad_olmOutgoingConnections ); 366 assert( a != NULL ); 367 368 UI2BV( &a->a_vals[0], lload_stats.global_outgoing ); 369 return SLAP_CB_CONTINUE; 370 } 371 372 static int 373 lload_monitor_ops_update( Operation *op, SlapReply *rs, Entry *e, void *priv ) 374 { 375 Attribute *a; 376 lload_counters_t *counters = (lload_counters_t *)priv; 377 378 a = attr_find( e->e_attrs, ad_olmReceivedOps ); 379 assert( a != NULL ); 380 UI2BV( &a->a_vals[0], counters->lc_ops_received ); 381 382 a = attr_find( e->e_attrs, ad_olmForwardedOps ); 383 assert( a != NULL ); 384 UI2BV( &a->a_vals[0], counters->lc_ops_forwarded ); 385 386 a = attr_find( e->e_attrs, ad_olmRejectedOps ); 387 assert( a != NULL ); 388 UI2BV( &a->a_vals[0], counters->lc_ops_rejected ); 389 390 a = attr_find( e->e_attrs, ad_olmCompletedOps ); 391 assert( a != NULL ); 392 UI2BV( &a->a_vals[0], counters->lc_ops_completed ); 393 394 a = attr_find( e->e_attrs, ad_olmFailedOps ); 395 assert( a != NULL ); 396 UI2BV( &a->a_vals[0], counters->lc_ops_failed ); 397 398 return SLAP_CB_CONTINUE; 399 } 400 401 static void 402 lload_monitor_ops_dispose( void **priv ) 403 { 404 return; 405 } 406 407 static int 408 lload_monitor_ops_free( Entry *e, void **priv ) 409 { 410 return LDAP_SUCCESS; 411 } 412 413 static int 414 lload_monitor_balancer_init( BackendDB *be, monitor_subsys_t *ms ) 415 { 416 monitor_extra_t *mbe; 417 Entry *e; 418 int rc; 419 monitor_callback_t *cb; 420 struct berval value = BER_BVC("0"); 421 422 assert( be != NULL ); 423 424 mbe = (monitor_extra_t *)be->bd_info->bi_extra; 425 426 dnNormalize( 0, NULL, NULL, &ms->mss_dn, &ms->mss_ndn, NULL ); 427 428 e = mbe->entry_stub( &ms->mss_dn, &ms->mss_ndn, &ms->mss_rdn, 429 oc_olmBalancer, NULL, NULL ); 430 if ( e == NULL ) { 431 Debug( LDAP_DEBUG_ANY, "lload_monitor_balancer_init: " 432 "unable to create entry \"%s,%s\"\n", 433 ms->mss_rdn.bv_val, ms->mss_ndn.bv_val ); 434 return -1; 435 } 436 437 ch_free( ms->mss_ndn.bv_val ); 438 ber_dupbv( &ms->mss_dn, &e->e_name ); 439 ber_dupbv( &ms->mss_ndn, &e->e_nname ); 440 441 cb = ch_calloc( sizeof(monitor_callback_t), 1 ); 442 cb->mc_update = lload_monitor_balancer_update; 443 cb->mc_free = lload_monitor_balancer_free; 444 cb->mc_dispose = lload_monitor_balancer_dispose; 445 cb->mc_private = NULL; 446 447 attr_merge_normalize_one( e, ad_olmIncomingConnections, &value, NULL ); 448 attr_merge_normalize_one( e, ad_olmOutgoingConnections, &value, NULL ); 449 450 rc = mbe->register_entry( e, cb, ms, 0 ); 451 if ( rc != LDAP_SUCCESS ) { 452 Debug( LDAP_DEBUG_ANY, "lload_monitor_balancer_init: " 453 "unable to register entry \"%s\" for monitoring\n", 454 e->e_name.bv_val ); 455 goto done; 456 } 457 458 done: 459 entry_free( e ); 460 461 return rc; 462 } 463 464 static int 465 lload_monitor_ops_init( BackendDB *be, monitor_subsys_t *ms ) 466 { 467 monitor_extra_t *mbe; 468 Entry *e, *parent; 469 int rc; 470 int i; 471 struct berval value = BER_BVC("0"); 472 473 assert( be != NULL ); 474 475 mbe = (monitor_extra_t *)be->bd_info->bi_extra; 476 477 dnNormalize( 0, NULL, NULL, &ms->mss_dn, &ms->mss_ndn, NULL ); 478 ms->mss_destroy = lload_monitor_subsystem_destroy; 479 480 parent = mbe->entry_stub( &ms->mss_dn, &ms->mss_ndn, &ms->mss_rdn, 481 oc_monitorContainer, NULL, NULL ); 482 if ( parent == NULL ) { 483 Debug( LDAP_DEBUG_ANY, "lload_monitor_ops_init: " 484 "unable to create entry \"%s,%s\"\n", 485 ms->mss_rdn.bv_val, ms->mss_ndn.bv_val ); 486 return -1; 487 } 488 ch_free( ms->mss_ndn.bv_val ); 489 ber_dupbv( &ms->mss_dn, &parent->e_name ); 490 ber_dupbv( &ms->mss_ndn, &parent->e_nname ); 491 492 rc = mbe->register_entry( parent, NULL, ms, MONITOR_F_PERSISTENT_CH ); 493 if ( rc != LDAP_SUCCESS ) { 494 Debug( LDAP_DEBUG_ANY, "lload_monitor_ops_init: " 495 "unable to register entry \"%s\" for monitoring\n", 496 parent->e_name.bv_val ); 497 goto done; 498 } 499 500 for ( i = 0; lload_monitor_op[i].rdn.bv_val != NULL; i++ ) { 501 monitor_callback_t *cb; 502 e = mbe->entry_stub( &parent->e_name, &parent->e_nname, 503 &lload_monitor_op[i].rdn, oc_olmBalancerOperation, NULL, NULL ); 504 if ( e == NULL ) { 505 Debug( LDAP_DEBUG_ANY, "lload_monitor_ops_init: " 506 "unable to create entry \"%s,%s\"\n", 507 lload_monitor_op[i].rdn.bv_val, parent->e_nname.bv_val ); 508 return -1; 509 } 510 511 /* attr_merge_normalize_one( e, ad_olmDbOperations, &value, NULL ); */ 512 513 /* 514 * We cannot share a single callback between entries. 515 * 516 * monitor_cache_destroy() tries to free all callbacks and it's called 517 * before mss_destroy() so we have no chance of handling it ourselves 518 */ 519 cb = ch_calloc( sizeof(monitor_callback_t), 1 ); 520 cb->mc_update = lload_monitor_ops_update; 521 cb->mc_free = lload_monitor_ops_free; 522 cb->mc_dispose = lload_monitor_ops_dispose; 523 cb->mc_private = &lload_stats.counters[i]; 524 525 attr_merge_normalize_one( e, ad_olmReceivedOps, &value, NULL ); 526 attr_merge_normalize_one( e, ad_olmForwardedOps, &value, NULL ); 527 attr_merge_normalize_one( e, ad_olmRejectedOps, &value, NULL ); 528 attr_merge_normalize_one( e, ad_olmCompletedOps, &value, NULL ); 529 attr_merge_normalize_one( e, ad_olmFailedOps, &value, NULL ); 530 531 rc = mbe->register_entry( e, cb, ms, 0 ); 532 533 entry_free( e ); 534 535 if ( rc != LDAP_SUCCESS ) { 536 Debug( LDAP_DEBUG_ANY, "lload_monitor_ops_init: " 537 "unable to register entry \"%s\" for monitoring\n", 538 e->e_name.bv_val ); 539 ch_free( cb ); 540 break; 541 } 542 } 543 544 done: 545 entry_free( parent ); 546 return rc; 547 } 548 549 static void * 550 lload_monitor_release_conn( void *ctx, void *arg ) 551 { 552 LloadConnection *c = arg; 553 epoch_t epoch = epoch_join(); 554 555 RELEASE_REF( c, c_refcnt, c->c_destroy ); 556 epoch_leave( epoch ); 557 return NULL; 558 } 559 560 static int 561 lload_monitor_conn_modify( Operation *op, SlapReply *rs, Entry *e, void *priv ) 562 { 563 Modifications *m; 564 LloadConnection *c = priv; 565 int rc = SLAP_CB_CONTINUE; 566 epoch_t epoch; 567 568 if ( !acquire_ref( &c->c_refcnt ) ) { 569 /* Shutting down, pretend it's already happened */ 570 return LDAP_NO_SUCH_OBJECT; 571 } 572 epoch = epoch_join(); 573 574 for ( m = op->orm_modlist; m; m = m->sml_next ) { 575 struct berval closing = BER_BVC("closing"); 576 int gentle = 1; 577 578 if ( m->sml_flags & SLAP_MOD_INTERNAL ) continue; 579 580 if ( m->sml_desc != ad_olmConnectionState || 581 m->sml_op != LDAP_MOD_REPLACE || m->sml_numvals != 1 || 582 ber_bvcmp( &m->sml_nvalues[0], &closing ) ) { 583 rc = LDAP_CONSTRAINT_VIOLATION; 584 goto done; 585 } 586 587 if ( lload_connection_close( c, &gentle ) ) { 588 rc = LDAP_OTHER; 589 goto done; 590 } 591 } 592 593 done: 594 epoch_leave( epoch ); 595 /* 596 * The connection might have been ready to disappear in epoch_leave(), that 597 * involves deleting this monitor entry. Make sure that doesn't happen 598 * punting the decref into a separate task that's not holding any locks and 599 * finishes after we did. 600 * 601 * FIXME: It would probably be cleaner to defer the entry deletion into a 602 * separate task instead but the entry holds a pointer to this connection 603 * that might not be safe to manipulate. 604 */ 605 ldap_pvt_thread_pool_submit( 606 &connection_pool, lload_monitor_release_conn, c ); 607 return rc; 608 } 609 610 /* 611 * Monitor cache is locked, the connection cannot be unlinked and freed under us. 612 * That also means we need to unlock and finish as soon as possible. 613 */ 614 static int 615 lload_monitor_conn_update( Operation *op, SlapReply *rs, Entry *e, void *priv ) 616 { 617 Attribute *a; 618 LloadConnection *c = priv; 619 struct berval bv_type, bv_state; 620 ldap_pvt_mp_t active, pending, received, completed, failed; 621 622 CONNECTION_LOCK(c); 623 624 pending = (ldap_pvt_mp_t)c->c_n_ops_executing; 625 received = c->c_counters.lc_ops_received; 626 completed = c->c_counters.lc_ops_completed; 627 failed = c->c_counters.lc_ops_failed; 628 629 switch ( c->c_type ) { 630 case LLOAD_C_OPEN: { 631 struct berval bv = BER_BVC("regular"); 632 bv_type = bv; 633 } break; 634 case LLOAD_C_PREPARING: { 635 struct berval bv = BER_BVC("preparing"); 636 bv_type = bv; 637 } break; 638 case LLOAD_C_BIND: { 639 struct berval bv = BER_BVC("bind"); 640 bv_type = bv; 641 } break; 642 case LLOAD_C_PRIVILEGED: { 643 struct berval bv = BER_BVC("privileged"); 644 bv_type = bv; 645 } break; 646 default: { 647 struct berval bv = BER_BVC("unknown"); 648 bv_type = bv; 649 } break; 650 } 651 652 switch ( c->c_state ) { 653 case LLOAD_C_INVALID: { 654 /* *_destroy removes the entry from list before setting c_state to 655 * INVALID */ 656 assert(0); 657 } break; 658 case LLOAD_C_READY: { 659 struct berval bv = BER_BVC("ready"); 660 bv_state = bv; 661 } break; 662 case LLOAD_C_CLOSING: { 663 struct berval bv = BER_BVC("closing"); 664 bv_state = bv; 665 } break; 666 case LLOAD_C_ACTIVE: { 667 struct berval bv = BER_BVC("active"); 668 bv_state = bv; 669 } break; 670 case LLOAD_C_BINDING: { 671 struct berval bv = BER_BVC("binding"); 672 bv_state = bv; 673 } break; 674 case LLOAD_C_DYING: { 675 /* I guess we got it before it was unlinked? */ 676 struct berval bv = BER_BVC("dying"); 677 bv_state = bv; 678 } break; 679 default: { 680 struct berval bv = BER_BVC("unknown"); 681 bv_state = bv; 682 } break; 683 } 684 685 CONNECTION_UNLOCK(c); 686 687 a = attr_find( e->e_attrs, ad_olmConnectionType ); 688 assert( a != NULL ); 689 if ( !(a->a_flags & SLAP_ATTR_DONT_FREE_DATA) ) { 690 ber_memfree( a->a_vals[0].bv_val ); 691 a->a_flags |= SLAP_ATTR_DONT_FREE_DATA; 692 } 693 a->a_vals[0] = bv_type; 694 695 a = attr_find( e->e_attrs, ad_olmConnectionState ); 696 assert( a != NULL ); 697 if ( !(a->a_flags & SLAP_ATTR_DONT_FREE_DATA) ) { 698 ber_memfree( a->a_vals[0].bv_val ); 699 a->a_flags |= SLAP_ATTR_DONT_FREE_DATA; 700 } 701 a->a_vals[0] = bv_state; 702 703 a = attr_find( e->e_attrs, ad_olmPendingOps ); 704 assert( a != NULL ); 705 UI2BV( &a->a_vals[0], pending ); 706 707 a = attr_find( e->e_attrs, ad_olmReceivedOps ); 708 assert( a != NULL ); 709 UI2BV( &a->a_vals[0], received ); 710 711 a = attr_find( e->e_attrs, ad_olmCompletedOps ); 712 assert( a != NULL ); 713 UI2BV( &a->a_vals[0], completed ); 714 715 a = attr_find( e->e_attrs, ad_olmFailedOps ); 716 assert( a != NULL ); 717 UI2BV( &a->a_vals[0], failed ); 718 719 return SLAP_CB_CONTINUE; 720 } 721 722 int 723 lload_monitor_conn_unlink( LloadConnection *c ) 724 { 725 BackendInfo *mi = backend_info( "monitor" ); 726 monitor_extra_t *mbe = mi->bi_extra; 727 728 assert( mbe && mbe->is_configured() ); 729 730 CONNECTION_ASSERT_LOCKED(c); 731 assert( !BER_BVISNULL( &c->c_monitor_dn ) ); 732 733 /* 734 * Avoid a lock inversion with threads holding monitor cache locks in turn 735 * waiting on CONNECTION_LOCK(c) 736 */ 737 CONNECTION_UNLOCK(c); 738 mbe->unregister_entry( &c->c_monitor_dn ); 739 CONNECTION_LOCK(c); 740 741 ber_memfree( c->c_monitor_dn.bv_val ); 742 BER_BVZERO( &c->c_monitor_dn ); 743 744 return 0; 745 } 746 747 int 748 lload_monitor_conn_entry_create( LloadConnection *c, monitor_subsys_t *ms ) 749 { 750 char buf[SLAP_TEXT_BUFLEN]; 751 char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE]; 752 struct tm tm; 753 struct berval bv_rdn, bv_timestamp, zero = BER_BVC("0"), 754 value = BER_BVC("unknown"); 755 monitor_entry_t *mp; 756 monitor_callback_t *cb; 757 Entry *e; 758 Attribute *a; 759 BackendInfo *mi = backend_info( "monitor" ); 760 monitor_extra_t *mbe = mi->bi_extra; 761 762 assert( mbe && mbe->is_configured() ); 763 764 CONNECTION_ASSERT_LOCKED(c); 765 assert( BER_BVISNULL( &c->c_monitor_dn ) ); 766 767 bv_rdn.bv_val = buf; 768 bv_rdn.bv_len = snprintf( 769 bv_rdn.bv_val, SLAP_TEXT_BUFLEN, "cn=Connection %lu", c->c_connid ); 770 771 ldap_pvt_gmtime( &c->c_activitytime, &tm ); 772 bv_timestamp.bv_len = lutil_gentime( timebuf, sizeof(timebuf), &tm ); 773 bv_timestamp.bv_val = timebuf; 774 775 e = mbe->entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv_rdn, 776 oc_olmBalancerConnection, &bv_timestamp, &bv_timestamp ); 777 778 cb = ch_calloc( sizeof(monitor_callback_t), 1 ); 779 cb->mc_update = lload_monitor_conn_update; 780 cb->mc_modify = lload_monitor_conn_modify; 781 cb->mc_private = c; 782 783 attr_merge_one( e, ad_olmConnectionType, &value, NULL ); 784 attr_merge_one( e, ad_olmConnectionState, &value, NULL ); 785 attr_merge_one( e, ad_olmPendingOps, &zero, NULL ); 786 attr_merge_one( e, ad_olmReceivedOps, &zero, NULL ); 787 attr_merge_one( e, ad_olmCompletedOps, &zero, NULL ); 788 attr_merge_one( e, ad_olmFailedOps, &zero, NULL ); 789 790 if ( mbe->register_entry( e, cb, NULL, 0 ) ) { 791 Debug( LDAP_DEBUG_ANY, "lload_monitor_conn_entry_create: " 792 "failed to register monitor entry for connid=%lu\n", 793 c->c_connid ); 794 795 ch_free( cb ); 796 entry_free( e ); 797 return -1; 798 } 799 800 ber_dupbv( &c->c_monitor_dn, &e->e_nname ); 801 entry_free( e ); 802 803 return 0; 804 } 805 806 static int 807 lload_monitor_incoming_conn_init( BackendDB *be, monitor_subsys_t *ms ) 808 { 809 monitor_extra_t *mbe; 810 Entry *e; 811 int rc; 812 813 assert( be != NULL ); 814 mbe = (monitor_extra_t *)be->bd_info->bi_extra; 815 816 ms->mss_destroy = lload_monitor_subsystem_destroy; 817 818 dnNormalize( 0, NULL, NULL, &ms->mss_dn, &ms->mss_ndn, NULL ); 819 820 e = mbe->entry_stub( &ms->mss_dn, &ms->mss_ndn, &ms->mss_rdn, 821 oc_monitorContainer, NULL, NULL ); 822 if ( e == NULL ) { 823 Debug( LDAP_DEBUG_ANY, "lload_monitor_incoming_conn_init: " 824 "unable to create entry \"%s,%s\"\n", 825 ms->mss_rdn.bv_val, ms->mss_ndn.bv_val ); 826 return -1; 827 } 828 ch_free( ms->mss_ndn.bv_val ); 829 ber_dupbv( &ms->mss_dn, &e->e_name ); 830 ber_dupbv( &ms->mss_ndn, &e->e_nname ); 831 832 rc = mbe->register_entry( e, NULL, ms, 0 ); 833 834 if ( rc != LDAP_SUCCESS ) { 835 Debug( LDAP_DEBUG_ANY, "lload_monitor_incoming_conn_init: " 836 "unable to register entry \"%s\" for monitoring\n", 837 e->e_name.bv_val ); 838 goto done; 839 } 840 841 lload_monitor_client_subsys = ms; 842 843 done: 844 entry_free( e ); 845 846 return rc; 847 } 848 849 static int 850 lload_monitor_server_update( 851 Operation *op, 852 SlapReply *rs, 853 Entry *e, 854 void *priv ) 855 { 856 Attribute *a; 857 LloadBackend *b = priv; 858 LloadConnection *c; 859 LloadPendingConnection *pc; 860 ldap_pvt_mp_t active = 0, pending = 0, received = 0, completed = 0, 861 failed = 0; 862 int i; 863 864 checked_lock( &b->b_mutex ); 865 active = b->b_active + b->b_bindavail; 866 867 LDAP_CIRCLEQ_FOREACH ( c, &b->b_preparing, c_next ) { 868 pending++; 869 } 870 871 LDAP_LIST_FOREACH( pc, &b->b_connecting, next ) { 872 pending++; 873 } 874 875 for ( i = 0; i < LLOAD_STATS_OPS_LAST; i++ ) { 876 received += b->b_counters[i].lc_ops_received; 877 completed += b->b_counters[i].lc_ops_completed; 878 failed += b->b_counters[i].lc_ops_failed; 879 } 880 881 a = attr_find( e->e_attrs, ad_olmPendingOps ); 882 assert( a != NULL ); 883 UI2BV( &a->a_vals[0], (long long unsigned int)b->b_n_ops_executing ); 884 885 checked_unlock( &b->b_mutex ); 886 887 /* Right now, there is no way to retrieve the entry from monitor's 888 * cache to replace URI at the moment it is modified */ 889 a = attr_find( e->e_attrs, ad_olmServerURI ); 890 assert( a != NULL ); 891 ber_bvreplace( &a->a_vals[0], &b->b_uri ); 892 893 a = attr_find( e->e_attrs, ad_olmActiveConnections ); 894 assert( a != NULL ); 895 UI2BV( &a->a_vals[0], active ); 896 897 a = attr_find( e->e_attrs, ad_olmPendingConnections ); 898 assert( a != NULL ); 899 UI2BV( &a->a_vals[0], pending ); 900 901 a = attr_find( e->e_attrs, ad_olmReceivedOps ); 902 assert( a != NULL ); 903 UI2BV( &a->a_vals[0], received ); 904 905 a = attr_find( e->e_attrs, ad_olmCompletedOps ); 906 assert( a != NULL ); 907 UI2BV( &a->a_vals[0], completed ); 908 909 a = attr_find( e->e_attrs, ad_olmFailedOps ); 910 assert( a != NULL ); 911 UI2BV( &a->a_vals[0], failed ); 912 913 return SLAP_CB_CONTINUE; 914 } 915 916 static int 917 lload_monitor_backend_open( BackendDB *be, monitor_subsys_t *ms ) 918 { 919 Entry *e; 920 struct berval value = BER_BVC("0"); 921 monitor_extra_t *mbe; 922 monitor_callback_t *cb; 923 LloadBackend *b = ms->mss_private; 924 LloadTier *tier = b->b_tier; 925 int rc; 926 927 assert( be != NULL ); 928 mbe = (monitor_extra_t *)be->bd_info->bi_extra; 929 930 e = mbe->entry_stub( &tier->t_monitor->mss_dn, &tier->t_monitor->mss_ndn, 931 &ms->mss_rdn, oc_olmBalancerServer, NULL, NULL ); 932 if ( e == NULL ) { 933 Debug( LDAP_DEBUG_ANY, "lload_monitor_backend_open: " 934 "unable to create entry \"%s,%s\"\n", 935 ms->mss_rdn.bv_val, tier->t_monitor->mss_dn.bv_val ); 936 return -1; 937 } 938 939 ber_dupbv( &ms->mss_dn, &e->e_name ); 940 ber_dupbv( &ms->mss_ndn, &e->e_nname ); 941 942 cb = ch_calloc( sizeof(monitor_callback_t), 1 ); 943 cb->mc_update = lload_monitor_server_update; 944 cb->mc_free = NULL; 945 cb->mc_dispose = NULL; 946 cb->mc_private = b; 947 948 attr_merge_normalize_one( e, ad_olmServerURI, &b->b_uri, NULL ); 949 attr_merge_normalize_one( e, ad_olmActiveConnections, &value, NULL ); 950 attr_merge_normalize_one( e, ad_olmPendingConnections, &value, NULL ); 951 attr_merge_normalize_one( e, ad_olmPendingOps, &value, NULL ); 952 attr_merge_normalize_one( e, ad_olmReceivedOps, &value, NULL ); 953 attr_merge_normalize_one( e, ad_olmCompletedOps, &value, NULL ); 954 attr_merge_normalize_one( e, ad_olmFailedOps, &value, NULL ); 955 956 rc = mbe->register_entry( e, cb, ms, 0 ); 957 958 if ( rc != LDAP_SUCCESS ) { 959 Debug( LDAP_DEBUG_ANY, "lload_monitor_backend_open: " 960 "unable to register entry \"%s\" for monitoring\n", 961 e->e_name.bv_val ); 962 goto done; 963 } 964 965 ms->mss_destroy = lload_monitor_backend_destroy; 966 967 done: 968 entry_free( e ); 969 return rc; 970 } 971 972 int 973 lload_monitor_backend_init( 974 BackendInfo *bi, 975 monitor_subsys_t *ms, 976 LloadBackend *b ) 977 { 978 monitor_extra_t *mbe = bi->bi_extra; 979 monitor_subsys_t *bk_mss; 980 981 /* FIXME: With back-monitor as it works now, there is no way to know when 982 * this can be safely freed so we leak it on shutdown */ 983 bk_mss = ch_calloc( 1, sizeof(monitor_subsys_t) ); 984 bk_mss->mss_rdn.bv_len = sizeof("cn=") + b->b_name.bv_len; 985 bk_mss->mss_rdn.bv_val = ch_malloc( bk_mss->mss_rdn.bv_len ); 986 bk_mss->mss_rdn.bv_len = snprintf( bk_mss->mss_rdn.bv_val, 987 bk_mss->mss_rdn.bv_len, "cn=%s", b->b_name.bv_val ); 988 989 bk_mss->mss_name = b->b_name.bv_val; 990 bk_mss->mss_flags = MONITOR_F_NONE; 991 bk_mss->mss_open = lload_monitor_backend_open; 992 bk_mss->mss_destroy = lload_monitor_subsystem_destroy; 993 bk_mss->mss_update = NULL; 994 bk_mss->mss_private = b; 995 996 if ( mbe->register_subsys_late( bk_mss ) ) { 997 Debug( LDAP_DEBUG_ANY, "lload_monitor_backend_init: " 998 "failed to register backend %s\n", 999 bk_mss->mss_name ); 1000 ch_free( bk_mss ); 1001 return -1; 1002 } 1003 1004 b->b_monitor = bk_mss; 1005 return LDAP_SUCCESS; 1006 } 1007 1008 static int 1009 lload_monitor_tier_open( BackendDB *be, monitor_subsys_t *ms ) 1010 { 1011 Entry *e; 1012 monitor_extra_t *mbe; 1013 LloadTier *tier = ms->mss_private; 1014 int rc; 1015 1016 assert( be != NULL ); 1017 mbe = (monitor_extra_t *)be->bd_info->bi_extra; 1018 1019 dnNormalize( 0, NULL, NULL, &ms->mss_dn, &ms->mss_ndn, NULL ); 1020 e = mbe->entry_stub( &ms->mss_dn, &ms->mss_ndn, &ms->mss_rdn, 1021 oc_monitorContainer, NULL, NULL ); 1022 if ( e == NULL ) { 1023 Debug( LDAP_DEBUG_ANY, "lload_monitor_tier_open: " 1024 "unable to create entry \"%s,%s\"\n", 1025 ms->mss_rdn.bv_val, ms->mss_ndn.bv_val ); 1026 return -1; 1027 } 1028 1029 ch_free( ms->mss_ndn.bv_val ); 1030 ber_dupbv( &ms->mss_dn, &e->e_name ); 1031 ber_dupbv( &ms->mss_ndn, &e->e_nname ); 1032 1033 rc = mbe->register_entry( e, NULL, ms, MONITOR_F_PERSISTENT_CH ); 1034 1035 if ( rc != LDAP_SUCCESS ) { 1036 Debug( LDAP_DEBUG_ANY, "lload_monitor_tier_open: " 1037 "unable to register entry \"%s\" for monitoring\n", 1038 e->e_name.bv_val ); 1039 goto done; 1040 } 1041 1042 tier->t_monitor = ms; 1043 ms->mss_destroy = lload_monitor_tier_destroy; 1044 1045 done: 1046 entry_free( e ); 1047 return rc; 1048 } 1049 1050 int 1051 lload_monitor_tier_init( BackendInfo *bi, LloadTier *tier ) 1052 { 1053 monitor_extra_t *mbe; 1054 monitor_subsys_t *mss; 1055 LloadBackend *b; 1056 1057 mbe = (monitor_extra_t *)bi->bi_extra; 1058 1059 mss = ch_calloc( 1, sizeof(monitor_subsys_t) ); 1060 mss->mss_rdn.bv_len = sizeof("cn=") + tier->t_name.bv_len; 1061 mss->mss_rdn.bv_val = ch_malloc( mss->mss_rdn.bv_len ); 1062 mss->mss_rdn.bv_len = snprintf( mss->mss_rdn.bv_val, mss->mss_rdn.bv_len, 1063 "cn=%s", tier->t_name.bv_val ); 1064 1065 ber_str2bv( LLOAD_MONITOR_TIERS_DN, 0, 0, &mss->mss_dn ); 1066 mss->mss_name = tier->t_name.bv_val; 1067 mss->mss_open = lload_monitor_tier_open; 1068 mss->mss_destroy = lload_monitor_subsystem_destroy; 1069 mss->mss_update = NULL; 1070 mss->mss_private = tier; 1071 1072 if ( mbe->register_subsys_late( mss ) ) { 1073 Debug( LDAP_DEBUG_ANY, "lload_monitor_tier_init: " 1074 "failed to register backend %s\n", 1075 mss->mss_name ); 1076 return -1; 1077 } 1078 1079 LDAP_CIRCLEQ_FOREACH ( b, &tier->t_backends, b_next ) { 1080 if ( lload_monitor_backend_init( bi, mss, b ) ) { 1081 return -1; 1082 } 1083 } 1084 1085 return LDAP_SUCCESS; 1086 } 1087 1088 int 1089 lload_monitor_tiers_init( BackendDB *be, monitor_subsys_t *ms ) 1090 { 1091 monitor_extra_t *mbe; 1092 LloadTier *tier; 1093 Entry *e; 1094 int rc; 1095 1096 assert( be != NULL ); 1097 mbe = (monitor_extra_t *)be->bd_info->bi_extra; 1098 1099 dnNormalize( 0, NULL, NULL, &ms->mss_dn, &ms->mss_ndn, NULL ); 1100 1101 e = mbe->entry_stub( &ms->mss_dn, &ms->mss_ndn, &ms->mss_rdn, 1102 oc_monitorContainer, NULL, NULL ); 1103 if ( e == NULL ) { 1104 Debug( LDAP_DEBUG_ANY, "lload_monitor_tiers_init: " 1105 "unable to create entry \"%s,%s\"\n", 1106 ms->mss_rdn.bv_val, ms->mss_ndn.bv_val ); 1107 return -1; 1108 } 1109 ch_free( ms->mss_ndn.bv_val ); 1110 ber_dupbv( &ms->mss_dn, &e->e_name ); 1111 ber_dupbv( &ms->mss_ndn, &e->e_nname ); 1112 1113 rc = mbe->register_entry( e, NULL, ms, MONITOR_F_PERSISTENT_CH ); 1114 1115 if ( rc != LDAP_SUCCESS ) { 1116 Debug( LDAP_DEBUG_ANY, "lload_monitor_tiers_init: " 1117 "unable to register entry \"%s\" for monitoring\n", 1118 e->e_name.bv_val ); 1119 goto done; 1120 } 1121 1122 LDAP_STAILQ_FOREACH ( tier, &tiers, t_next ) { 1123 if ( (rc = lload_monitor_tier_init( be->bd_info, tier )) ) { 1124 break; 1125 } 1126 } 1127 done: 1128 entry_free( e ); 1129 1130 return rc; 1131 } 1132 1133 static int 1134 lload_monitor_incoming_count( LloadConnection *conn, void *argv ) 1135 { 1136 lload_global_stats_t *tmp_stats = argv; 1137 tmp_stats->global_incoming++; 1138 return 0; 1139 } 1140 1141 /* 1142 * Update all global statistics other than rejected and received, 1143 * which are updated in real time 1144 */ 1145 void * 1146 lload_monitor_update_global_stats( void *ctx, void *arg ) 1147 { 1148 struct re_s *rtask = arg; 1149 lload_global_stats_t tmp_stats = {}; 1150 LloadTier *tier; 1151 int i; 1152 1153 Debug( LDAP_DEBUG_TRACE, "lload_monitor_update_global_stats: " 1154 "updating stats\n" ); 1155 1156 /* count incoming connections */ 1157 checked_lock( &clients_mutex ); 1158 connections_walk( &clients_mutex, &clients, lload_monitor_incoming_count, 1159 &tmp_stats ); 1160 checked_unlock( &clients_mutex ); 1161 1162 LDAP_STAILQ_FOREACH ( tier, &tiers, t_next ) { 1163 LloadBackend *b; 1164 1165 LDAP_CIRCLEQ_FOREACH ( b, &tier->t_backends, b_next ) { 1166 checked_lock( &b->b_mutex ); 1167 tmp_stats.global_outgoing += b->b_active + b->b_bindavail; 1168 1169 /* merge completed and failed stats */ 1170 for ( i = 0; i < LLOAD_STATS_OPS_LAST; i++ ) { 1171 tmp_stats.counters[i].lc_ops_completed += 1172 b->b_counters[i].lc_ops_completed; 1173 tmp_stats.counters[i].lc_ops_failed += 1174 b->b_counters[i].lc_ops_failed; 1175 } 1176 checked_unlock( &b->b_mutex ); 1177 } 1178 } 1179 1180 /* update lload_stats */ 1181 lload_stats.global_outgoing = tmp_stats.global_outgoing; 1182 lload_stats.global_incoming = tmp_stats.global_incoming; 1183 for ( i = 0; i < LLOAD_STATS_OPS_LAST; i++ ) { 1184 lload_stats.counters[i].lc_ops_completed = 1185 tmp_stats.counters[i].lc_ops_completed; 1186 lload_stats.counters[i].lc_ops_failed = 1187 tmp_stats.counters[i].lc_ops_failed; 1188 } 1189 1190 /* reschedule */ 1191 checked_lock( &slapd_rq.rq_mutex ); 1192 ldap_pvt_runqueue_stoptask( &slapd_rq, rtask ); 1193 checked_unlock( &slapd_rq.rq_mutex ); 1194 return NULL; 1195 } 1196 1197 static char *lload_subsys_rdn[] = { 1198 LLOAD_MONITOR_BALANCER_RDN, 1199 LLOAD_MONITOR_INCOMING_RDN, 1200 LLOAD_MONITOR_OPERATIONS_RDN, 1201 LLOAD_MONITOR_TIERS_RDN, 1202 NULL 1203 }; 1204 1205 static struct monitor_subsys_t balancer_subsys[] = { 1206 { 1207 LLOAD_MONITOR_BALANCER_NAME, 1208 BER_BVNULL, 1209 BER_BVC(SLAPD_MONITOR_BACKEND_DN), 1210 BER_BVNULL, 1211 { BER_BVC("Load Balancer information"), 1212 BER_BVNULL }, 1213 MONITOR_F_PERSISTENT_CH, 1214 lload_monitor_balancer_init, 1215 lload_monitor_subsystem_destroy, /* destroy */ 1216 NULL, /* update */ 1217 NULL, /* create */ 1218 NULL /* modify */ 1219 }, 1220 { 1221 LLOAD_MONITOR_INCOMING_NAME, 1222 BER_BVNULL, 1223 BER_BVC(LLOAD_MONITOR_BALANCER_DN), 1224 BER_BVNULL, 1225 { BER_BVC("Load Balancer incoming connections"), 1226 BER_BVNULL }, 1227 MONITOR_F_NONE, 1228 lload_monitor_incoming_conn_init, 1229 lload_monitor_subsystem_destroy, /* destroy */ 1230 NULL, /* update */ 1231 NULL, /* create */ 1232 NULL /* modify */ 1233 }, 1234 { 1235 LLOAD_MONITOR_OPERATIONS_NAME, 1236 BER_BVNULL, 1237 BER_BVC(LLOAD_MONITOR_BALANCER_DN), 1238 BER_BVNULL, 1239 { BER_BVC("Load Balancer global operation statistics"), 1240 BER_BVNULL }, 1241 MONITOR_F_PERSISTENT_CH, 1242 lload_monitor_ops_init, 1243 lload_monitor_subsystem_destroy, /* destroy */ 1244 NULL, /* update */ 1245 NULL, /* create */ 1246 NULL /* modify */ 1247 }, 1248 { 1249 LLOAD_MONITOR_TIERS_NAME, 1250 BER_BVNULL, 1251 BER_BVC(LLOAD_MONITOR_BALANCER_DN), 1252 BER_BVNULL, 1253 { BER_BVC("Load Balancer Backends information"), 1254 BER_BVNULL }, 1255 MONITOR_F_PERSISTENT_CH, 1256 lload_monitor_tiers_init, 1257 lload_monitor_subsystem_destroy, /* destroy */ 1258 NULL, /* update */ 1259 NULL, /* create */ 1260 NULL /* modify */ 1261 }, 1262 { NULL } 1263 }; 1264 1265 int 1266 lload_monitor_open( void ) 1267 { 1268 static int lload_monitor_initialized_failure = 1; 1269 static int lload_monitor_initialized = 0; 1270 BackendInfo *mi; 1271 monitor_extra_t *mbe; 1272 monitor_subsys_t *mss; 1273 ConfigArgs c; 1274 char *argv[3], **rdn; 1275 int i, rc; 1276 1277 /* check if monitor is configured and usable */ 1278 mi = backend_info( "monitor" ); 1279 if ( !mi || !mi->bi_extra ) { 1280 Debug( LDAP_DEBUG_CONFIG, "lload_monitor_open: " 1281 "monitor backend not available, monitoring disabled\n" ); 1282 return 0; 1283 } 1284 mbe = mi->bi_extra; 1285 1286 /* don't bother if monitor is not configured */ 1287 if ( !mbe->is_configured() ) { 1288 static int warning = 0; 1289 1290 if ( warning++ == 0 ) { 1291 Debug( LDAP_DEBUG_CONFIG, "lload_monitor_open: " 1292 "monitoring disabled; " 1293 "configure monitor database to enable\n" ); 1294 } 1295 1296 return 0; 1297 } 1298 1299 if ( lload_monitor_initialized++ ) { 1300 return lload_monitor_initialized_failure; 1301 } 1302 1303 argv[0] = "lload monitor"; 1304 c.argv = argv; 1305 c.argc = 3; 1306 c.fname = argv[0]; 1307 for ( i = 0; s_oid[i].name; i++ ) { 1308 argv[1] = s_oid[i].name; 1309 argv[2] = s_oid[i].oid; 1310 1311 if ( parse_oidm( &c, 0, NULL ) != 0 ) { 1312 Debug( LDAP_DEBUG_ANY, "lload_monitor_open: " 1313 "unable to add objectIdentifier \"%s=%s\"\n", 1314 s_oid[i].name, s_oid[i].oid ); 1315 return 2; 1316 } 1317 } 1318 1319 for ( i = 0; s_at[i].desc != NULL; i++ ) { 1320 rc = register_at( s_at[i].desc, s_at[i].ad, 1 ); 1321 if ( rc != LDAP_SUCCESS ) { 1322 Debug( LDAP_DEBUG_ANY, "lload_monitor_open: " 1323 "register_at failed for attributeType (%s)\n", 1324 s_at[i].desc ); 1325 return 3; 1326 1327 } else { 1328 (*s_at[i].ad)->ad_type->sat_flags |= SLAP_AT_HIDE; 1329 } 1330 } 1331 1332 for ( i = 0; s_oc[i].desc != NULL; i++ ) { 1333 rc = register_oc( s_oc[i].desc, s_oc[i].oc, 1 ); 1334 if ( rc != LDAP_SUCCESS ) { 1335 Debug( LDAP_DEBUG_ANY, "lload_monitor_open: " 1336 "register_oc failed for objectClass (%s)\n", 1337 s_oc[i].desc ); 1338 return 4; 1339 1340 } else { 1341 (*s_oc[i].oc)->soc_flags |= SLAP_OC_HIDE; 1342 } 1343 } 1344 1345 for ( i = 0; s_moc[i].name != NULL; i++ ) { 1346 *s_moc[i].oc = oc_find( s_moc[i].name ); 1347 if ( !*s_moc[i].oc ) { 1348 Debug( LDAP_DEBUG_ANY, "lload_monitor_open: " 1349 "failed to find objectClass (%s)\n", 1350 s_moc[i].name ); 1351 return 5; 1352 } 1353 } 1354 1355 /* register the subsystems - Servers are registered in backends_init */ 1356 for ( mss = balancer_subsys, rdn = lload_subsys_rdn; mss->mss_name; 1357 mss++, rdn++ ) { 1358 ber_str2bv( *rdn, 0, 1, &mss->mss_rdn ); 1359 if ( mbe->register_subsys_late( mss ) ) { 1360 Debug( LDAP_DEBUG_ANY, "lload_monitor_open: " 1361 "failed to register %s subsystem\n", 1362 mss->mss_name ); 1363 return -1; 1364 } 1365 } 1366 1367 checked_lock( &slapd_rq.rq_mutex ); 1368 ldap_pvt_runqueue_insert( &slapd_rq, 1, lload_monitor_update_global_stats, 1369 NULL, "lload_monitor_update_global_stats", "lloadd" ); 1370 checked_unlock( &slapd_rq.rq_mutex ); 1371 1372 return (lload_monitor_initialized_failure = LDAP_SUCCESS); 1373 } 1374