1 17 package org.apache.ldap.server.db.jdbm; 18 19 20 import jdbm.RecordManager; 21 import jdbm.helper.MRU; 22 import jdbm.recman.BaseRecordManager; 23 import jdbm.recman.CacheRecordManager; 24 import org.apache.ldap.common.schema.AttributeType; 25 import org.apache.ldap.common.util.LRUMap; 26 import org.apache.ldap.server.db.Index; 27 import org.apache.ldap.server.db.IndexComparator; 28 import org.apache.ldap.server.db.IndexEnumeration; 29 import org.apache.ldap.server.schema.SerializableComparator; 30 import org.apache.regexp.RE; 31 32 import javax.naming.NamingEnumeration ; 33 import javax.naming.NamingException ; 34 import javax.naming.directory.Attribute ; 35 import javax.naming.directory.Attributes ; 36 import java.io.File ; 37 import java.io.IOException ; 38 import java.math.BigInteger ; 39 40 41 47 public class JdbmIndex implements Index 48 { 49 50 public static final String FORWARD_BTREE = "_forward"; 51 52 public static final String REVERSE_BTREE = "_reverse"; 53 54 55 private AttributeType attribute; 56 57 private JdbmTable forward = null; 58 59 private JdbmTable reverse = null; 60 61 private RecordManager recMan = null; 62 66 private LRUMap keyCache = null; 67 68 69 73 74 83 public JdbmIndex( AttributeType attribute, RecordManager recMan ) 84 throws NamingException 85 { 86 this.attribute = attribute; 87 keyCache = new LRUMap( 1000 ); 88 this.recMan = recMan; 89 initTables(); 90 } 91 92 93 100 public JdbmIndex( AttributeType attribute, String wkDirPath ) 101 throws NamingException 102 { 103 File file = new File ( wkDirPath + File.separator 104 + attribute.getName() ); 105 this.attribute = attribute; 106 keyCache = new LRUMap( 1000 ); 107 108 try 109 { 110 String path = file.getAbsolutePath(); 111 BaseRecordManager base = new BaseRecordManager( path ); 112 base.disableTransactions(); 113 recMan = new CacheRecordManager( base , new MRU( 1000 ) ); 114 } 115 catch ( IOException e ) 116 { 117 NamingException ne = new NamingException ( 118 "Could not initialize the record manager" ); 119 ne.setRootCause( e ); 120 throw ne; 121 } 122 123 initTables(); 124 } 125 126 127 133 private void initTables() throws NamingException 134 { 135 SerializableComparator comp; 136 comp = new SerializableComparator( attribute.getEquality().getOid() ); 137 138 143 forward = new JdbmTable( attribute.getName() + FORWARD_BTREE, 144 true, recMan, new IndexComparator( comp, true ) ); 145 146 152 reverse = new JdbmTable( attribute.getName() + REVERSE_BTREE, 153 ! attribute.isSingleValue(), recMan, 154 new IndexComparator( comp, false ) ); 155 } 156 157 158 161 public AttributeType getAttribute() 162 { 163 return attribute; 164 } 165 166 167 171 172 175 public int count() 176 throws NamingException 177 { 178 return forward.count(); 179 } 180 181 182 185 public int count( Object attrVal ) 186 throws NamingException 187 { 188 return forward.count( getNormalized( attrVal ) ); 189 } 190 191 192 195 public int count( Object attrVal, boolean isGreaterThan ) 196 throws NamingException 197 { 198 return forward.count( getNormalized( attrVal ), isGreaterThan ); 199 } 200 201 202 206 207 210 public BigInteger forwardLookup( Object attrVal ) 211 throws NamingException 212 { 213 return ( BigInteger ) forward.get( getNormalized( attrVal ) ); 214 } 215 216 217 220 public Object reverseLookup( BigInteger id ) 221 throws NamingException 222 { 223 return reverse.get( id ); 224 } 225 226 227 231 232 236 public synchronized void add( Object attrVal, BigInteger id ) 237 throws NamingException 238 { 239 forward.put( getNormalized( attrVal ), id ); 240 reverse.put( id, getNormalized( attrVal ) ); 241 } 242 243 244 248 public synchronized void add( Attribute attr, BigInteger id ) 249 throws NamingException 250 { 251 NamingEnumeration values = attr.getAll(); 253 reverse.put( id, values ); 254 255 values = attr.getAll(); 257 while ( values.hasMore() ) 258 { 259 forward.put( values.next(), id ); 260 } 261 } 262 263 264 268 public synchronized void add( Attributes attrs, BigInteger id ) 269 throws NamingException 270 { 271 add( attrs.get( attribute.getName() ), id ); 272 } 273 274 275 279 public synchronized void drop( Object attrVal, BigInteger id ) 280 throws NamingException 281 { 282 forward.remove( getNormalized( attrVal ), id ); 283 reverse.remove( id, getNormalized( attrVal ) ); 284 } 285 286 287 290 public void drop( BigInteger entryId ) 291 throws NamingException 292 { 293 NamingEnumeration values = reverse.listValues( entryId ); 294 295 while ( values.hasMore() ) 296 { 297 forward.remove( values.next(), entryId ); 298 } 299 300 reverse.remove( entryId ); 301 } 302 303 304 308 public void drop( Attribute attr, BigInteger id ) 309 throws NamingException 310 { 311 NamingEnumeration values = attr.getAll(); 313 314 if ( ! values.hasMore() ) 316 { 317 drop( id ); 318 return; 319 } 320 321 reverse.remove( id, values ); 322 323 values = attr.getAll(); 325 while ( values.hasMore() ) 326 { 327 forward.remove( values.next(), id ); 328 } 329 } 330 331 332 336 public void drop( Attributes attrs, BigInteger id ) 337 throws NamingException 338 { 339 drop( attrs.get( attribute.getName() ), id ); 340 } 341 342 343 347 348 351 public IndexEnumeration listReverseIndices( BigInteger id ) 352 throws NamingException 353 { 354 return new IndexEnumeration( reverse.listTuples( id ), true ); 355 } 356 357 358 361 public IndexEnumeration listIndices() 362 throws NamingException 363 { 364 return new IndexEnumeration( forward.listTuples() ); 365 } 366 367 368 371 public IndexEnumeration listIndices( Object attrVal ) 372 throws NamingException 373 { 374 return new IndexEnumeration( forward.listTuples( 375 getNormalized( attrVal ) ) ); 376 } 377 378 379 383 public IndexEnumeration listIndices( Object attrVal, 384 boolean isGreaterThan ) throws NamingException 385 { 386 return new IndexEnumeration( forward.listTuples( 387 getNormalized( attrVal ), isGreaterThan ) ); 388 } 389 390 391 394 public IndexEnumeration listIndices( RE regex ) 395 throws NamingException 396 { 397 return new IndexEnumeration( forward.listTuples(), false, regex ); 398 } 399 400 401 405 public IndexEnumeration listIndices( RE regex, String prefix ) 406 throws NamingException 407 { 408 return new IndexEnumeration( forward.listTuples( 409 getNormalized( prefix ), true ), false, regex ); 410 } 411 412 413 417 418 422 public boolean hasValue( Object attrVal, BigInteger id ) 423 throws NamingException 424 { 425 return forward.has( getNormalized( attrVal ), id ); 426 } 427 428 429 433 public boolean hasValue( Object attrVal, BigInteger id, 434 boolean isGreaterThan ) 435 throws NamingException 436 { 437 return forward.has( getNormalized( attrVal ), 438 id, isGreaterThan ); 439 } 440 441 442 446 public boolean hasValue( RE regex, BigInteger id ) 447 throws NamingException 448 { 449 IndexEnumeration list = new IndexEnumeration( 450 reverse.listTuples( id ), true, regex ); 451 boolean hasValue = list.hasMore(); 452 list.close(); 453 return hasValue; 454 } 455 456 457 461 462 465 public synchronized void close() 466 throws NamingException 467 { 468 try 469 { 470 forward.close(); 471 reverse.close(); 472 recMan.commit(); 473 recMan.close(); 474 } 475 catch ( IOException e ) 476 { 477 NamingException ne = new NamingException ( 478 "Exception while closing backend index file for attribute " 479 + attribute.getName() ); 480 ne.setRootCause( e ); 481 throw ne; 482 } 483 } 484 485 486 489 public synchronized void sync() 490 throws NamingException 491 { 492 try 493 { 494 recMan.commit(); 495 } 496 catch ( IOException e ) 497 { 498 NamingException ne = new NamingException ( 499 "Exception while syncing backend index file for attribute " 500 + attribute.getName() ); 501 ne.setRootCause( e ); 502 throw ne; 503 } 504 } 505 506 507 517 public Object getNormalized( Object attrVal ) 518 throws NamingException 519 { 520 Object normalized = keyCache.get( attrVal ); 521 522 if ( null == normalized ) 523 { 524 normalized = attribute.getEquality().getNormalizer().normalize( attrVal ); 525 526 keyCache.put( attrVal, normalized ); 530 keyCache.put( normalized, normalized ); 531 } 532 533 return normalized; 534 } 535 } 536 | Popular Tags |