]> git.sur5r.net Git - openldap/blob - servers/slapd/back-meta/candidates.c
Sync with HEAD
[openldap] / servers / slapd / back-meta / candidates.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2003 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15 /* ACKNOWLEDGEMENTS:
16  * This work was initially developed by the Howard Chu for inclusion
17  * in OpenLDAP Software and subsequently enhanced by Pierangelo
18  * Masarati.
19  */
20 /* This is an altered version */
21 /*
22  * Copyright 2001, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
23  *
24  * This work has been developed to fulfill the requirements
25  * of SysNet s.n.c. <http:www.sys-net.it> and it has been donated
26  * to the OpenLDAP Foundation in the hope that it may be useful
27  * to the Open Source community, but WITHOUT ANY WARRANTY.
28  *
29  * Permission is granted to anyone to use this software for any purpose
30  * on any computer system, and to alter it and redistribute it, subject
31  * to the following restrictions:
32  *
33  * 1. The author and SysNet s.n.c. are not responsible for the consequences
34  *    of use of this software, no matter how awful, even if they arise from 
35  *    flaws in it.
36  *
37  * 2. The origin of this software must not be misrepresented, either by
38  *    explicit claim or by omission.  Since few users ever read sources,
39  *    credits should appear in the documentation.
40  *
41  * 3. Altered versions must be plainly marked as such, and must not be
42  *    misrepresented as being the original software.  Since few users
43  *    ever read sources, credits should appear in the documentation.
44  *    SysNet s.n.c. cannot be responsible for the consequences of the
45  *    alterations.
46  *
47  * 4. This notice may not be removed or altered.
48  *
49  *
50  * This software is based on the backend back-ldap, implemented
51  * by Howard Chu <hyc@highlandsun.com>, and modified by Mark Valence
52  * <kurash@sassafras.com>, Pierangelo Masarati <ando@sys-net.it> and other
53  * contributors. The contribution of the original software to the present
54  * implementation is acknowledged in this copyright statement.
55  *
56  * A special acknowledgement goes to Howard for the overall architecture
57  * (and for borrowing large pieces of code), and to Mark, who implemented
58  * from scratch the attribute/objectclass mapping.
59  *
60  * The original copyright statement follows.
61  *
62  * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
63  *
64  * Permission is granted to anyone to use this software for any purpose
65  * on any computer system, and to alter it and redistribute it, subject
66  * to the following restrictions:
67  *
68  * 1. The author is not responsible for the consequences of use of this
69  *    software, no matter how awful, even if they arise from flaws in it.
70  *
71  * 2. The origin of this software must not be misrepresented, either by
72  *    explicit claim or by omission.  Since few users ever read sources,
73  *    credits should appear in the documentation.
74  *
75  * 3. Altered versions must be plainly marked as such, and must not be
76  *    misrepresented as being the original software.  Since few users
77  *    ever read sources, credits should appear in the
78  *    documentation.
79  *
80  * 4. This notice may not be removed or altered.
81  *                
82  */
83
84 #include "portable.h"
85
86 #include <stdio.h>
87
88 #include "slap.h"
89 #include "../back-ldap/back-ldap.h"
90 #include "back-meta.h"
91
92 /*
93  * The meta-directory has one suffix, called <suffix>.
94  * It handles a pool of target servers, each with a branch suffix
95  * of the form <branch X>,<suffix>
96  *
97  * When the meta-directory receives a request with a dn that belongs
98  * to a branch, the corresponding target is invoked. When the dn
99  * does not belong to a specific branch, all the targets that
100  * are compatible with the dn are selected as candidates, and
101  * the request is spawned to all the candidate targets
102  *
103  * A request is characterized by a dn. The following cases are handled:
104  *      - the dn is the suffix: <dn> == <suffix>,
105  *              all the targets are candidates (search ...)
106  *      - the dn is a branch suffix: <dn> == <branch X>,<suffix>, or
107  *      - the dn is a subtree of a branch suffix:
108  *              <dn> == <rdn>,<branch X>,<suffix>,
109  *              the target is the only candidate.
110  *
111  * A possible extension will include the handling of multiple suffixes
112  */
113
114 /*
115  * returns 1 if suffix is candidate for dn, otherwise 0
116  *
117  * Note: this function should never be called if dn is the <suffix>.
118  */
119 int 
120 meta_back_is_candidate(
121                 struct berval   *nsuffix,
122                 struct berval   *ndn
123 )
124 {
125         if ( dnIsSuffix( nsuffix, ndn ) || dnIsSuffix( ndn, nsuffix ) ) {
126                 /*
127                  * suffix longer than dn
128                  */
129                 return META_CANDIDATE;
130         }
131
132         return META_NOT_CANDIDATE;
133 }
134
135 /*
136  * meta_back_count_candidates
137  *
138  * returns a count of the possible candidate targets
139  * Note: dn MUST be normalized
140  */
141
142 int
143 meta_back_count_candidates(
144                 struct metainfo         *li,
145                 struct berval           *ndn
146 )
147 {
148         int i, cnt = 0;
149
150         /*
151          * I know assertions should not check run-time values;
152          * at present I didn't find a place for such checks
153          * after config.c
154          */
155         assert( li->targets != NULL );
156         assert( li->ntargets != 0 );
157
158         for ( i = 0; i < li->ntargets; ++i ) {
159                 if ( meta_back_is_candidate( &li->targets[ i ]->suffix, ndn ) ) {
160                         ++cnt;
161                 }
162         }
163
164         return cnt;
165 }
166
167 /*
168  * meta_back_is_candidate_unique
169  *
170  * checks whether a candidate is unique
171  * Note: dn MUST be normalized
172  */
173 int
174 meta_back_is_candidate_unique(
175                 struct metainfo         *li,
176                 struct berval           *ndn
177 )
178 {
179         return ( meta_back_count_candidates( li, ndn ) == 1 );
180 }
181
182 /*
183  * meta_back_select_unique_candidate
184  *
185  * returns the index of the candidate in case it is unique, otherwise -1
186  * Note: dn MUST be normalized.
187  * Note: if defined, the default candidate is returned in case of no match.
188  */
189 int
190 meta_back_select_unique_candidate(
191                 struct metainfo         *li,
192                 struct berval           *ndn
193 )
194 {
195         int i;
196         
197         switch ( meta_back_count_candidates( li, ndn ) ) {
198         case 1:
199                 break;
200         case 0:
201         default:
202                 return ( li->defaulttarget == META_DEFAULT_TARGET_NONE
203                                 ? -1 : li->defaulttarget );
204         }
205
206         for ( i = 0; i < li->ntargets; ++i ) {
207                 if ( meta_back_is_candidate( &li->targets[ i ]->suffix, ndn ) ) {
208                         return i;
209                 }
210         }
211
212         return -1;
213 }
214
215 /*
216  * meta_clear_unused_candidates
217  *
218  * clears all candidates except candidate
219  */
220 int
221 meta_clear_unused_candidates(
222                 struct metainfo         *li,
223                 struct metaconn         *lc,
224                 int                     candidate,
225                 int                     reallyclean
226 )
227 {
228         int i;
229         
230         for ( i = 0; i < li->ntargets; ++i ) {
231                 if ( i == candidate ) {
232                         continue;
233                 }
234                 meta_clear_one_candidate( &lc->conns[ i ], reallyclean );
235         }
236
237         return 0;
238 }
239
240 /*
241  * meta_clear_one_candidate
242  *
243  * clears the selected candidate
244  */
245 int
246 meta_clear_one_candidate(
247                 struct metasingleconn   *lsc,
248                 int                     reallyclean
249 )
250 {
251         lsc->candidate = META_NOT_CANDIDATE;
252
253         if ( !reallyclean ) {
254                 return 0;
255         }
256
257         if ( lsc->ld ) {
258                 ldap_unbind( lsc->ld );
259                 lsc->ld = NULL;
260         }
261
262         if ( lsc->bound_dn.bv_val != NULL ) {
263                 ber_memfree( lsc->bound_dn.bv_val );
264                 lsc->bound_dn.bv_val = NULL;
265                 lsc->bound_dn.bv_len = 0;
266         }
267
268         return 0;
269 }
270