1 /*	$NetBSD: rww.c,v 1.1.1.3 2010/12/12 15:23:16 adam Exp $	*/
2 
3 /* readw.c - deal with read waiters subsystem */
4 /* OpenLDAP: pkg/ldap/servers/slapd/back-monitor/rww.c,v 1.36.2.7 2010/04/13 20:23:33 kurt Exp */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2001-2010 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 "portable.h"
25 
26 #include <stdio.h>
27 #include <ac/string.h>
28 
29 #include "slap.h"
30 #include "lutil.h"
31 #include "back-monitor.h"
32 
33 static int
34 monitor_subsys_rww_destroy(
35 	BackendDB		*be,
36 	monitor_subsys_t	*ms );
37 
38 static int
39 monitor_subsys_rww_update(
40 	Operation		*op,
41 	SlapReply		*rs,
42 	Entry                   *e );
43 
44 enum {
45 	MONITOR_RWW_READ = 0,
46 	MONITOR_RWW_WRITE,
47 
48 	MONITOR_RWW_LAST
49 };
50 
51 static struct monitor_rww_t {
52 	struct berval	rdn;
53 	struct berval	nrdn;
54 } monitor_rww[] = {
55 	{ BER_BVC("cn=Read"),		BER_BVNULL },
56 	{ BER_BVC("cn=Write"),		BER_BVNULL },
57 	{ BER_BVNULL,			BER_BVNULL }
58 };
59 
60 int
61 monitor_subsys_rww_init(
62 	BackendDB		*be,
63 	monitor_subsys_t	*ms )
64 {
65 	monitor_info_t	*mi;
66 
67 	Entry		**ep, *e_conn;
68 	monitor_entry_t	*mp;
69 	int			i;
70 
71 	assert( be != NULL );
72 
73 	ms->mss_destroy = monitor_subsys_rww_destroy;
74 	ms->mss_update = monitor_subsys_rww_update;
75 
76 	mi = ( monitor_info_t * )be->be_private;
77 
78 	if ( monitor_cache_get( mi, &ms->mss_ndn, &e_conn ) ) {
79 		Debug( LDAP_DEBUG_ANY,
80 			"monitor_subsys_rww_init: "
81 			"unable to get entry \"%s\"\n",
82 			ms->mss_ndn.bv_val, 0, 0 );
83 		return( -1 );
84 	}
85 
86 	mp = ( monitor_entry_t * )e_conn->e_private;
87 	mp->mp_children = NULL;
88 	ep = &mp->mp_children;
89 
90 	for ( i = 0; i < MONITOR_RWW_LAST; i++ ) {
91 		struct berval		nrdn, bv;
92 		Entry			*e;
93 
94 		e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &monitor_rww[i].rdn,
95 			mi->mi_oc_monitorCounterObject, mi, NULL, NULL );
96 		if ( e == NULL ) {
97 			Debug( LDAP_DEBUG_ANY,
98 				"monitor_subsys_rww_init: "
99 				"unable to create entry \"cn=Read,%s\"\n",
100 				ms->mss_ndn.bv_val, 0, 0 );
101 			return( -1 );
102 		}
103 
104 		/* steal normalized RDN */
105 		dnRdn( &e->e_nname, &nrdn );
106 		ber_dupbv( &monitor_rww[ i ].nrdn, &nrdn );
107 
108 		BER_BVSTR( &bv, "0" );
109 		attr_merge_one( e, mi->mi_ad_monitorCounter, &bv, NULL );
110 
111 		mp = monitor_entrypriv_create();
112 		if ( mp == NULL ) {
113 			return -1;
114 		}
115 		e->e_private = ( void * )mp;
116 		mp->mp_info = ms;
117 		mp->mp_flags = ms->mss_flags \
118 			| MONITOR_F_SUB | MONITOR_F_PERSISTENT;
119 
120 		if ( monitor_cache_add( mi, e ) ) {
121 			Debug( LDAP_DEBUG_ANY,
122 				"monitor_subsys_rww_init: "
123 				"unable to add entry \"%s,%s\"\n",
124 				monitor_rww[ i ].rdn.bv_val,
125 				ms->mss_ndn.bv_val, 0 );
126 			return( -1 );
127 		}
128 
129 		*ep = e;
130 		ep = &mp->mp_next;
131 	}
132 
133 	monitor_cache_release( mi, e_conn );
134 
135 	return( 0 );
136 }
137 
138 static int
139 monitor_subsys_rww_destroy(
140 	BackendDB		*be,
141 	monitor_subsys_t	*ms )
142 {
143 	int		i;
144 
145 	for ( i = 0; i < MONITOR_RWW_LAST; i++ ) {
146 		ber_memfree_x( monitor_rww[ i ].nrdn.bv_val, NULL );
147 	}
148 
149 	return 0;
150 }
151 
152 static int
153 monitor_subsys_rww_update(
154 	Operation		*op,
155 	SlapReply		*rs,
156 	Entry                   *e )
157 {
158 	monitor_info_t *mi = (monitor_info_t *)op->o_bd->be_private;
159 	Connection	*c;
160 	int		connindex;
161 	long		nconns, nwritewaiters, nreadwaiters;
162 
163 	int		i;
164 	struct berval	nrdn;
165 
166 	Attribute	*a;
167 	char 		buf[LDAP_PVT_INTTYPE_CHARS(long)];
168 	long		num = 0;
169 	ber_len_t	len;
170 
171 	assert( mi != NULL );
172 	assert( e != NULL );
173 
174 	dnRdn( &e->e_nname, &nrdn );
175 
176 	for ( i = 0; !BER_BVISNULL( &monitor_rww[ i ].nrdn ); i++ ) {
177 		if ( dn_match( &nrdn, &monitor_rww[ i ].nrdn ) ) {
178 			break;
179 		}
180 	}
181 
182 	if ( i == MONITOR_RWW_LAST ) {
183 		return SLAP_CB_CONTINUE;
184 	}
185 
186 	nconns = nwritewaiters = nreadwaiters = 0;
187 	for ( c = connection_first( &connindex );
188 			c != NULL;
189 			c = connection_next( c, &connindex ), nconns++ )
190 	{
191 		if ( c->c_writewaiter ) {
192 			nwritewaiters++;
193 		}
194 
195 		/* FIXME: ?!? */
196 		if ( c->c_currentber != NULL ) {
197 			nreadwaiters++;
198 		}
199 	}
200 	connection_done(c);
201 
202 	switch ( i ) {
203 	case MONITOR_RWW_READ:
204 		num = nreadwaiters;
205 		break;
206 
207 	case MONITOR_RWW_WRITE:
208 		num = nwritewaiters;
209 		break;
210 
211 	default:
212 		assert( 0 );
213 	}
214 
215 	snprintf( buf, sizeof( buf ), "%ld", num );
216 
217 	a = attr_find( e->e_attrs, mi->mi_ad_monitorCounter );
218 	assert( a != NULL );
219 	len = strlen( buf );
220 	if ( len > a->a_vals[ 0 ].bv_len ) {
221 		a->a_vals[ 0 ].bv_val = ber_memrealloc( a->a_vals[ 0 ].bv_val, len + 1 );
222 		if ( BER_BVISNULL( &a->a_vals[ 0 ] ) ) {
223 			BER_BVZERO( &a->a_vals[ 0 ] );
224 			return SLAP_CB_CONTINUE;
225 		}
226 	}
227 	AC_MEMCPY( a->a_vals[ 0 ].bv_val, buf, len + 1 );
228 	a->a_vals[ 0 ].bv_len = len;
229 
230 	/* FIXME: touch modifyTimestamp? */
231 
232 	return SLAP_CB_CONTINUE;
233 }
234 
235