1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.directory.server.core.partition.impl.btree.jdbm;
20
21
22 import java.io.IOException;
23
24 import jdbm.helper.TupleBrowser;
25
26 import org.apache.directory.api.ldap.model.constants.Loggers;
27 import org.apache.directory.api.ldap.model.cursor.AbstractCursor;
28 import org.apache.directory.api.ldap.model.cursor.CursorException;
29 import org.apache.directory.api.ldap.model.cursor.InvalidCursorPositionException;
30 import org.apache.directory.api.ldap.model.cursor.Tuple;
31 import org.apache.directory.api.ldap.model.exception.LdapException;
32 import org.apache.directory.server.i18n.I18n;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36
37
38
39
40
41
42
43
44
45 class NoDupsCursor<K, V> extends AbstractCursor<Tuple<K, V>>
46 {
47
48 private static final Logger LOG_CURSOR = LoggerFactory.getLogger( Loggers.CURSOR_LOG.getName() );
49
50
51 private static final boolean IS_DEBUG = LOG_CURSOR.isDebugEnabled();
52
53 private final JdbmTable<K, V> table;
54
55 private jdbm.helper.Tuple jdbmTuple = new jdbm.helper.Tuple();
56 private Tuple<K, V> returnedTuple = new Tuple<>();
57 private TupleBrowser browser;
58 private boolean valueAvailable;
59
60
61
62
63
64
65
66 NoDupsCursor( JdbmTable<K, V> table )
67 {
68 if ( IS_DEBUG )
69 {
70 LOG_CURSOR.debug( "Creating NoDupsCursor {}", this );
71 }
72
73 this.table = table;
74 }
75
76
77 private void clearValue()
78 {
79 returnedTuple.setKey( null );
80 returnedTuple.setValue( null );
81 jdbmTuple.setKey( null );
82 jdbmTuple.setValue( null );
83 valueAvailable = false;
84 }
85
86
87 public boolean available()
88 {
89 return valueAvailable;
90 }
91
92
93 public void beforeKey( K key ) throws CursorException
94 {
95 checkNotClosed();
96 try
97 {
98 browser = table.getBTree().browse( key );
99 clearValue();
100 }
101 catch ( IOException e )
102 {
103 throw new CursorException( e );
104 }
105 }
106
107
108 @SuppressWarnings("unchecked")
109 public void afterKey( K key ) throws CursorException
110 {
111 try
112 {
113 browser = table.getBTree().browse( key );
114
115
116
117
118
119
120
121
122 while ( browser.getNext( jdbmTuple ) )
123 {
124 checkNotClosed();
125 K next = ( K ) jdbmTuple.getKey();
126
127 int nextCompared = table.getKeyComparator().compare( next, key );
128
129 if ( nextCompared > 0 )
130 {
131 browser.getPrevious( jdbmTuple );
132 clearValue();
133 return;
134 }
135 }
136
137 clearValue();
138 }
139 catch ( IOException e )
140 {
141 throw new CursorException( e );
142 }
143 }
144
145
146 public void beforeValue( K key, V value ) throws Exception
147 {
148 throw new UnsupportedOperationException( I18n.err( I18n.ERR_596 ) );
149 }
150
151
152 public void afterValue( K key, V value )
153 {
154 throw new UnsupportedOperationException( I18n.err( I18n.ERR_596 ) );
155 }
156
157
158
159
160
161
162
163
164 public void before( Tuple<K, V> element ) throws CursorException
165 {
166 beforeKey( element.getKey() );
167 }
168
169
170
171
172
173 public void after( Tuple<K, V> element ) throws CursorException
174 {
175 afterKey( element.getKey() );
176 }
177
178
179
180
181
182 public void beforeFirst() throws LdapException, CursorException
183 {
184 checkNotClosed();
185 try
186 {
187 browser = table.getBTree().browse();
188 clearValue();
189 }
190 catch ( IOException e )
191 {
192 throw new CursorException( e );
193 }
194 }
195
196
197
198
199
200 public void afterLast() throws LdapException, CursorException
201 {
202 checkNotClosed();
203 try
204 {
205 browser = table.getBTree().browse( null );
206 clearValue();
207 }
208 catch ( IOException e )
209 {
210 throw new CursorException( e );
211 }
212 }
213
214
215
216
217
218 public boolean first() throws LdapException, CursorException
219 {
220 beforeFirst();
221 return next();
222 }
223
224
225
226
227
228 public boolean last() throws LdapException, CursorException
229 {
230 afterLast();
231 return previous();
232 }
233
234
235
236
237
238 @SuppressWarnings("unchecked")
239 public boolean previous() throws LdapException, CursorException
240 {
241 checkNotClosed();
242
243 if ( browser == null )
244 {
245 afterLast();
246 }
247
248 try
249 {
250 if ( browser.getPrevious( jdbmTuple ) )
251 {
252 if ( returnedTuple.getKey() != null
253 && table.getKeyComparator().compare( ( K ) jdbmTuple.getKey(), returnedTuple.getKey() ) == 0 )
254 {
255 browser.getPrevious( jdbmTuple );
256 }
257
258 returnedTuple.setKey( ( K ) jdbmTuple.getKey() );
259 returnedTuple.setValue( ( V ) jdbmTuple.getValue() );
260 valueAvailable = true;
261 return true;
262 }
263 else
264 {
265 clearValue();
266 return false;
267 }
268 }
269 catch ( IOException e )
270 {
271 throw new CursorException( e );
272 }
273 }
274
275
276
277
278
279 @SuppressWarnings("unchecked")
280 public boolean next() throws LdapException, CursorException
281 {
282 checkNotClosed();
283
284 if ( browser == null )
285 {
286 beforeFirst();
287 }
288
289 try
290 {
291 if ( browser.getNext( jdbmTuple ) )
292 {
293 if ( returnedTuple.getKey() != null
294 && table.getKeyComparator().compare( ( K ) jdbmTuple.getKey(), returnedTuple.getKey() ) == 0 )
295 {
296 browser.getNext( jdbmTuple );
297 }
298
299 returnedTuple.setKey( ( K ) jdbmTuple.getKey() );
300 returnedTuple.setValue( ( V ) jdbmTuple.getValue() );
301 valueAvailable = true;
302 return true;
303 }
304 else
305 {
306 clearValue();
307 return false;
308 }
309 }
310 catch ( IOException e )
311 {
312 throw new CursorException( e );
313 }
314 }
315
316
317
318
319
320 public Tuple<K, V> get() throws CursorException
321 {
322 checkNotClosed();
323 if ( valueAvailable )
324 {
325 return returnedTuple;
326 }
327
328 throw new InvalidCursorPositionException();
329 }
330
331
332
333
334
335 @Override
336 public void close() throws IOException
337 {
338 if ( IS_DEBUG )
339 {
340 LOG_CURSOR.debug( "Closing NoDupsCursor {}", this );
341 }
342
343 super.close();
344 }
345
346
347
348
349
350 @Override
351 public void close( Exception cause ) throws IOException
352 {
353 if ( IS_DEBUG )
354 {
355 LOG_CURSOR.debug( "Closing NoDupsCursor {}", this );
356 }
357
358 super.close( cause );
359 }
360 }