1 /* dncache.c - dn caching for back-asyncmeta */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2016-2021 The OpenLDAP Foundation.
6  * Portions Copyright 2016 Symas Corporation.
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 the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 
18 /* ACKNOWLEDGEMENTS:
19  * This work was developed by Symas Corporation
20  * based on back-meta module for inclusion in OpenLDAP Software.
21  * This work was sponsored by Ericsson. */
22 
23 #include "portable.h"
24 
25 #include <stdio.h>
26 #include <ac/string.h>
27 
28 #include "slap.h"
29 #include "../back-ldap/back-ldap.h"
30 #include "back-asyncmeta.h"
31 
32 /*
33  * The dncache, at present, maps an entry to the target that holds it.
34  */
35 
36 typedef struct metadncacheentry_t {
37 	struct berval	dn;
38 	int 		target;
39 
40 	time_t 		lastupdated;
41 } metadncacheentry_t;
42 
43 /*
44  * asyncmeta_dncache_cmp
45  *
46  * compares two struct metadncacheentry; used by avl stuff
47  * FIXME: modify avl stuff to delete an entry based on cmp
48  * (e.g. when ttl expired?)
49  */
50 int
asyncmeta_dncache_cmp(const void * c1,const void * c2)51 asyncmeta_dncache_cmp(
52 	const void	*c1,
53 	const void	*c2 )
54 {
55 	metadncacheentry_t	*cc1 = ( metadncacheentry_t * )c1;
56 	metadncacheentry_t	*cc2 = ( metadncacheentry_t * )c2;
57 
58 	/*
59 	 * case sensitive, because the dn MUST be normalized
60 	 */
61 	return ber_bvcmp( &cc1->dn, &cc2->dn);
62 }
63 
64 /*
65  * asyncmeta_dncache_dup
66  *
67  * returns -1 in case a duplicate struct metadncacheentry has been inserted;
68  * used by avl stuff
69  */
70 int
asyncmeta_dncache_dup(void * c1,void * c2)71 asyncmeta_dncache_dup(
72 	void		*c1,
73 	void		*c2 )
74 {
75 	metadncacheentry_t	*cc1 = ( metadncacheentry_t * )c1;
76 	metadncacheentry_t	*cc2 = ( metadncacheentry_t * )c2;
77 
78 	/*
79 	 * case sensitive, because the dn MUST be normalized
80 	 */
81 	return ( ber_bvcmp( &cc1->dn, &cc2->dn ) == 0 ) ? -1 : 0;
82 }
83 
84 /*
85  * asyncmeta_dncache_get_target
86  *
87  * returns the target a dn belongs to, or -1 in case the dn is not
88  * in the cache
89  */
90 int
asyncmeta_dncache_get_target(a_metadncache_t * cache,struct berval * ndn)91 asyncmeta_dncache_get_target(
92 	a_metadncache_t	*cache,
93 	struct berval	*ndn )
94 {
95 	metadncacheentry_t	tmp_entry,
96 				*entry;
97 	int			target = META_TARGET_NONE;
98 
99 	assert( cache != NULL );
100 	assert( ndn != NULL );
101 
102 	tmp_entry.dn = *ndn;
103 	ldap_pvt_thread_mutex_lock( &cache->mutex );
104 	entry = ( metadncacheentry_t * )ldap_avl_find( cache->tree,
105 			( caddr_t )&tmp_entry, asyncmeta_dncache_cmp );
106 
107 	if ( entry != NULL ) {
108 
109 		/*
110 		 * if cache->ttl < 0, cache never expires;
111 		 * if cache->ttl = 0 no cache is used; shouldn't get here
112 		 * else, cache is used with ttl
113 		 */
114 		if ( cache->ttl < 0 ) {
115 			target = entry->target;
116 
117 		} else {
118 			if ( entry->lastupdated+cache->ttl > slap_get_time() ) {
119 				target = entry->target;
120 			}
121 		}
122 	}
123 	ldap_pvt_thread_mutex_unlock( &cache->mutex );
124 
125 	return target;
126 }
127 
128 /*
129  * asyncmeta_dncache_update_entry
130  *
131  * updates target and lastupdated of a struct metadncacheentry if exists,
132  * otherwise it gets created; returns -1 in case of error
133  */
134 int
asyncmeta_dncache_update_entry(a_metadncache_t * cache,struct berval * ndn,int target)135 asyncmeta_dncache_update_entry(
136 	a_metadncache_t	*cache,
137 	struct berval	*ndn,
138 	int 		target )
139 {
140 	metadncacheentry_t	*entry,
141 				tmp_entry;
142 	time_t			curr_time = 0L;
143 	int			err = 0;
144 
145 	assert( cache != NULL );
146 	assert( ndn != NULL );
147 
148 	/*
149 	 * if cache->ttl < 0, cache never expires;
150 	 * if cache->ttl = 0 no cache is used; shouldn't get here
151 	 * else, cache is used with ttl
152 	 */
153 	if ( cache->ttl > 0 ) {
154 		curr_time = slap_get_time();
155 	}
156 
157 	tmp_entry.dn = *ndn;
158 
159 	ldap_pvt_thread_mutex_lock( &cache->mutex );
160 	entry = ( metadncacheentry_t * )ldap_avl_find( cache->tree,
161 			( caddr_t )&tmp_entry, asyncmeta_dncache_cmp );
162 
163 	if ( entry != NULL ) {
164 		entry->target = target;
165 		entry->lastupdated = curr_time;
166 
167 	} else {
168 		entry = ch_malloc( sizeof( metadncacheentry_t ) + ndn->bv_len + 1 );
169 		if ( entry == NULL ) {
170 			err = -1;
171 			goto error_return;
172 		}
173 
174 		entry->dn.bv_len = ndn->bv_len;
175 		entry->dn.bv_val = (char *)&entry[ 1 ];
176 		AC_MEMCPY( entry->dn.bv_val, ndn->bv_val, ndn->bv_len );
177 		entry->dn.bv_val[ ndn->bv_len ] = '\0';
178 
179 		entry->target = target;
180 		entry->lastupdated = curr_time;
181 
182 		err = ldap_avl_insert( &cache->tree, ( caddr_t )entry,
183 				asyncmeta_dncache_cmp, asyncmeta_dncache_dup );
184 	}
185 
186 error_return:;
187 	ldap_pvt_thread_mutex_unlock( &cache->mutex );
188 
189 	return err;
190 }
191 
192 int
asyncmeta_dncache_delete_entry(a_metadncache_t * cache,struct berval * ndn)193 asyncmeta_dncache_delete_entry(
194 	a_metadncache_t	*cache,
195 	struct berval	*ndn )
196 {
197 	metadncacheentry_t	*entry,
198 				tmp_entry;
199 
200 	assert( cache != NULL );
201 	assert( ndn != NULL );
202 
203 	tmp_entry.dn = *ndn;
204 
205 	ldap_pvt_thread_mutex_lock( &cache->mutex );
206 	entry = ldap_avl_delete( &cache->tree, ( caddr_t )&tmp_entry,
207 			asyncmeta_dncache_cmp );
208 	ldap_pvt_thread_mutex_unlock( &cache->mutex );
209 
210 	if ( entry != NULL ) {
211 		asyncmeta_dncache_free( ( void * )entry );
212 	}
213 
214 	return 0;
215 }
216 
217 /*
218  * meta_dncache_free
219  *
220  * frees an entry
221  *
222  */
223 void
asyncmeta_dncache_free(void * e)224 asyncmeta_dncache_free(
225 	void		*e )
226 {
227 	free( e );
228 }
229