1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.xdbm.impl.avl;
21
22
23 import java.io.IOException;
24 import java.net.URI;
25
26 import org.apache.directory.api.ldap.model.cursor.Cursor;
27 import org.apache.directory.api.ldap.model.cursor.CursorException;
28 import org.apache.directory.api.ldap.model.cursor.EmptyCursor;
29 import org.apache.directory.api.ldap.model.cursor.Tuple;
30 import org.apache.directory.api.ldap.model.exception.LdapException;
31 import org.apache.directory.api.ldap.model.exception.LdapOtherException;
32 import org.apache.directory.api.ldap.model.schema.AttributeType;
33 import org.apache.directory.api.ldap.model.schema.LdapComparator;
34 import org.apache.directory.api.ldap.model.schema.MatchingRule;
35 import org.apache.directory.api.ldap.model.schema.Normalizer;
36 import org.apache.directory.api.ldap.model.schema.SchemaManager;
37 import org.apache.directory.api.ldap.model.schema.comparators.UuidComparator;
38 import org.apache.directory.server.core.api.partition.PartitionTxn;
39 import org.apache.directory.server.core.partition.impl.btree.IndexCursorAdaptor;
40 import org.apache.directory.server.i18n.I18n;
41 import org.apache.directory.server.xdbm.AbstractIndex;
42 import org.apache.directory.server.xdbm.IndexEntry;
43
44
45
46
47
48
49
50 public class AvlIndex<K> extends AbstractIndex<K, String>
51 {
52 protected Normalizer normalizer;
53 protected AvlTable<K, String> forward;
54 protected AvlTable<String, K> reverse;
55
56
57 public AvlIndex()
58 {
59 super( true );
60 }
61
62
63 public AvlIndex( String attributeId )
64 {
65 super( attributeId, true );
66 }
67
68
69 public AvlIndex( String attributeId, boolean withReverse )
70 {
71 super( attributeId, withReverse );
72 }
73
74
75 public void init( SchemaManager schemaManager, AttributeType attributeType ) throws LdapException
76 {
77 this.attributeType = attributeType;
78
79 MatchingRule mr = attributeType.getEquality();
80
81 if ( mr == null )
82 {
83 mr = attributeType.getOrdering();
84 }
85
86 if ( mr == null )
87 {
88 mr = attributeType.getSubstring();
89 }
90
91 normalizer = mr.getNormalizer();
92
93 if ( normalizer == null )
94 {
95 throw new LdapOtherException( I18n.err( I18n.ERR_212, attributeType ) );
96 }
97
98 LdapComparator<K> comp = ( LdapComparator<K> ) mr.getLdapComparator();
99
100
101
102
103
104
105 forward = new AvlTable<>( attributeType.getName(), comp, UuidComparator.INSTANCE, true );
106
107
108
109
110
111
112
113 if ( withReverse )
114 {
115 if ( attributeType.isSingleValued() )
116 {
117 reverse = new AvlTable<>( attributeType.getName(), UuidComparator.INSTANCE, comp, false );
118 }
119 else
120 {
121 reverse = new AvlTable<>( attributeType.getName(), UuidComparator.INSTANCE, comp, true );
122 }
123 }
124 }
125
126
127 public void add( PartitionTxn partitionTxn, K attrVal, String id ) throws LdapException
128 {
129 forward.put( partitionTxn, attrVal, id );
130
131 if ( withReverse )
132 {
133 reverse.put( partitionTxn, id, attrVal );
134 }
135 }
136
137
138
139
140
141 @Override
142 public void close( PartitionTxn partitionTxn ) throws LdapException, IOException
143 {
144 if ( forward != null )
145 {
146 forward.close( partitionTxn );
147 }
148
149 if ( reverse != null )
150 {
151 reverse.close( partitionTxn );
152 }
153 }
154
155
156
157
158
159 public long count( PartitionTxn partitionTxn ) throws LdapException
160 {
161 return forward.count( partitionTxn );
162 }
163
164
165
166
167
168 public long count( PartitionTxn partitionTxn, K attrVal ) throws LdapException
169 {
170 return forward.count( partitionTxn, attrVal );
171 }
172
173
174
175
176
177 public void drop( PartitionTxn partitionTxn, String id ) throws LdapException
178 {
179 if ( withReverse )
180 {
181 if ( isDupsEnabled() )
182 {
183 Cursor<Tuple<String, K>> cursor = reverse.cursor( partitionTxn, id );
184
185 try
186 {
187 while ( cursor.next() )
188 {
189 Tuple<String, K> tuple = cursor.get();
190 forward.remove( partitionTxn, tuple.getValue(), id );
191 }
192
193 cursor.close();
194 }
195 catch ( CursorException | IOException e )
196 {
197 throw new LdapOtherException( e.getMessage(), e );
198 }
199 }
200 else
201 {
202 K key = reverse.get( partitionTxn, id );
203 forward.remove( partitionTxn, key );
204 }
205
206 reverse.remove( partitionTxn, id );
207 }
208 }
209
210
211
212
213
214 @Override
215 public void drop( PartitionTxn partitionTxn, K attrVal, String id ) throws LdapException
216 {
217 forward.remove( partitionTxn, attrVal, id );
218
219 if ( withReverse )
220 {
221 reverse.remove( partitionTxn, id, attrVal );
222 }
223 }
224
225
226
227
228
229 public boolean forward( PartitionTxn partitionTxn, K attrVal ) throws LdapException
230 {
231 return forward.has( partitionTxn, attrVal );
232 }
233
234
235
236
237
238 public boolean forward( PartitionTxn partitionTxn, K attrVal, String id ) throws LdapException
239 {
240 return forward.has( partitionTxn, attrVal, id );
241 }
242
243
244
245
246
247 @Override
248 public Cursor<IndexEntry<K, String>> forwardCursor( PartitionTxn partitionTxn ) throws LdapException
249 {
250 return new IndexCursorAdaptor( partitionTxn, forward.cursor(), true );
251 }
252
253
254
255
256
257 @SuppressWarnings("unchecked")
258 public Cursor<IndexEntry<K, String>> forwardCursor( PartitionTxn partitionTxn, K key ) throws LdapException
259 {
260 return new IndexCursorAdaptor( partitionTxn, forward.cursor( partitionTxn, key ), true );
261 }
262
263
264
265
266
267 public String forwardLookup( PartitionTxn partitionTxn, K attrVal ) throws LdapException
268 {
269 return forward.get( partitionTxn, attrVal );
270 }
271
272
273
274
275
276 @Override
277 public Cursor<String> forwardValueCursor( PartitionTxn partitionTxn, K key ) throws LdapException
278 {
279 return forward.valueCursor( partitionTxn, key );
280 }
281
282
283
284
285
286 @Override
287 public long greaterThanCount( PartitionTxn partitionTxn, K attrVal ) throws LdapException
288 {
289 return forward.greaterThanCount( partitionTxn, attrVal );
290 }
291
292
293
294
295
296 @Override
297 public long lessThanCount( PartitionTxn partitionTxn, K attrVal ) throws LdapException
298 {
299 return forward.lessThanCount( partitionTxn, attrVal );
300 }
301
302
303
304
305
306 @Override
307 public boolean reverse( PartitionTxn partitionTxn, String id ) throws LdapException
308 {
309 if ( withReverse )
310 {
311 return reverse.has( partitionTxn, id );
312 }
313 else
314 {
315 return false;
316 }
317 }
318
319
320
321
322
323 @Override
324 public boolean reverse( PartitionTxn partitionTxn, String id, K attrVal ) throws LdapException
325 {
326 if ( withReverse )
327 {
328 return reverse.has( partitionTxn, id, attrVal );
329 }
330 else
331 {
332 return false;
333 }
334 }
335
336
337
338
339
340 public K reverseLookup( PartitionTxn partitionTxn, String id ) throws LdapException
341 {
342 if ( withReverse )
343 {
344 return reverse.get( partitionTxn, id );
345 }
346 else
347 {
348 return null;
349 }
350 }
351
352
353
354
355
356 @Override
357 public Cursor<K> reverseValueCursor( PartitionTxn partitionTxn, String id ) throws LdapException
358 {
359 if ( withReverse )
360 {
361 return reverse.valueCursor( partitionTxn, id );
362 }
363 else
364 {
365 return new EmptyCursor<>();
366 }
367 }
368
369
370
371
372
373 public void setWkDirPath( URI wkDirPath )
374 {
375 throw new UnsupportedOperationException( I18n.err( I18n.ERR_213 ) );
376 }
377
378
379
380
381
382 public URI getWkDirPath()
383 {
384 return null;
385 }
386
387
388
389
390
391 @Override
392 public boolean isDupsEnabled()
393 {
394 if ( withReverse )
395 {
396 return reverse.isDupsEnabled();
397 }
398 else
399 {
400 return false;
401 }
402 }
403 }