]> git.sur5r.net Git - openldap/blob - servers/slapd/back-meta/candidates.c
a) implement a new candidate selection procedure, based on target naming
[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-2005 The OpenLDAP Foundation.
5  * Portions Copyright 2001-2003 Pierangelo Masarati.
6  * Portions Copyright 1999-2003 Howard Chu.
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 /* ACKNOWLEDGEMENTS:
18  * This work was initially developed by the Howard Chu for inclusion
19  * in OpenLDAP Software and subsequently enhanced by Pierangelo
20  * Masarati.
21  */
22
23 #include "portable.h"
24
25 #include <stdio.h>
26
27 #include "slap.h"
28 #include "../back-ldap/back-ldap.h"
29 #include "back-meta.h"
30
31 /*
32  * The meta-directory has one suffix, called <suffix>.
33  * It handles a pool of target servers, each with a branch suffix
34  * of the form <branch X>,<suffix>
35  *
36  * When the meta-directory receives a request with a dn that belongs
37  * to a branch, the corresponding target is invoked. When the dn
38  * does not belong to a specific branch, all the targets that
39  * are compatible with the dn are selected as candidates, and
40  * the request is spawned to all the candidate targets
41  *
42  * A request is characterized by a dn. The following cases are handled:
43  *      - the dn is the suffix: <dn> == <suffix>,
44  *              all the targets are candidates (search ...)
45  *      - the dn is a branch suffix: <dn> == <branch X>,<suffix>, or
46  *      - the dn is a subtree of a branch suffix:
47  *              <dn> == <rdn>,<branch X>,<suffix>,
48  *              the target is the only candidate.
49  *
50  * A possible extension will include the handling of multiple suffixes
51  */
52
53 static int
54 meta_back_count_candidates(
55                 struct metainfo         *li,
56                 struct berval           *ndn
57 );
58
59 static int
60 meta_back_is_candidate_unique(
61                 struct metainfo         *li,
62                 struct berval           *ndn
63 );
64
65 /*
66  * returns 1 if suffix is candidate for dn, otherwise 0
67  *
68  * Note: this function should never be called if dn is the <suffix>.
69  */
70 int 
71 meta_back_is_candidate(
72                 struct berval   *nsuffix,
73                 struct berval   *ndn
74 )
75 {
76         if ( dnIsSuffix( nsuffix, ndn ) || dnIsSuffix( ndn, nsuffix ) ) {
77                 /*
78                  * suffix longer than dn
79                  */
80                 return META_CANDIDATE;
81         }
82
83         return META_NOT_CANDIDATE;
84 }
85
86 /*
87  * meta_back_count_candidates
88  *
89  * returns a count of the possible candidate targets
90  * Note: dn MUST be normalized
91  */
92
93 static int
94 meta_back_count_candidates(
95                 struct metainfo         *li,
96                 struct berval           *ndn
97 )
98 {
99         int i, cnt = 0;
100
101         /*
102          * I know assertions should not check run-time values;
103          * at present I didn't find a place for such checks
104          * after config.c
105          */
106         assert( li->mi_targets != NULL );
107         assert( li->mi_ntargets != 0 );
108
109         for ( i = 0; i < li->mi_ntargets; ++i ) {
110                 if ( meta_back_is_candidate( &li->mi_targets[ i ]->mt_nsuffix, ndn ) )
111                 {
112                         ++cnt;
113                 }
114         }
115
116         return cnt;
117 }
118
119 /*
120  * meta_back_is_candidate_unique
121  *
122  * checks whether a candidate is unique
123  * Note: dn MUST be normalized
124  */
125 static int
126 meta_back_is_candidate_unique(
127                 struct metainfo         *li,
128                 struct berval           *ndn
129 )
130 {
131         return ( meta_back_count_candidates( li, ndn ) == 1 );
132 }
133
134 /*
135  * meta_back_select_unique_candidate
136  *
137  * returns the index of the candidate in case it is unique, otherwise -1
138  * Note: dn MUST be normalized.
139  * Note: if defined, the default candidate is returned in case of no match.
140  */
141 int
142 meta_back_select_unique_candidate(
143                 struct metainfo         *li,
144                 struct berval           *ndn
145 )
146 {
147         int     i, candidate = META_TARGET_NONE;
148
149         for ( i = 0; i < li->mi_ntargets; ++i ) {
150                 if ( meta_back_is_candidate( &li->mi_targets[ i ]->mt_nsuffix, ndn ) )
151                 {
152                         if ( candidate == META_TARGET_NONE ) {
153                                 candidate = i;
154
155                         } else {
156                                 return META_TARGET_MULTIPLE;
157                         }
158                 }
159         }
160
161         return candidate;
162 }
163
164 /*
165  * meta_clear_unused_candidates
166  *
167  * clears all candidates except candidate
168  */
169 int
170 meta_clear_unused_candidates(
171                 Operation               *op,
172                 struct metaconn         *lc,
173                 int                     candidate
174 )
175 {
176         struct metainfo *li = ( struct metainfo * )op->o_bd->be_private;
177         int             i;
178         char            *candidates = meta_back_candidates_get( op );
179         
180         for ( i = 0; i < li->mi_ntargets; ++i ) {
181                 if ( i == candidate ) {
182                         continue;
183                 }
184                 candidates[ i ] = META_NOT_CANDIDATE;
185         }
186
187         return 0;
188 }
189
190 /*
191  * meta_clear_one_candidate
192  *
193  * clears the selected candidate
194  */
195 int
196 meta_clear_one_candidate(
197                 struct metasingleconn   *lsc
198 )
199 {
200         if ( lsc->msc_ld ) {
201                 ldap_unbind_ext_s( lsc->msc_ld, NULL, NULL );
202                 lsc->msc_ld = NULL;
203         }
204
205         if ( !BER_BVISNULL( &lsc->msc_bound_ndn ) ) {
206                 ber_memfree( lsc->msc_bound_ndn.bv_val );
207                 BER_BVZERO( &lsc->msc_bound_ndn );
208         }
209
210         if ( !BER_BVISNULL( &lsc->msc_cred ) ) {
211                 ber_memfree( lsc->msc_cred.bv_val );
212                 BER_BVZERO( &lsc->msc_cred );
213         }
214
215         return 0;
216 }
217