tier.c revision 1.2 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