001    /*
002     *  Licensed to the Apache Software Foundation (ASF) under one
003     *  or more contributor license agreements.  See the NOTICE file
004     *  distributed with this work for additional information
005     *  regarding copyright ownership.  The ASF licenses this file
006     *  to you under the Apache License, Version 2.0 (the
007     *  "License"); you may not use this file except in compliance
008     *  with the License.  You may obtain a copy of the License at
009     *  
010     *    http://www.apache.org/licenses/LICENSE-2.0
011     *  
012     *  Unless required by applicable law or agreed to in writing,
013     *  software distributed under the License is distributed on an
014     *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     *  KIND, either express or implied.  See the License for the
016     *  specific language governing permissions and limitations
017     *  under the License. 
018     *  
019     */
020    package org.apache.directory.server.tools;
021    
022    
023    import java.io.File;
024    
025    import jdbm.helper.MRU;
026    import jdbm.recman.BaseRecordManager;
027    import jdbm.recman.CacheRecordManager;
028    
029    import org.apache.commons.cli.CommandLine;
030    import org.apache.commons.cli.Option;
031    import org.apache.commons.cli.Options;
032    import org.apache.directory.server.constants.ApacheSchemaConstants;
033    import org.apache.directory.server.core.DefaultDirectoryService;
034    import org.apache.directory.server.core.DirectoryService;
035    import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmIndex;
036    import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmMasterTable;
037    import org.apache.directory.server.i18n.I18n;
038    import org.apache.directory.server.xdbm.Tuple;
039    import org.apache.directory.server.xdbm.tools.IndexUtils;
040    import org.apache.directory.shared.ldap.cursor.Cursor;
041    import org.apache.directory.shared.ldap.entry.DefaultServerEntry;
042    import org.apache.directory.shared.ldap.entry.EntryAttribute;
043    import org.apache.directory.shared.ldap.entry.ServerEntry;
044    import org.apache.directory.shared.ldap.schema.AttributeType;
045    import org.apache.directory.shared.ldap.schema.SchemaManager;
046    
047    
048    /**
049     * Simple tool used to dump the contents of a jdbm based partition.
050     * 
051     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
052     * @version $Rev: 442600 $
053     */
054    public class IndexCommand extends ToolCommand
055    {
056        private SchemaManager schemaManager;
057    
058        private DirectoryService directoryService;
059    
060        public IndexCommand()
061        {
062            super( "index" );
063        }
064    
065    
066        private SchemaManager loadSchemaManager() throws Exception
067        {
068            // --------------------------------------------------------------------
069            // Load the bootstrap schemas to start up the schema partition
070            // --------------------------------------------------------------------
071            directoryService = new DefaultDirectoryService();
072            directoryService.setWorkingDirectory( getInstanceLayout().getPartitionsDir() );
073            directoryService.startup();
074    
075            SchemaManager schemaManager = directoryService.getSchemaManager();
076            
077            return schemaManager;
078        }
079    
080    
081        public void execute( CommandLine cmdline ) throws Exception
082        {
083    //        getLayout().verifyInstallation();
084            schemaManager = loadSchemaManager();
085    
086            String[] partitions = cmdline.getOptionValues( 'p' );
087            String attribute = cmdline.getOptionValue( 'a' );
088            String indexDirPath = cmdline.getOptionValue( 'w' );
089            
090            for ( int ii = 0; ii < partitions.length; ii++ )
091            {
092                File partitionDirectory = new File( getInstanceLayout().getPartitionsDir(), partitions[ii] );
093                File indexDir = null;
094                
095                if( indexDirPath != null )
096                {
097                    indexDir = new File( indexDirPath );
098                }
099                
100                AttributeType attrType = schemaManager.lookupAttributeTypeRegistry( attribute );
101                
102                System.out.println( "building index for attribute type: " + attrType + ", of the partition: " + partitions[ii] );
103                if( indexDir != null )
104                {
105                    System.out.println( "The index file location is: " + indexDir.getAbsolutePath() );
106                }
107                
108                buildIndex( partitionDirectory, indexDir, attrType );
109            }
110            
111            directoryService.shutdown();
112        }
113    
114    
115        @SuppressWarnings("unchecked")
116        private void buildIndex( File partitionDirectory, File indexDirectory, AttributeType attributeType ) throws Exception
117        {
118            if ( !partitionDirectory.exists() )
119            {
120                System.err.println( I18n.err( I18n.ERR_196, partitionDirectory ) );
121                System.exit( 1 );
122            }
123    
124            String path = partitionDirectory.getPath() + File.separator + "master";
125            BaseRecordManager base = new BaseRecordManager( path );
126            base.disableTransactions();
127            CacheRecordManager recMan = new CacheRecordManager( base, new MRU( 1000 ) );
128    
129            JdbmMasterTable<ServerEntry> master = new JdbmMasterTable<ServerEntry>( recMan, schemaManager );
130            JdbmIndex index = new JdbmIndex();
131            index.setAttributeId( attributeType.getName() );
132            index.setCacheSize( JdbmIndex.DEFAULT_INDEX_CACHE_SIZE );
133            index.setNumDupLimit( JdbmIndex.DEFAULT_DUPLICATE_LIMIT );
134    
135            if( indexDirectory == null )
136            {
137                indexDirectory = partitionDirectory;
138            }
139    
140            index.setWkDirPath( indexDirectory );
141            index.init( schemaManager, attributeType, indexDirectory );
142    
143            IndexUtils.printContents( index );
144            
145            JdbmIndex existenceIdx = new JdbmIndex();
146            existenceIdx.setAttributeId( ApacheSchemaConstants.APACHE_EXISTENCE_AT_OID );
147            existenceIdx.setCacheSize( JdbmIndex.DEFAULT_INDEX_CACHE_SIZE );
148            existenceIdx.setNumDupLimit( JdbmIndex.DEFAULT_DUPLICATE_LIMIT );
149    
150            existenceIdx.setWkDirPath( partitionDirectory );
151            existenceIdx.init( schemaManager, schemaManager.lookupAttributeTypeRegistry( ApacheSchemaConstants.APACHE_EXISTENCE_AT_OID ), partitionDirectory );
152    
153            Cursor<Tuple<Long,ServerEntry>> list = master.cursor();
154            
155            while ( list.next() )
156            {
157                Tuple<Long,ServerEntry> tuple = list.get();
158                Long id = tuple.getKey();
159                DefaultServerEntry entry = ( DefaultServerEntry ) tuple.getValue();
160    
161                EntryAttribute attr = entry.get( attributeType );
162                if ( attr == null )
163                {
164                    continue;
165                }
166    
167                for ( int ii = 0; ii < attr.size(); ii++ )
168                {
169                    index.add( attr.get( ii ).get(), id );
170                }
171    
172                existenceIdx.add( attributeType.getOid(), id );
173            }
174    
175            index.sync();
176            index.close();
177            existenceIdx.sync();
178            existenceIdx.close();
179        }
180    
181    
182        public Options getOptions()
183        {
184            Options opts = new Options();
185            Option op = null;
186            op = new Option( "p", "partitions", true, "the partitions to add the attribute indices to" );
187            op.setRequired( true );
188            op.setValueSeparator( File.pathSeparatorChar );
189            opts.addOption( op );
190            op = new Option( "a", "attributes", true, "the attribute to index" );
191            op.setRequired( true );
192            op.setValueSeparator( File.pathSeparatorChar );
193            opts.addOption( op );
194            op = new Option( "i", "install-path", true, "path to apacheds installation directory" );
195            op.setRequired( true );
196            opts.addOption( op );
197            op = new Option( "w", "index-path", true, "path to the directory where index should be stored" );
198            op.setRequired( false );
199            opts.addOption( op );
200    
201            return opts;
202        }
203    }