tier.c revision 1.1.1.1 1 /* $NetBSD: tier.c,v 1.1.1.1 2025/09/05 21:09:46 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.1.1.1 2025/09/05 21:09:46 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