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.tools;
21
22
23 import java.io.File;
24 import java.io.IOException;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Set;
28
29 import javax.naming.directory.Attribute;
30 import javax.naming.directory.Attributes;
31
32 import jdbm.helper.MRU;
33 import jdbm.recman.BaseRecordManager;
34 import jdbm.recman.CacheRecordManager;
35
36 import org.apache.commons.cli.CommandLine;
37 import org.apache.commons.cli.Option;
38 import org.apache.commons.cli.Options;
39 import org.apache.directory.server.constants.ServerDNConstants;
40 import org.apache.directory.server.core.DefaultDirectoryService;
41 import org.apache.directory.server.core.DirectoryService;
42 import org.apache.directory.server.core.cursor.Cursor;
43 import org.apache.directory.server.core.entry.ServerEntry;
44 import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmIndex;
45 import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmMasterTable;
46 import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition;
47 import org.apache.directory.server.core.schema.PartitionSchemaLoader;
48 import org.apache.directory.server.schema.SerializableComparator;
49 import org.apache.directory.server.schema.bootstrap.ApacheSchema;
50 import org.apache.directory.server.schema.bootstrap.ApachemetaSchema;
51 import org.apache.directory.server.schema.bootstrap.BootstrapSchemaLoader;
52 import org.apache.directory.server.schema.bootstrap.CoreSchema;
53 import org.apache.directory.server.schema.bootstrap.Schema;
54 import org.apache.directory.server.schema.bootstrap.SystemSchema;
55 import org.apache.directory.server.schema.bootstrap.partition.DbFileListing;
56 import org.apache.directory.server.schema.registries.DefaultOidRegistry;
57 import org.apache.directory.server.schema.registries.DefaultRegistries;
58 import org.apache.directory.server.schema.registries.OidRegistry;
59 import org.apache.directory.server.schema.registries.Registries;
60 import org.apache.directory.server.xdbm.Index;
61 import org.apache.directory.server.xdbm.Tuple;
62 import org.apache.directory.shared.ldap.MultiException;
63 import org.apache.directory.shared.ldap.exception.LdapConfigurationException;
64 import org.apache.directory.shared.ldap.exception.LdapNamingException;
65 import org.apache.directory.shared.ldap.message.ResultCodeEnum;
66 import org.apache.directory.shared.ldap.schema.AttributeType;
67 import org.apache.directory.shared.ldap.util.AttributeUtils;
68
69
70
71
72
73
74
75
76 public class IndexCommand extends ToolCommand
77 {
78 private Registries bootstrapRegistries = new DefaultRegistries( "bootstrap", new BootstrapSchemaLoader(),
79 new DefaultOidRegistry() );
80
81
82 public IndexCommand()
83 {
84 super( "index" );
85 }
86
87
88 @SuppressWarnings("unchecked")
89 private Registries loadRegistries() throws Exception
90 {
91
92
93
94
95
96 BootstrapSchemaLoader loader = new BootstrapSchemaLoader();
97 OidRegistry oidRegistry = new DefaultOidRegistry();
98 final Registries registries = new DefaultRegistries( "bootstrap", loader, oidRegistry );
99
100
101 Set<Schema> bootstrapSchemas = new HashSet<Schema>();
102 bootstrapSchemas.add( new ApachemetaSchema() );
103 bootstrapSchemas.add( new ApacheSchema() );
104 bootstrapSchemas.add( new CoreSchema() );
105 bootstrapSchemas.add( new SystemSchema() );
106 loader.loadWithDependencies( bootstrapSchemas, registries );
107
108
109 List<Throwable> errors = registries.checkRefInteg();
110
111 if ( !errors.isEmpty() )
112 {
113 MultiException e = new MultiException();
114 for ( Throwable t : errors )
115 {
116 e.addThrowable( t );
117 }
118
119 throw e;
120 }
121
122 SerializableComparator.setRegistry( registries.getComparatorRegistry() );
123
124
125
126
127
128
129 File schemaDirectory = new File( getLayout().getPartitionsDirectory(), "schema" );
130 if ( !schemaDirectory.exists() )
131 {
132 throw new LdapConfigurationException( "The following schema directory from "
133 + "the installation layout could not be found:\n\t" + schemaDirectory );
134 }
135
136 JdbmPartition schemaPartition = new JdbmPartition();
137 schemaPartition.setId( "schema" );
138 schemaPartition.setCacheSize( 1000 );
139
140 DbFileListing listing;
141 try
142 {
143 listing = new DbFileListing();
144 }
145 catch ( IOException e )
146 {
147 throw new LdapNamingException( "Got IOException while trying to read DBFileListing: " + e.getMessage(),
148 ResultCodeEnum.OTHER );
149 }
150
151 Set<Index<?,ServerEntry>> indexedAttributes = new HashSet<Index<?,ServerEntry>>();
152
153 for ( String attributeId : listing.getIndexedAttributes() )
154 {
155 indexedAttributes.add( new JdbmIndex( attributeId ) );
156 }
157
158 schemaPartition.setIndexedAttributes( indexedAttributes );
159 schemaPartition.setSuffix( ServerDNConstants.OU_SCHEMA_DN );
160
161 DirectoryService directoryService = new DefaultDirectoryService();
162 schemaPartition.init( directoryService );
163
164
165
166
167
168 PartitionSchemaLoader schemaLoader = new PartitionSchemaLoader( schemaPartition, registries );
169 Registries globalRegistries = new DefaultRegistries( "global", schemaLoader, oidRegistry );
170 schemaLoader.loadEnabled( globalRegistries );
171 SerializableComparator.setRegistry( globalRegistries.getComparatorRegistry() );
172 return globalRegistries;
173 }
174
175
176 public void execute( CommandLine cmdline ) throws Exception
177 {
178 getLayout().verifyInstallation();
179 bootstrapRegistries = loadRegistries();
180
181 String[] partitions = cmdline.getOptionValues( 'p' );
182 String attribute = cmdline.getOptionValue( 'a' );
183
184 for ( int ii = 0; ii < partitions.length; ii++ )
185 {
186 File partitionDirectory = new File( getLayout().getPartitionsDirectory(), partitions[ii] );
187 buildIndex( partitionDirectory, bootstrapRegistries.getAttributeTypeRegistry().lookup( attribute ) );
188 }
189 }
190
191
192 @SuppressWarnings("unchecked")
193 private void buildIndex( File partitionDirectory, AttributeType attributeType ) throws Exception
194 {
195 if ( !partitionDirectory.exists() )
196 {
197 System.err.println( "Partition directory " + partitionDirectory + " does not exist!" );
198 System.exit( 1 );
199 }
200
201 String path = partitionDirectory.getPath() + File.separator + "master";
202 BaseRecordManager base = new BaseRecordManager( path );
203 base.disableTransactions();
204 CacheRecordManager recMan = new CacheRecordManager( base, new MRU( 1000 ) );
205
206 JdbmMasterTable<ServerEntry> master = new JdbmMasterTable<ServerEntry>( recMan, bootstrapRegistries );
207 JdbmIndex index = new JdbmIndex();
208 index.setAttributeId( attributeType.getName() );
209 index.setWkDirPath( partitionDirectory );
210 index.setCacheSize( 1000 );
211 index.setNumDupLimit( 1000 );
212 index.init( attributeType, partitionDirectory );
213
214 Cursor<Tuple<Long,ServerEntry>> list = master.cursor();
215 while ( list.next() )
216 {
217 Tuple<Long,ServerEntry> tuple = list.get();
218 Long id = tuple.getKey();
219 Attributes entry = ( Attributes ) tuple.getValue();
220
221 Attribute attr = AttributeUtils.getAttribute( entry, attributeType );
222 if ( attr == null )
223 {
224 continue;
225 }
226
227 for ( int ii = 0; ii < attr.size(); ii++ )
228 {
229 index.add( attr.get( ii ), id );
230 }
231 }
232
233 index.sync();
234 }
235
236
237 public Options getOptions()
238 {
239 Options opts = new Options();
240 Option op = null;
241 op = new Option( "p", "partitions", true, "the partitions to add the attribute indices to" );
242 op.setRequired( true );
243 op.setValueSeparator( File.pathSeparatorChar );
244 opts.addOption( op );
245 op = new Option( "a", "attributes", true, "the attribute to index" );
246 op.setRequired( true );
247 op.setValueSeparator( File.pathSeparatorChar );
248 opts.addOption( op );
249 op = new Option( "i", "install-path", true, "path to apacheds installation directory" );
250 op.setRequired( true );
251 opts.addOption( op );
252 return opts;
253 }
254 }