1 /* $NetBSD: thread.c,v 1.1.1.6 2018/02/06 01:53:16 christos Exp $ */ 2 3 /* thread.c - deal with thread subsystem */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2001-2017 The OpenLDAP Foundation. 8 * Portions Copyright 2001-2003 Pierangelo Masarati. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted only as authorized by the OpenLDAP 13 * Public License. 14 * 15 * A copy of this license is available in file LICENSE in the 16 * top-level directory of the distribution or, alternatively, at 17 * <http://www.OpenLDAP.org/license.html>. 18 */ 19 /* ACKNOWLEDGEMENTS: 20 * This work was initially developed by Pierangelo Masarati for inclusion 21 * in OpenLDAP Software. 22 */ 23 24 #include <sys/cdefs.h> 25 __RCSID("$NetBSD: thread.c,v 1.1.1.6 2018/02/06 01:53:16 christos Exp $"); 26 27 #include "portable.h" 28 29 #include <stdio.h> 30 #include <ac/string.h> 31 32 #include "slap.h" 33 #include "back-monitor.h" 34 35 #include <ldap_rq.h> 36 37 #ifndef NO_THREADS 38 typedef enum { 39 MT_UNKNOWN, 40 MT_RUNQUEUE, 41 MT_TASKLIST, 42 43 MT_LAST 44 } monitor_thread_t; 45 46 static struct { 47 struct berval rdn; 48 struct berval desc; 49 struct berval nrdn; 50 ldap_pvt_thread_pool_param_t param; 51 monitor_thread_t mt; 52 } mt[] = { 53 { BER_BVC( "cn=Max" ), 54 BER_BVC("Maximum number of threads as configured"), 55 BER_BVNULL, LDAP_PVT_THREAD_POOL_PARAM_MAX, MT_UNKNOWN }, 56 { BER_BVC( "cn=Max Pending" ), 57 BER_BVC("Maximum number of pending threads"), 58 BER_BVNULL, LDAP_PVT_THREAD_POOL_PARAM_MAX_PENDING, MT_UNKNOWN }, 59 { BER_BVC( "cn=Open" ), 60 BER_BVC("Number of open threads"), 61 BER_BVNULL, LDAP_PVT_THREAD_POOL_PARAM_OPEN, MT_UNKNOWN }, 62 { BER_BVC( "cn=Starting" ), 63 BER_BVC("Number of threads being started"), 64 BER_BVNULL, LDAP_PVT_THREAD_POOL_PARAM_STARTING, MT_UNKNOWN }, 65 { BER_BVC( "cn=Active" ), 66 BER_BVC("Number of active threads"), 67 BER_BVNULL, LDAP_PVT_THREAD_POOL_PARAM_ACTIVE, MT_UNKNOWN }, 68 { BER_BVC( "cn=Pending" ), 69 BER_BVC("Number of pending threads"), 70 BER_BVNULL, LDAP_PVT_THREAD_POOL_PARAM_PENDING, MT_UNKNOWN }, 71 { BER_BVC( "cn=Backload" ), 72 BER_BVC("Number of active plus pending threads"), 73 BER_BVNULL, LDAP_PVT_THREAD_POOL_PARAM_BACKLOAD, MT_UNKNOWN }, 74 #if 0 /* not meaningful right now */ 75 { BER_BVC( "cn=Active Max" ), 76 BER_BVNULL, 77 BER_BVNULL, LDAP_PVT_THREAD_POOL_PARAM_ACTIVE_MAX, MT_UNKNOWN }, 78 { BER_BVC( "cn=Pending Max" ), 79 BER_BVNULL, 80 BER_BVNULL, LDAP_PVT_THREAD_POOL_PARAM_PENDING_MAX, MT_UNKNOWN }, 81 { BER_BVC( "cn=Backload Max" ), 82 BER_BVNULL, 83 BER_BVNULL, LDAP_PVT_THREAD_POOL_PARAM_BACKLOAD_MAX,MT_UNKNOWN }, 84 #endif 85 { BER_BVC( "cn=State" ), 86 BER_BVC("Thread pool state"), 87 BER_BVNULL, LDAP_PVT_THREAD_POOL_PARAM_STATE, MT_UNKNOWN }, 88 89 { BER_BVC( "cn=Runqueue" ), 90 BER_BVC("Queue of running threads - besides those handling operations"), 91 BER_BVNULL, LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN, MT_RUNQUEUE }, 92 { BER_BVC( "cn=Tasklist" ), 93 BER_BVC("List of running plus standby threads - besides those handling operations"), 94 BER_BVNULL, LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN, MT_TASKLIST }, 95 96 { BER_BVNULL } 97 }; 98 99 static int 100 monitor_subsys_thread_update( 101 Operation *op, 102 SlapReply *rs, 103 Entry *e ); 104 #endif /* ! NO_THREADS */ 105 106 /* 107 * initializes log subentry 108 */ 109 int 110 monitor_subsys_thread_init( 111 BackendDB *be, 112 monitor_subsys_t *ms ) 113 { 114 #ifndef NO_THREADS 115 monitor_info_t *mi; 116 monitor_entry_t *mp; 117 Entry *e, **ep, *e_thread; 118 int i; 119 120 ms->mss_update = monitor_subsys_thread_update; 121 122 mi = ( monitor_info_t * )be->be_private; 123 124 if ( monitor_cache_get( mi, &ms->mss_ndn, &e_thread ) ) { 125 Debug( LDAP_DEBUG_ANY, 126 "monitor_subsys_thread_init: unable to get entry \"%s\"\n", 127 ms->mss_dn.bv_val, 128 0, 0 ); 129 return( -1 ); 130 } 131 132 mp = ( monitor_entry_t * )e_thread->e_private; 133 mp->mp_children = NULL; 134 ep = &mp->mp_children; 135 136 for ( i = 0; !BER_BVISNULL( &mt[ i ].rdn ); i++ ) { 137 static char buf[ BACKMONITOR_BUFSIZE ]; 138 int count = -1; 139 char *state = NULL; 140 struct berval bv = BER_BVNULL; 141 142 /* 143 * Max 144 */ 145 e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, 146 &mt[ i ].rdn, 147 mi->mi_oc_monitoredObject, NULL, NULL ); 148 if ( e == NULL ) { 149 Debug( LDAP_DEBUG_ANY, 150 "monitor_subsys_thread_init: " 151 "unable to create entry \"%s,%s\"\n", 152 mt[ i ].rdn.bv_val, 153 ms->mss_ndn.bv_val, 0 ); 154 return( -1 ); 155 } 156 157 /* NOTE: reference to the normalized DN of the entry, 158 * under the assumption it's not modified */ 159 dnRdn( &e->e_nname, &mt[ i ].nrdn ); 160 161 switch ( mt[ i ].param ) { 162 case LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN: 163 break; 164 165 case LDAP_PVT_THREAD_POOL_PARAM_STATE: 166 if ( ldap_pvt_thread_pool_query( &connection_pool, 167 mt[ i ].param, (void *)&state ) == 0 ) 168 { 169 ber_str2bv( state, 0, 0, &bv ); 170 171 } else { 172 BER_BVSTR( &bv, "unknown" ); 173 } 174 break; 175 176 default: 177 /* NOTE: in case of error, it'll be set to -1 */ 178 (void)ldap_pvt_thread_pool_query( &connection_pool, 179 mt[ i ].param, (void *)&count ); 180 bv.bv_val = buf; 181 bv.bv_len = snprintf( buf, sizeof( buf ), "%d", count ); 182 break; 183 } 184 185 if ( !BER_BVISNULL( &bv ) ) { 186 attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo, &bv, NULL ); 187 } 188 189 if ( !BER_BVISNULL( &mt[ i ].desc ) ) { 190 attr_merge_normalize_one( e, 191 slap_schema.si_ad_description, 192 &mt[ i ].desc, NULL ); 193 } 194 195 mp = monitor_entrypriv_create(); 196 if ( mp == NULL ) { 197 return -1; 198 } 199 e->e_private = ( void * )mp; 200 mp->mp_info = ms; 201 mp->mp_flags = ms->mss_flags \ 202 | MONITOR_F_SUB | MONITOR_F_PERSISTENT; 203 204 if ( monitor_cache_add( mi, e ) ) { 205 Debug( LDAP_DEBUG_ANY, 206 "monitor_subsys_thread_init: " 207 "unable to add entry \"%s,%s\"\n", 208 mt[ i ].rdn.bv_val, 209 ms->mss_dn.bv_val, 0 ); 210 return( -1 ); 211 } 212 213 *ep = e; 214 ep = &mp->mp_next; 215 } 216 217 monitor_cache_release( mi, e_thread ); 218 219 #endif /* ! NO_THREADS */ 220 return( 0 ); 221 } 222 223 #ifndef NO_THREADS 224 static int 225 monitor_subsys_thread_update( 226 Operation *op, 227 SlapReply *rs, 228 Entry *e ) 229 { 230 monitor_info_t *mi = ( monitor_info_t * )op->o_bd->be_private; 231 Attribute *a; 232 BerVarray vals = NULL; 233 char buf[ BACKMONITOR_BUFSIZE ]; 234 struct berval rdn, bv; 235 int which, i; 236 struct re_s *re; 237 int count = -1; 238 char *state = NULL; 239 240 assert( mi != NULL ); 241 242 dnRdn( &e->e_nname, &rdn ); 243 244 for ( i = 0; !BER_BVISNULL( &mt[ i ].nrdn ); i++ ) { 245 if ( dn_match( &mt[ i ].nrdn, &rdn ) ) { 246 break; 247 } 248 } 249 250 which = i; 251 if ( BER_BVISNULL( &mt[ which ].nrdn ) ) { 252 return SLAP_CB_CONTINUE; 253 } 254 255 a = attr_find( e->e_attrs, mi->mi_ad_monitoredInfo ); 256 257 switch ( mt[ which ].param ) { 258 case LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN: 259 switch ( mt[ which ].mt ) { 260 case MT_RUNQUEUE: 261 if ( a != NULL ) { 262 if ( a->a_nvals != a->a_vals ) { 263 ber_bvarray_free( a->a_nvals ); 264 } 265 ber_bvarray_free( a->a_vals ); 266 a->a_vals = NULL; 267 a->a_nvals = NULL; 268 a->a_numvals = 0; 269 } 270 271 i = 0; 272 bv.bv_val = buf; 273 ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); 274 LDAP_STAILQ_FOREACH( re, &slapd_rq.run_list, rnext ) { 275 bv.bv_len = snprintf( buf, sizeof( buf ), "{%d}%s(%s)", 276 i, re->tname, re->tspec ); 277 if ( bv.bv_len < sizeof( buf ) ) { 278 value_add_one( &vals, &bv ); 279 } 280 i++; 281 } 282 ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); 283 284 if ( vals ) { 285 attr_merge_normalize( e, mi->mi_ad_monitoredInfo, vals, NULL ); 286 ber_bvarray_free( vals ); 287 288 } else { 289 attr_delete( &e->e_attrs, mi->mi_ad_monitoredInfo ); 290 } 291 break; 292 293 case MT_TASKLIST: 294 if ( a != NULL ) { 295 if ( a->a_nvals != a->a_vals ) { 296 ber_bvarray_free( a->a_nvals ); 297 } 298 ber_bvarray_free( a->a_vals ); 299 a->a_vals = NULL; 300 a->a_nvals = NULL; 301 a->a_numvals = 0; 302 } 303 304 i = 0; 305 bv.bv_val = buf; 306 ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); 307 LDAP_STAILQ_FOREACH( re, &slapd_rq.task_list, tnext ) { 308 bv.bv_len = snprintf( buf, sizeof( buf ), "{%d}%s(%s)", 309 i, re->tname, re->tspec ); 310 if ( bv.bv_len < sizeof( buf ) ) { 311 value_add_one( &vals, &bv ); 312 } 313 i++; 314 } 315 ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); 316 317 if ( vals ) { 318 attr_merge_normalize( e, mi->mi_ad_monitoredInfo, vals, NULL ); 319 ber_bvarray_free( vals ); 320 321 } else { 322 attr_delete( &e->e_attrs, mi->mi_ad_monitoredInfo ); 323 } 324 break; 325 326 default: 327 assert( 0 ); 328 } 329 break; 330 331 case LDAP_PVT_THREAD_POOL_PARAM_STATE: 332 if ( a == NULL ) { 333 return rs->sr_err = LDAP_OTHER; 334 } 335 if ( ldap_pvt_thread_pool_query( &connection_pool, 336 mt[ i ].param, (void *)&state ) == 0 ) 337 { 338 ber_str2bv( state, 0, 0, &bv ); 339 ber_bvreplace( &a->a_vals[ 0 ], &bv ); 340 } 341 break; 342 343 default: 344 if ( a == NULL ) { 345 return rs->sr_err = LDAP_OTHER; 346 } 347 if ( ldap_pvt_thread_pool_query( &connection_pool, 348 mt[ i ].param, (void *)&count ) == 0 ) 349 { 350 bv.bv_val = buf; 351 bv.bv_len = snprintf( buf, sizeof( buf ), "%d", count ); 352 if ( bv.bv_len < sizeof( buf ) ) { 353 ber_bvreplace( &a->a_vals[ 0 ], &bv ); 354 } 355 } 356 break; 357 } 358 359 /* FIXME: touch modifyTimestamp? */ 360 361 return SLAP_CB_CONTINUE; 362 } 363 #endif /* ! NO_THREADS */ 364