1 /* $NetBSD: tier.c,v 1.2 2025/09/05 21:16:24 christos Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2024 The OpenLDAP Foundation. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted only as authorized by the OpenLDAP 11 * Public License. 12 * 13 * A copy of this license is available in the file LICENSE in the 14 * top-level directory of the distribution or, alternatively, at 15 * <http://www.OpenLDAP.org/license.html>. 16 */ 17 18 #include <sys/cdefs.h> 19 __RCSID("$NetBSD: tier.c,v 1.2 2025/09/05 21:16:24 christos Exp $"); 20 21 #include "portable.h" 22 23 #include "lload.h" 24 25 lload_t_head tiers; 26 27 int 28 tier_startup( LloadTier *tier ) 29 { 30 LloadBackend *b; 31 32 LDAP_CIRCLEQ_FOREACH ( b, &tier->t_backends, b_next ) { 33 checked_lock( &b->b_mutex ); 34 if ( !b->b_retry_event ) { 35 b->b_retry_event = evtimer_new( daemon_base, backend_connect, b ); 36 if ( !b->b_retry_event ) { 37 Debug( LDAP_DEBUG_ANY, "tier_startup: " 38 "%s failed to allocate retry event\n", 39 tier->t_type.tier_name ); 40 return -1; 41 } 42 } 43 backend_retry( b ); 44 checked_unlock( &b->b_mutex ); 45 } 46 return LDAP_SUCCESS; 47 } 48 49 int 50 tier_reset( LloadTier *tier, int shutdown ) 51 { 52 LloadBackend *b; 53 54 LDAP_CIRCLEQ_FOREACH ( b, &tier->t_backends, b_next ) { 55 epoch_t epoch = epoch_join(); 56 57 checked_lock( &b->b_mutex ); 58 if ( shutdown ) { 59 b->b_numconns = b->b_numbindconns = 0; 60 } 61 backend_reset( b, 1 ); 62 backend_retry( b ); 63 checked_unlock( &b->b_mutex ); 64 65 epoch_leave( epoch ); 66 } 67 return LDAP_SUCCESS; 68 } 69 70 int 71 tier_destroy( LloadTier *tier ) 72 { 73 while ( !LDAP_CIRCLEQ_EMPTY( &tier->t_backends ) ) { 74 LloadBackend *b = LDAP_CIRCLEQ_FIRST( &tier->t_backends ); 75 epoch_t epoch = epoch_join(); 76 77 lload_backend_destroy( b ); 78 79 epoch_leave( epoch ); 80 } 81 82 #ifdef BALANCER_MODULE 83 if ( tier->t_monitor ) { 84 /* FIXME: implement proper subsys shutdown in back-monitor or make 85 * backend just an entry, not a subsys */ 86 if ( slapd_shutdown ) { 87 /* Just drop backlink, back-monitor will call mss_destroy later */ 88 assert( tier->t_monitor->mss_private == tier ); 89 tier->t_monitor->mss_private = NULL; 90 } else { 91 BackendDB *be; 92 struct berval monitordn = BER_BVC("cn=monitor"); 93 int rc; 94 95 be = select_backend( &monitordn, 0 ); 96 97 rc = tier->t_monitor->mss_destroy( be, tier->t_monitor ); 98 assert( rc == LDAP_SUCCESS ); 99 } 100 } 101 #endif /* BALANCER_MODULE */ 102 103 ch_free( tier->t_name.bv_val ); 104 ch_free( tier ); 105 return LDAP_SUCCESS; 106 } 107 108 void 109 lload_tiers_destroy( void ) 110 { 111 while ( !LDAP_STAILQ_EMPTY( &tiers ) ) { 112 LloadTier *tier = LDAP_STAILQ_FIRST( &tiers ); 113 114 LDAP_STAILQ_REMOVE_HEAD( &tiers, t_next ); 115 tier->t_type.tier_destroy( tier ); 116 } 117 } 118 119 void 120 lload_tiers_shutdown( void ) 121 { 122 lload_tiers_reset( 1 ); 123 } 124 125 void 126 lload_tiers_reset( int shutdown ) 127 { 128 LloadTier *tier; 129 130 LDAP_STAILQ_FOREACH ( tier, &tiers, t_next ) { 131 tier->t_type.tier_reset( tier, shutdown ); 132 } 133 } 134 135 void 136 lload_tiers_update( evutil_socket_t s, short what, void *arg ) 137 { 138 LloadTier *tier; 139 140 LDAP_STAILQ_FOREACH ( tier, &tiers, t_next ) { 141 if ( tier->t_type.tier_update ) { 142 tier->t_type.tier_update( tier ); 143 } 144 } 145 } 146 147 extern struct lload_tier_type roundrobin_tier; 148 extern struct lload_tier_type weighted_tier; 149 extern struct lload_tier_type bestof_tier; 150 151 struct { 152 char *name; 153 struct lload_tier_type *type; 154 } tier_types[] = { 155 { "roundrobin", &roundrobin_tier }, 156 { "weighted", &weighted_tier }, 157 { "bestof", &bestof_tier }, 158 159 { NULL } 160 }; 161 162 struct lload_tier_type * 163 lload_tier_find( char *name ) 164 { 165 int i; 166 167 for ( i = 0; tier_types[i].name; i++ ) { 168 if ( !strcasecmp( name, tier_types[i].name ) ) { 169 return tier_types[i].type; 170 } 171 } 172 return NULL; 173 } 174