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.core.partition.impl.btree.jdbm;
021    
022    
023    import jdbm.RecordManager;
024    import jdbm.helper.LongSerializer;
025    import jdbm.helper.Serializer;
026    import jdbm.helper.StringComparator;
027    
028    import org.apache.directory.server.i18n.I18n;
029    import org.apache.directory.server.xdbm.MasterTable;
030    import org.apache.directory.shared.ldap.schema.SchemaManager;
031    import org.apache.directory.shared.ldap.schema.comparators.SerializableComparator;
032    
033    
034    /**
035     * The master table used to store the Attributes of entries.
036     *
037     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
038     * @version $Rev: 902308 $
039     */
040    public class JdbmMasterTable<E> extends JdbmTable<Long,E> implements MasterTable<E>
041    {
042        private static final StringComparator STRCOMP = new StringComparator();
043    
044    
045        private static final SerializableComparator<Long> LONG_COMPARATOR =
046                new SerializableComparator<Long>( "1.3.6.1.4.1.18060.0.4.1.1.2" )
047        {
048            private static final long serialVersionUID = 4048791282048841016L;
049    
050    
051            public int compare( Long o1, Long o2 )
052            {
053                if ( o1 == null )
054                {
055                    throw new IllegalArgumentException( I18n.err( I18n.ERR_525 ) );
056                } 
057                else if ( o2 == null )
058                {
059                    throw new IllegalArgumentException( I18n.err( I18n.ERR_526 ) );
060                }
061    
062                if ( o1 == ( long ) o2 )
063                {
064                    return 0;
065                }
066                
067                if ( o1 == ( long ) o2 )
068                {
069                    return 0;
070                }
071                
072                if ( o1 >= 0 )
073                {
074                    if ( o2 >= 0 )
075                    {
076                        return ( o1 > ( long ) o2 ) ? 1 : -1;
077                    }
078                    else
079                    {
080                        return -1;
081                    }
082                }
083                else if ( o2 >= 0 )
084                {
085                    return 1;
086                }
087                else
088                {
089                    return ( o1 < ( long ) o2 ) ? -1 : 1;
090                }
091            }
092        };
093    
094    
095        private static final SerializableComparator<String> STRING_COMPARATOR =
096                new SerializableComparator<String>( "1.3.6.1.4.1.18060.0.4.1.1.3" )
097        {
098            private static final long serialVersionUID = 3258689922792961845L;
099    
100    
101            public int compare( String o1, String o2 )
102            {
103                return STRCOMP.compare( o1, o2 );
104            }
105        };
106    
107    
108        protected final JdbmTable<String,String> adminTbl;
109    
110    
111        /**
112         * Creates the master table using JDBM B+Trees for the backing store.
113         *
114         * @param recMan the JDBM record manager
115         * @param schemaManager the schema mamanger
116         * @throws Exception if there is an error opening the Db file.
117         */
118        public JdbmMasterTable( RecordManager recMan, SchemaManager schemaManager ) throws Exception
119        {
120            super( schemaManager, DBF, recMan, LONG_COMPARATOR, LongSerializer.INSTANCE, new ServerEntrySerializer( schemaManager ) );
121            adminTbl = new JdbmTable<String,String>( schemaManager, "admin", recMan, STRING_COMPARATOR, null, null );
122            String seqValue = adminTbl.get( SEQPROP_KEY );
123    
124            if ( null == seqValue )
125            {
126                adminTbl.put( SEQPROP_KEY, "0" );
127            }
128            
129            LONG_COMPARATOR.setSchemaManager( schemaManager );
130            STRING_COMPARATOR.setSchemaManager( schemaManager );
131        }
132    
133    
134        protected JdbmMasterTable( RecordManager recMan, SchemaManager schemaManager, String dbName, Serializer serializer ) throws Exception
135        {
136            super( schemaManager, DBF, recMan, LONG_COMPARATOR, LongSerializer.INSTANCE, serializer );
137            adminTbl = new JdbmTable<String,String>( schemaManager, dbName, recMan, STRING_COMPARATOR, null, null );
138            String seqValue = adminTbl.get( SEQPROP_KEY );
139    
140            if ( null == seqValue )
141            {
142                adminTbl.put( SEQPROP_KEY, "0" );
143            }
144        }
145    
146        /**
147         * Gets the ServerEntry from this MasterTable.
148         *
149         * @param id the Long id of the entry to retrieve.
150         * @return the ServerEntry with operational attributes and all.
151         * @throws Exception if there is a read error on the underlying Db.
152         */
153        public E get( Long id ) throws Exception
154        {
155            return super.get( id );
156        }
157    
158    
159        /**
160         * Puts the ServerEntry into this master table at an index
161         * specified by id.  Used both to create new entries and update existing
162         * ones.
163         *
164         * @param entry the ServerEntry w/ operational attributes
165         * @param id    the Long id of the entry to put
166         * @throws Exception if there is a write error on the underlying Db.
167         */
168        public void put( Long id, E entry ) throws Exception
169        {
170            super.put( id, entry );
171        }
172    
173    
174        /**
175         * Deletes a ServerEntry from the master table at an index specified by id.
176         *
177         * @param id the Long id of the entry to delete
178         * @throws Exception if there is a write error on the underlying Db
179         */
180        public void delete( Long id ) throws Exception
181        {
182            super.remove( id );
183        }
184    
185    
186        public Long getCurrentId() throws Exception
187        {
188            Long id;
189    
190            synchronized ( adminTbl )
191            {
192                id = new Long( adminTbl.get( SEQPROP_KEY ) );
193            }
194    
195            return id;
196        }
197    
198    
199        /**
200         * Get's the next value from this SequenceBDb.  This has the side-effect of
201         * changing the current sequence values permanently in memory and on disk.
202         * Master table sequence begins at BigInteger.ONE.  The BigInteger.ZERO is
203         * used for the fictitious parent of the suffix root entry.
204         *
205         * @return the current value incremented by one.
206         * @throws Exception if the admin table storing sequences cannot be
207         *                         read and written to.
208         */
209        public Long getNextId() throws Exception
210        {
211            Long nextVal;
212            Long lastVal;
213    
214            synchronized ( adminTbl )
215            {
216                lastVal = new Long( adminTbl.get( SEQPROP_KEY ) );
217                nextVal = lastVal + 1L;
218                adminTbl.put( SEQPROP_KEY, nextVal.toString() );
219            }
220    
221            return nextVal;
222        }
223    
224    
225        /**
226         * Gets a persistent property stored in the admin table of this MasterTable.
227         *
228         * @param property the key of the property to get the value of
229         * @return the value of the property
230         * @throws Exception when the underlying admin table cannot be read
231         */
232        public String getProperty( String property ) throws Exception
233        {
234            synchronized ( adminTbl )
235            {
236                return adminTbl.get( property );
237            }
238        }
239    
240    
241        /**
242         * Sets a persistent property stored in the admin table of this MasterTable.
243         *
244         * @param property the key of the property to set the value of
245         * @param value    the value of the property
246         * @throws Exception when the underlying admin table cannot be writen
247         */
248        public void setProperty( String property, String value ) throws Exception
249        {
250            synchronized ( adminTbl )
251            {
252                adminTbl.put( property, value );
253            }
254        }
255    }