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