1 /* operation.c - deal with operation subsystem */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2001-2021 The OpenLDAP Foundation.
6  * Portions Copyright 2001-2003 Pierangelo Masarati.
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 file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 /* ACKNOWLEDGEMENTS:
18  * This work was initially developed by Pierangelo Masarati for inclusion
19  * in OpenLDAP Software.
20  */
21 
22 #include "portable.h"
23 
24 #include <stdio.h>
25 #include <ac/string.h>
26 
27 #include "slap.h"
28 #include "back-monitor.h"
29 #include "lber_pvt.h"
30 
31 struct monitor_ops_t {
32 	struct berval	rdn;
33 	struct berval	nrdn;
34 } monitor_op[] = {
35 	{ BER_BVC( "cn=Bind" ),		BER_BVNULL },
36 	{ BER_BVC( "cn=Unbind" ),	BER_BVNULL },
37 	{ BER_BVC( "cn=Search" ),	BER_BVNULL },
38 	{ BER_BVC( "cn=Compare" ),	BER_BVNULL },
39 	{ BER_BVC( "cn=Modify" ),	BER_BVNULL },
40 	{ BER_BVC( "cn=Modrdn" ),	BER_BVNULL },
41 	{ BER_BVC( "cn=Add" ),		BER_BVNULL },
42 	{ BER_BVC( "cn=Delete" ),	BER_BVNULL },
43 	{ BER_BVC( "cn=Abandon" ),	BER_BVNULL },
44 	{ BER_BVC( "cn=Extended" ),	BER_BVNULL },
45 	{ BER_BVNULL,			BER_BVNULL }
46 };
47 
48 static int
49 monitor_subsys_ops_destroy(
50 	BackendDB		*be,
51 	monitor_subsys_t	*ms );
52 
53 static int
54 monitor_subsys_ops_update(
55 	Operation		*op,
56 	SlapReply		*rs,
57 	Entry                   *e );
58 
59 int
monitor_subsys_ops_init(BackendDB * be,monitor_subsys_t * ms)60 monitor_subsys_ops_init(
61 	BackendDB		*be,
62 	monitor_subsys_t	*ms )
63 {
64 	monitor_info_t	*mi;
65 
66 	Entry		*e_op, **ep;
67 	monitor_entry_t	*mp;
68 	int 		i;
69 	struct berval	bv_zero = BER_BVC( "0" );
70 
71 	assert( be != NULL );
72 
73 	ms->mss_destroy = monitor_subsys_ops_destroy;
74 	ms->mss_update = monitor_subsys_ops_update;
75 
76 	mi = ( monitor_info_t * )be->be_private;
77 
78 	if ( monitor_cache_get( mi,
79 			&ms->mss_ndn, &e_op ) )
80 	{
81 		Debug( LDAP_DEBUG_ANY,
82 			"monitor_subsys_ops_init: "
83 			"unable to get entry \"%s\"\n",
84 			ms->mss_ndn.bv_val,
85 			0, 0 );
86 		return( -1 );
87 	}
88 
89 	attr_merge_one( e_op, mi->mi_ad_monitorOpInitiated, &bv_zero, NULL );
90 	attr_merge_one( e_op, mi->mi_ad_monitorOpCompleted, &bv_zero, NULL );
91 
92 	mp = ( monitor_entry_t * )e_op->e_private;
93 	mp->mp_children = NULL;
94 	ep = &mp->mp_children;
95 
96 	for ( i = 0; i < SLAP_OP_LAST; i++ ) {
97 		struct berval	rdn;
98 		Entry		*e;
99 		struct berval bv;
100 
101 		/*
102 		 * Initiated ops
103 		 */
104 		e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &monitor_op[i].rdn,
105 			mi->mi_oc_monitorOperation, NULL, NULL );
106 
107 		if ( e == NULL ) {
108 			Debug( LDAP_DEBUG_ANY,
109 				"monitor_subsys_ops_init: "
110 				"unable to create entry \"%s,%s\"\n",
111 				monitor_op[ i ].rdn.bv_val,
112 				ms->mss_ndn.bv_val, 0 );
113 			return( -1 );
114 		}
115 
116 		BER_BVSTR( &bv, "0" );
117 		attr_merge_one( e, mi->mi_ad_monitorOpInitiated, &bv, NULL );
118 		attr_merge_one( e, mi->mi_ad_monitorOpCompleted, &bv, NULL );
119 
120 		/* steal normalized RDN */
121 		dnRdn( &e->e_nname, &rdn );
122 		ber_dupbv( &monitor_op[ i ].nrdn, &rdn );
123 
124 		mp = monitor_entrypriv_create();
125 		if ( mp == NULL ) {
126 			return -1;
127 		}
128 		e->e_private = ( void * )mp;
129 		mp->mp_info = ms;
130 		mp->mp_flags = ms->mss_flags \
131 			| MONITOR_F_SUB | MONITOR_F_PERSISTENT;
132 
133 		if ( monitor_cache_add( mi, e ) ) {
134 			Debug( LDAP_DEBUG_ANY,
135 				"monitor_subsys_ops_init: "
136 				"unable to add entry \"%s,%s\"\n",
137 				monitor_op[ i ].rdn.bv_val,
138 				ms->mss_ndn.bv_val, 0 );
139 			return( -1 );
140 		}
141 
142 		*ep = e;
143 		ep = &mp->mp_next;
144 	}
145 
146 	monitor_cache_release( mi, e_op );
147 
148 	return( 0 );
149 }
150 
151 static int
monitor_subsys_ops_destroy(BackendDB * be,monitor_subsys_t * ms)152 monitor_subsys_ops_destroy(
153 	BackendDB		*be,
154 	monitor_subsys_t	*ms )
155 {
156 	int		i;
157 
158 	for ( i = 0; i < SLAP_OP_LAST; i++ ) {
159 		if ( !BER_BVISNULL( &monitor_op[ i ].nrdn ) ) {
160 			ch_free( monitor_op[ i ].nrdn.bv_val );
161 		}
162 	}
163 
164 	return 0;
165 }
166 
167 static int
monitor_subsys_ops_update(Operation * op,SlapReply * rs,Entry * e)168 monitor_subsys_ops_update(
169 	Operation		*op,
170 	SlapReply		*rs,
171 	Entry                   *e )
172 {
173 	monitor_info_t		*mi = ( monitor_info_t * )op->o_bd->be_private;
174 
175 	ldap_pvt_mp_t		nInitiated = LDAP_PVT_MP_INIT,
176 				nCompleted = LDAP_PVT_MP_INIT;
177 	struct berval		rdn;
178 	int 			i;
179 	Attribute		*a;
180 	slap_counters_t *sc;
181 	static struct berval	bv_ops = BER_BVC( "cn=operations" );
182 
183 	assert( mi != NULL );
184 	assert( e != NULL );
185 
186 	dnRdn( &e->e_nname, &rdn );
187 
188 	if ( dn_match( &rdn, &bv_ops ) ) {
189 		ldap_pvt_mp_init( nInitiated );
190 		ldap_pvt_mp_init( nCompleted );
191 
192 		ldap_pvt_thread_mutex_lock( &slap_counters.sc_mutex );
193 		ldap_pvt_mp_add( nInitiated, slap_counters.sc_ops_initiated );
194 		ldap_pvt_mp_add( nCompleted, slap_counters.sc_ops_completed );
195 		for ( sc = slap_counters.sc_next; sc; sc = sc->sc_next ) {
196 			ldap_pvt_thread_mutex_lock( &sc->sc_mutex );
197 			ldap_pvt_mp_add( nInitiated, sc->sc_ops_initiated );
198 			ldap_pvt_mp_add( nCompleted, sc->sc_ops_completed );
199 			ldap_pvt_thread_mutex_unlock( &sc->sc_mutex );
200 		}
201 		ldap_pvt_thread_mutex_unlock( &slap_counters.sc_mutex );
202 
203 	} else {
204 		for ( i = 0; i < SLAP_OP_LAST; i++ ) {
205 			if ( dn_match( &rdn, &monitor_op[ i ].nrdn ) )
206 			{
207 				ldap_pvt_thread_mutex_lock( &slap_counters.sc_mutex );
208 				ldap_pvt_mp_init_set( nInitiated, slap_counters.sc_ops_initiated_[ i ] );
209 				ldap_pvt_mp_init_set( nCompleted, slap_counters.sc_ops_completed_[ i ] );
210 				for ( sc = slap_counters.sc_next; sc; sc = sc->sc_next ) {
211 					ldap_pvt_thread_mutex_lock( &sc->sc_mutex );
212 					ldap_pvt_mp_add( nInitiated, sc->sc_ops_initiated_[ i ] );
213 					ldap_pvt_mp_add( nCompleted, sc->sc_ops_completed_[ i ] );
214 					ldap_pvt_thread_mutex_unlock( &sc->sc_mutex );
215 				}
216 				ldap_pvt_thread_mutex_unlock( &slap_counters.sc_mutex );
217 				break;
218 			}
219 		}
220 
221 		if ( i == SLAP_OP_LAST ) {
222 			/* not found ... */
223 			return( 0 );
224 		}
225 	}
226 
227 	a = attr_find( e->e_attrs, mi->mi_ad_monitorOpInitiated );
228 	assert ( a != NULL );
229 
230 	/* NOTE: no minus sign is allowed in the counters... */
231 	UI2BV( &a->a_vals[ 0 ], nInitiated );
232 	ldap_pvt_mp_clear( nInitiated );
233 
234 	a = attr_find( e->e_attrs, mi->mi_ad_monitorOpCompleted );
235 	assert ( a != NULL );
236 
237 	/* NOTE: no minus sign is allowed in the counters... */
238 	UI2BV( &a->a_vals[ 0 ], nCompleted );
239 	ldap_pvt_mp_clear( nCompleted );
240 
241 	/* FIXME: touch modifyTimestamp? */
242 
243 	return SLAP_CB_CONTINUE;
244 }
245 
246