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.core.partition.impl.btree.jdbm;
21
22
23 import java.io.File;
24 import java.io.FilenameFilter;
25 import java.io.IOException;
26 import java.net.URI;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.List;
30 import java.util.UUID;
31
32 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
33 import org.apache.directory.api.ldap.model.csn.CsnFactory;
34 import org.apache.directory.api.ldap.model.cursor.Cursor;
35 import org.apache.directory.api.ldap.model.cursor.CursorException;
36 import org.apache.directory.api.ldap.model.cursor.Tuple;
37 import org.apache.directory.api.ldap.model.entry.Attribute;
38 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
39 import org.apache.directory.api.ldap.model.entry.Entry;
40 import org.apache.directory.api.ldap.model.entry.Value;
41 import org.apache.directory.api.ldap.model.exception.LdapException;
42 import org.apache.directory.api.ldap.model.exception.LdapOtherException;
43 import org.apache.directory.api.ldap.model.exception.LdapSchemaViolationException;
44 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
45 import org.apache.directory.api.ldap.model.name.Dn;
46 import org.apache.directory.api.ldap.model.schema.AttributeType;
47 import org.apache.directory.api.ldap.model.schema.SchemaManager;
48 import org.apache.directory.api.util.exception.MultiException;
49 import org.apache.directory.server.constants.ApacheSchemaConstants;
50 import org.apache.directory.server.core.api.DnFactory;
51 import org.apache.directory.server.core.api.entry.ClonedServerEntry;
52 import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
53 import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
54 import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext;
55 import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
56 import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext;
57 import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext;
58 import org.apache.directory.server.core.api.interceptor.context.OperationContext;
59 import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext;
60 import org.apache.directory.server.core.api.partition.Partition;
61 import org.apache.directory.server.core.api.partition.PartitionReadTxn;
62 import org.apache.directory.server.core.api.partition.PartitionTxn;
63 import org.apache.directory.server.core.api.partition.PartitionWriteTxn;
64 import org.apache.directory.server.core.partition.impl.btree.AbstractBTreePartition;
65 import org.apache.directory.server.i18n.I18n;
66 import org.apache.directory.server.xdbm.Index;
67 import org.apache.directory.server.xdbm.ParentIdAndRdn;
68 import org.apache.directory.server.xdbm.search.impl.CursorBuilder;
69 import org.apache.directory.server.xdbm.search.impl.DefaultOptimizer;
70 import org.apache.directory.server.xdbm.search.impl.DefaultSearchEngine;
71 import org.apache.directory.server.xdbm.search.impl.EvaluatorBuilder;
72 import org.apache.directory.server.xdbm.search.impl.NoOpOptimizer;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
75
76 import com.github.benmanes.caffeine.cache.Cache;
77 import com.github.benmanes.caffeine.cache.Caffeine;
78
79 import jdbm.RecordManager;
80 import jdbm.helper.MRU;
81 import jdbm.recman.BaseRecordManager;
82 import jdbm.recman.CacheRecordManager;
83 import jdbm.recman.TransactionManager;
84
85
86
87
88
89
90
91
92 public class JdbmPartition extends AbstractBTreePartition
93 {
94
95 private static final Logger LOG = LoggerFactory.getLogger( JdbmPartition.class );
96
97 private static final String JDBM_DB_FILE_EXTN = ".db";
98
99 private static final FilenameFilter DB_FILTER = new FilenameFilter()
100 {
101 @Override
102 public boolean accept( File dir, String name )
103 {
104
105 return name.endsWith( JDBM_DB_FILE_EXTN ) && !name.startsWith( "master." );
106 }
107 };
108
109
110 private RecordManager recMan;
111
112
113 private Cache< String, Entry > entryCache;
114
115
116
117
118
119
120
121
122 public JdbmPartition( SchemaManager schemaManager, DnFactory dnFactory )
123 {
124 super( schemaManager, dnFactory );
125
126
127 if ( cacheSize < 0 )
128 {
129 cacheSize = DEFAULT_CACHE_SIZE;
130 LOG.debug( "Using the default entry cache size of {} for {} partition", cacheSize, id );
131 }
132 else
133 {
134 LOG.debug( "Using the custom configured cache size of {} for {} partition", cacheSize, id );
135 }
136 }
137
138
139
140
141
142 private int rebuildIndexes( PartitionTxn partitionTxn ) throws LdapException, IOException
143 {
144 Cursor<Tuple<String, Entry>> cursor = getMasterTable().cursor();
145
146 int masterTableCount = 0;
147 int repaired = 0;
148
149 System.out.println( "Re-building indices..." );
150
151 boolean ctxEntryLoaded = false;
152
153 try
154 {
155 while ( cursor.next() )
156 {
157 masterTableCount++;
158 Tuple<String, Entry> tuple = cursor.get();
159 String id = tuple.getKey();
160
161 Entry entry = tuple.getValue();
162
163
164 String parentId = entry.get( ApacheSchemaConstants.ENTRY_PARENT_ID_OID ).getString();
165 System.out.println( "Read entry " + entry.getDn() + " with ID " + id + " and parent ID " + parentId );
166
167 Dn dn = entry.getDn();
168
169 ParentIdAndRdn parentIdAndRdn = null;
170
171
172 if ( !ctxEntryLoaded && getSuffixDn().getName().startsWith( dn.getName() ) )
173 {
174
175 parentIdAndRdn = new ParentIdAndRdn( parentId, getSuffixDn().getRdns() );
176 ctxEntryLoaded = true;
177 }
178 else
179 {
180 parentIdAndRdn = new ParentIdAndRdn( parentId, dn.getRdn() );
181 }
182
183
184 rdnIdx.add( partitionTxn, parentIdAndRdn, id );
185
186
187
188 Attribute objectClass = entry.get( objectClassAT );
189
190 if ( objectClass == null )
191 {
192 String msg = I18n.err( I18n.ERR_217, dn, entry );
193 ResultCodeEnum rc = ResultCodeEnum.OBJECT_CLASS_VIOLATION;
194 throw new LdapSchemaViolationException( rc, msg );
195 }
196
197 for ( Value value : objectClass )
198 {
199 String valueStr = value.getString();
200
201 if ( valueStr.equals( SchemaConstants.TOP_OC ) )
202 {
203 continue;
204 }
205
206 objectClassIdx.add( partitionTxn, valueStr, id );
207 }
208
209
210 if ( objectClass.contains( SchemaConstants.ALIAS_OC ) )
211 {
212 Attribute aliasAttr = entry.get( aliasedObjectNameAT );
213 addAliasIndices( partitionTxn, id, dn, new Dn( schemaManager, aliasAttr.getString() ) );
214 }
215
216
217
218 Attribute entryCsn = entry.get( entryCsnAT );
219
220 if ( entryCsn == null )
221 {
222 String msg = I18n.err( I18n.ERR_219, dn, entry );
223 throw new LdapSchemaViolationException( ResultCodeEnum.OBJECT_CLASS_VIOLATION, msg );
224 }
225
226 entryCsnIdx.add( partitionTxn, entryCsn.getString(), id );
227
228
229
230 if ( entry.containsAttribute( administrativeRoleAT ) )
231 {
232
233 Attribute adminRoles = entry.get( administrativeRoleAT );
234
235 for ( Value value : adminRoles )
236 {
237 adminRoleIdx.add( partitionTxn, value.getString(), id );
238 }
239
240
241 presenceIdx.add( partitionTxn, administrativeRoleAT.getOid(), id );
242 }
243
244
245
246 for ( Attribute attribute : entry )
247 {
248 AttributeType attributeType = attribute.getAttributeType();
249 String attributeOid = attributeType.getOid();
250
251 if ( hasUserIndexOn( attributeType ) )
252 {
253 Index<Object, String> idx = ( Index<Object, String> ) getUserIndex( attributeType );
254
255
256
257
258 for ( Value value : attribute )
259 {
260 idx.add( partitionTxn, value.getString(), id );
261 }
262
263
264 presenceIdx.add( partitionTxn, attributeOid, id );
265 }
266 }
267 }
268
269 }
270 catch ( Exception e )
271 {
272 System.out.println( "Exiting after fetching entries " + repaired );
273 throw new LdapOtherException( e.getMessage(), e );
274 }
275 finally
276 {
277 cursor.close();
278 }
279
280 return masterTableCount;
281 }
282
283
284
285
286
287 private void updateRdnIndexCounters( PartitionTxn partitionTxn ) throws LdapException, IOException
288 {
289 Cursor<Tuple<String, Entry>> cursor = getMasterTable().cursor();
290
291 System.out.println( "Updating the RDN index counters..." );
292
293 try
294 {
295 while ( cursor.next() )
296 {
297 Tuple<String, Entry> tuple = cursor.get();
298
299 Entry entry = tuple.getValue();
300
301
302
303 String parentId = entry.get( ApacheSchemaConstants.ENTRY_PARENT_ID_OID ).getString();
304
305 if ( parentId != Partition.ROOT_ID )
306 {
307 updateRdnIdx( partitionTxn, parentId, ADD_CHILD, 0 );
308 }
309 }
310 }
311 catch ( Exception e )
312 {
313 System.out.println( "Exiting, wasn't able to update the RDN index counters" );
314 throw new LdapOtherException( e.getMessage(), e );
315 }
316 finally
317 {
318 cursor.close();
319 }
320 }
321
322
323
324
325
326 @Override
327 protected void doRepair() throws LdapException
328 {
329 BaseRecordManager base;
330
331 try
332 {
333 base = new BaseRecordManager( getPartitionPath().getPath() );
334 TransactionManager transactionManager = base.getTransactionManager();
335 transactionManager.setMaximumTransactionsInLog( 2000 );
336 }
337 catch ( IOException ioe )
338 {
339 throw new LdapOtherException( ioe.getMessage(), ioe );
340 }
341
342
343 File partitionDir = new File( getPartitionPath() );
344
345
346 List<String> indexDbFileNameList = Arrays.asList( partitionDir.list( DB_FILTER ) );
347
348
349 List<String> allIndices = new ArrayList<>();
350
351 try
352 {
353
354 for ( Index<?, String> index : getIndexedAttributes() )
355 {
356
357 AttributeType indexAT = schemaManager.lookupAttributeTypeRegistry( index.getAttributeId() );
358 String oid = indexAT.getOid();
359 allIndices.add( oid );
360
361
362 String name = oid + JDBM_DB_FILE_EXTN;
363
364
365
366 if ( indexDbFileNameList.contains( name ) )
367 {
368 ( ( JdbmIndex<?> ) index ).close( null );
369
370 File indexFile = new File( partitionDir, name );
371 indexFile.delete();
372
373
374 ( ( JdbmIndex<?> ) index ).init( base, schemaManager, indexAT );
375 }
376 }
377
378 int masterTableCount = rebuildIndexes( null );
379
380
381
382 updateRdnIndexCounters( null );
383
384
385 sync();
386
387 System.out.println( "Total entries present in the partition " + masterTableCount );
388 System.out.println( "Repair complete" );
389 }
390 catch ( IOException ioe )
391 {
392 throw new LdapOtherException( ioe.getMessage(), ioe );
393 }
394 }
395
396
397 @Override
398 protected void doInit() throws LdapException
399 {
400 if ( !initialized )
401 {
402 BaseRecordManager base;
403
404
405 if ( !optimizerEnabled )
406 {
407 setOptimizer( new NoOpOptimizer() );
408 }
409 else
410 {
411 setOptimizer( new DefaultOptimizer( this ) );
412 }
413
414 EvaluatorBuildersearch/impl/EvaluatorBuilder.html#EvaluatorBuilder">EvaluatorBuilder evaluatorBuilder = new EvaluatorBuilder( this, schemaManager );
415 CursorBuilder/xdbm/search/impl/CursorBuilder.html#CursorBuilder">CursorBuilder cursorBuilder = new CursorBuilder( this, evaluatorBuilder );
416
417 setSearchEngine( new DefaultSearchEngine( this, cursorBuilder, evaluatorBuilder, getOptimizer() ) );
418
419
420 File partitionDir = new File( getPartitionPath() );
421
422 if ( !partitionDir.exists() && !partitionDir.mkdirs() )
423 {
424 throw new LdapOtherException( I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECTORY, partitionDir ) );
425 }
426
427
428 String path = partitionDir.getPath() + File.separator + id;
429
430 try
431 {
432 base = new BaseRecordManager( path );
433 TransactionManager transactionManager = base.getTransactionManager();
434 transactionManager.setMaximumTransactionsInLog( 2000 );
435
436
437
438 String cacheSizeVal = System.getProperty( "jdbm.recman.cache.size", "100" );
439
440 int recCacheSize = Integer.parseInt( cacheSizeVal );
441
442 LOG.info( "Setting CacheRecondManager's cache size to {}", recCacheSize );
443
444 recMan = new CacheRecordManager( base, new MRU( recCacheSize ) );
445 }
446 catch ( IOException ioe )
447 {
448 throw new LdapOtherException( ioe.getMessage(), ioe );
449 }
450
451
452 List<String> allIndices = new ArrayList<>();
453 List<Index<?, String>> indexToBuild = new ArrayList<>();
454
455 for ( Index<?, String> index : getIndexedAttributes() )
456 {
457 String oid = schemaManager.lookupAttributeTypeRegistry( index.getAttributeId() ).getOid();
458 allIndices.add( oid );
459
460
461
462 try
463 {
464
465 String forwardIndex = oid + "_forward";
466
467 if ( recMan.getNamedObject( forwardIndex ) == 0 )
468 {
469
470 indexToBuild.add( index );
471 }
472 }
473 catch ( IOException ioe )
474 {
475 throw new LdapOtherException( ioe.getMessage(), ioe );
476 }
477 }
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511 super.doInit();
512
513 if ( cacheSize < 0 )
514 {
515 cacheSize = DEFAULT_CACHE_SIZE;
516 LOG.debug( "Using the default entry cache size of {} for {} partition", cacheSize, id );
517 }
518 else
519 {
520 LOG.debug( "Using the custom configured cache size of {} for {} partition", cacheSize, id );
521 }
522
523
524 try
525 {
526 master = new JdbmMasterTable( recMan, schemaManager );
527 }
528 catch ( IOException ioe )
529 {
530 throw new LdapOtherException( ioe.getMessage(), ioe );
531 }
532
533 if ( !indexToBuild.isEmpty() )
534 {
535 buildUserIndex( beginReadTransaction(), indexToBuild );
536 }
537
538 entryCache = Caffeine.newBuilder().maximumSize( cacheSize ).build();
539
540
541 if ( ( suffixDn != null ) && ( contextEntry != null ) )
542 {
543 Dn contextEntryDn = contextEntry.getDn();
544
545
546 if ( !contextEntryDn.isSchemaAware() )
547 {
548 contextEntryDn = new Dn( schemaManager, contextEntryDn );
549 }
550
551
552 if ( suffixDn.equals( contextEntryDn ) )
553 {
554
555 Entry suffixEntry;
556 LookupOperationContext/interceptor/context/LookupOperationContext.html#LookupOperationContext">LookupOperationContext lookupContext = new LookupOperationContext( null, suffixDn );
557 lookupContext.setPartition( this );
558
559 try ( PartitionTxn partitionTxn = beginReadTransaction() )
560 {
561 lookupContext.setTransaction( partitionTxn );
562 suffixEntry = lookup( lookupContext );
563 }
564 catch ( IOException ioe )
565 {
566 throw new LdapOtherException( ioe.getMessage(), ioe );
567 }
568
569
570 if ( suffixEntry == null )
571 {
572
573 if ( !contextEntry.isSchemaAware() )
574 {
575
576 contextEntry = new DefaultEntry( schemaManager, contextEntry );
577 }
578
579
580 if ( contextEntry.get( SchemaConstants.ENTRY_CSN_AT ) == null )
581 {
582 contextEntry.add( SchemaConstants.ENTRY_CSN_AT, new CsnFactory( 0 ).newInstance()
583 .toString() );
584 }
585
586
587 if ( contextEntry.get( SchemaConstants.ENTRY_UUID_AT ) == null )
588 {
589 String uuid = UUID.randomUUID().toString();
590 contextEntry.add( SchemaConstants.ENTRY_UUID_AT, uuid );
591 }
592
593
594 PartitionTxn partitionTxn = null;
595 AddOperationContextre/api/interceptor/context/AddOperationContext.html#AddOperationContext">AddOperationContext addContext = new AddOperationContext( null, contextEntry );
596
597 try
598 {
599 partitionTxn = beginWriteTransaction();
600 addContext.setTransaction( partitionTxn );
601
602 add( addContext );
603 partitionTxn.commit();
604 }
605 catch ( LdapException le )
606 {
607 if ( partitionTxn != null )
608 {
609 try
610 {
611 partitionTxn.abort();
612 }
613 catch ( IOException ioe )
614 {
615 throw new LdapOtherException( ioe.getMessage(), ioe );
616 }
617 }
618
619 throw le;
620 }
621 catch ( IOException ioe )
622 {
623 try
624 {
625 partitionTxn.abort();
626 }
627 catch ( IOException ioe2 )
628 {
629 throw new LdapOtherException( ioe2.getMessage(), ioe2 );
630 }
631
632 throw new LdapOtherException( ioe.getMessage(), ioe );
633 }
634 }
635 }
636 }
637
638
639 initialized = true;
640 }
641 }
642
643
644
645
646
647 public String getDefaultId()
648 {
649 return Partition.DEFAULT_ID;
650 }
651
652
653
654
655
656 public String getRootId()
657 {
658 return Partition.ROOT_ID;
659 }
660
661
662
663
664
665
666
667
668 @Override
669 public synchronized void sync() throws LdapException
670 {
671 if ( !initialized )
672 {
673 return;
674 }
675
676 try
677 {
678
679 recMan.commit();
680
681
682 BaseRecordManager baseRecordManager = null;
683
684 if ( recMan instanceof CacheRecordManager )
685 {
686 baseRecordManager = ( ( BaseRecordManager ) ( ( CacheRecordManager ) recMan ).getRecordManager() );
687 }
688 else
689 {
690 baseRecordManager = ( ( BaseRecordManager ) recMan );
691 }
692
693 baseRecordManager.getTransactionManager().synchronizeLog();
694 }
695 catch ( IOException ioe )
696 {
697 throw new LdapOtherException( ioe.getMessage(), ioe );
698 }
699 }
700
701
702
703
704
705
706
707
708
709
710
711
712 private void buildUserIndex( PartitionTxn partitionTxn, List<Index<?, String>> indices ) throws LdapException
713 {
714 try
715 {
716 Cursor<Tuple<String, Entry>> cursor = master.cursor();
717 cursor.beforeFirst();
718
719 while ( cursor.next() )
720 {
721 for ( Index index : indices )
722 {
723 AttributeType atType = index.getAttribute();
724
725 String attributeOid = index.getAttribute().getOid();
726
727 if ( systemIndices.get( attributeOid ) != null )
728 {
729
730 continue;
731 }
732
733 LOG.info( "building the index for attribute type {}", atType );
734
735 Tuple<String, Entry> tuple = cursor.get();
736
737 String id = tuple.getKey();
738 Entry entry = tuple.getValue();
739
740 Attribute entryAttr = entry.get( atType );
741
742 if ( entryAttr != null )
743 {
744 for ( Value value : entryAttr )
745 {
746 index.add( partitionTxn, value.getString(), id );
747 }
748
749
750 presenceIdx.add( partitionTxn, attributeOid, id );
751 }
752 }
753 }
754
755 cursor.close();
756 }
757 catch ( CursorException | IOException e )
758 {
759 throw new LdapOtherException( e.getMessage(), e );
760 }
761 }
762
763
764
765
766
767
768 private void deleteUnusedIndexFiles( List<String> allIndices, File[] dbFiles )
769 {
770 for ( File file : dbFiles )
771 {
772 String name = file.getName();
773
774 name = name.substring( 0, name.lastIndexOf( JDBM_DB_FILE_EXTN ) );
775
776 if ( systemIndices.get( name ) != null )
777 {
778
779 continue;
780 }
781
782
783 if ( !allIndices.contains( name ) )
784 {
785 boolean deleted = file.delete();
786
787 if ( deleted )
788 {
789 LOG.info( "Deleted unused index file {}", file.getAbsolutePath() );
790 }
791 else
792 {
793 LOG.warn( "Failed to delete unused index file {}", file.getAbsolutePath() );
794 }
795 }
796 }
797 }
798
799
800
801
802
803 @Override
804 protected Index<?, String> convertAndInit( Index<?, String> index ) throws LdapException
805 {
806 JdbmIndex<?> jdbmIndex;
807
808 if ( index instanceof JdbmRdnIndex )
809 {
810 jdbmIndex = ( JdbmRdnIndex ) index;
811 }
812 else if ( index instanceof JdbmDnIndex )
813 {
814 jdbmIndex = ( JdbmDnIndex ) index;
815 }
816 else if ( index instanceof JdbmIndex<?> )
817 {
818 jdbmIndex = ( JdbmIndex<?> ) index;
819 }
820 else
821 {
822 LOG.debug( "Supplied index {} is not a JdbmIndex. "
823 + "Will create new JdbmIndex using copied configuration parameters.", index );
824 jdbmIndex = new JdbmIndex( index.getAttributeId(), true );
825 jdbmIndex.setCacheSize( index.getCacheSize() );
826 jdbmIndex.setNumDupLimit( JdbmIndex.DEFAULT_DUPLICATE_LIMIT );
827 }
828
829 try
830 {
831 jdbmIndex.init( recMan, schemaManager, schemaManager.lookupAttributeTypeRegistry( index.getAttributeId() ) );
832 }
833 catch ( IOException ioe )
834 {
835 throw new LdapOtherException( ioe.getMessage(), ioe );
836 }
837
838 return jdbmIndex;
839 }
840
841
842
843
844
845 @Override
846 protected synchronized void doDestroy( PartitionTxn partitionTxn ) throws LdapException
847 {
848 MultiException errors = new MultiException( I18n.err( I18n.ERR_577 ) );
849
850 if ( !initialized )
851 {
852 return;
853 }
854
855 try
856 {
857 super.doDestroy( partitionTxn );
858 }
859 catch ( Exception e )
860 {
861 errors.addThrowable( e );
862 }
863
864
865 try
866 {
867 recMan.close();
868 LOG.debug( "Closed record manager for {} partition.", suffixDn );
869 }
870 catch ( IOException t )
871 {
872 LOG.error( I18n.err( I18n.ERR_127 ), t );
873 errors.addThrowable( t );
874 }
875 finally
876 {
877 if ( entryCache != null )
878 {
879 entryCache.invalidateAll();
880 }
881 }
882
883 if ( errors.size() > 0 )
884 {
885 throw new LdapOtherException( errors.getMessage(), errors );
886 }
887 }
888
889
890
891
892
893 @Override
894 protected final Index createSystemIndex( String oid, URI path, boolean withReverse ) throws LdapException
895 {
896 LOG.debug( "Supplied index {} is not a JdbmIndex. "
897 + "Will create new JdbmIndex using copied configuration parameters." );
898 JdbmIndex<?> jdbmIndex;
899
900 if ( oid.equals( ApacheSchemaConstants.APACHE_RDN_AT_OID ) )
901 {
902 jdbmIndex = new JdbmRdnIndex();
903 jdbmIndex.setAttributeId( ApacheSchemaConstants.APACHE_RDN_AT_OID );
904 jdbmIndex.setNumDupLimit( JdbmIndex.DEFAULT_DUPLICATE_LIMIT );
905 }
906 else if ( oid.equals( ApacheSchemaConstants.APACHE_ALIAS_AT_OID ) )
907 {
908 jdbmIndex = new JdbmDnIndex( ApacheSchemaConstants.APACHE_ALIAS_AT_OID );
909 jdbmIndex.setAttributeId( ApacheSchemaConstants.APACHE_ALIAS_AT_OID );
910 jdbmIndex.setNumDupLimit( JdbmIndex.DEFAULT_DUPLICATE_LIMIT );
911 }
912 else
913 {
914 jdbmIndex = new JdbmIndex( oid, withReverse );
915 jdbmIndex.setNumDupLimit( JdbmIndex.DEFAULT_DUPLICATE_LIMIT );
916 }
917
918 jdbmIndex.setWkDirPath( path );
919
920 return jdbmIndex;
921 }
922
923
924 @Override
925 public void updateCache( OperationContext opCtx )
926 {
927 if ( entryCache == null )
928 {
929 return;
930 }
931
932 try
933 {
934 if ( opCtx instanceof ModifyOperationContext )
935 {
936
937 ModifyOperationContext/../../../org/apache/directory/server/core/api/interceptor/context/ModifyOperationContext.html#ModifyOperationContext">ModifyOperationContext modCtx = ( ModifyOperationContext ) opCtx;
938 Entry entry = modCtx.getAlteredEntry();
939 String id = entry.get( SchemaConstants.ENTRY_UUID_AT ).getString();
940
941 if ( entry instanceof ClonedServerEntry )
942 {
943 entry = ( ( ClonedServerEntry ) entry ).getOriginalEntry();
944 }
945
946 entryCache.put( id, entry );
947 }
948 else if ( ( opCtx instanceof MoveOperationContext )
949 || ( opCtx instanceof MoveAndRenameOperationContext )
950 || ( opCtx instanceof RenameOperationContext ) )
951 {
952
953 entryCache.invalidateAll();
954 }
955 else if ( opCtx instanceof DeleteOperationContext )
956 {
957
958 DeleteOperationContext/../../../org/apache/directory/server/core/api/interceptor/context/DeleteOperationContext.html#DeleteOperationContext">DeleteOperationContext delCtx = ( DeleteOperationContext ) opCtx;
959 entryCache.invalidate( delCtx.getEntry().get( SchemaConstants.ENTRY_UUID_AT ).getString() );
960 }
961 }
962 catch ( LdapException e )
963 {
964 LOG.warn( "Failed to update entry cache", e );
965 }
966 }
967
968
969 @Override
970 public Entry lookupCache( String id )
971 {
972 return ( entryCache != null ) ? entryCache.getIfPresent( id ) : null;
973 }
974
975
976 @Override
977 public void addToCache( String id, Entry entry )
978 {
979 if ( entryCache == null )
980 {
981 return;
982 }
983
984 Entry addedEntry = entry;
985
986 if ( entry instanceof ClonedServerEntry )
987 {
988 addedEntry = ( ( ClonedServerEntry ) entry ).getOriginalEntry();
989 }
990
991 entryCache.put( id, addedEntry );
992 }
993
994
995 @Override
996 public PartitionReadTxn beginReadTransaction()
997 {
998 return new PartitionReadTxn();
999 }
1000
1001
1002 @Override
1003 public PartitionWriteTxn beginWriteTransaction()
1004 {
1005 return new JdbmPartitionWriteTxn( recMan, isSyncOnWrite() );
1006 }
1007 }