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