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 */
020package org.apache.directory.server.core.partition.impl.btree.mavibot;
021
022
023import java.io.DataInputStream;
024import java.io.DataOutputStream;
025import java.io.IOException;
026import java.io.RandomAccessFile;
027import java.nio.charset.StandardCharsets;
028
029import org.apache.directory.api.ldap.model.entry.DefaultEntry;
030import org.apache.directory.api.ldap.model.entry.Entry;
031import org.apache.directory.api.ldap.model.ldif.LdifEntry;
032import org.apache.directory.api.ldap.model.ldif.LdifReader;
033import org.apache.directory.api.ldap.model.name.Dn;
034import org.apache.directory.api.ldap.model.schema.SchemaManager;
035import org.apache.directory.mavibot.btree.Tuple;
036import org.apache.directory.mavibot.btree.util.TupleReaderWriter;
037import org.slf4j.Logger;
038import org.slf4j.LoggerFactory;
039
040
041/**
042 * TODO LdifTupleReaderWriter.
043 *
044 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
045 */
046public class LdifTupleReaderWriter<E> implements TupleReaderWriter<Dn, E>
047{
048
049    private LdifReader reader = null;
050
051    private static final Logger LOG = LoggerFactory.getLogger( LdifTupleReaderWriter.class );
052
053    private String ldifFile;
054    
055    private RandomAccessFile raf;
056    
057    private SchemaManager schemaManager;
058    
059    public LdifTupleReaderWriter( String ldifFile, SchemaManager schemaManager )
060    {
061        this.ldifFile = ldifFile;
062        this.schemaManager = schemaManager;
063        
064        try
065        {
066            raf = new RandomAccessFile( ldifFile, "r" );
067        }
068        catch ( Exception e )
069        {
070            throw new RuntimeException( e );
071        }
072    }
073    
074
075    @Override
076    public Tuple<Dn, E> readSortedTuple( DataInputStream in )
077    {
078        try
079        {
080            if ( in.available() > 0 )
081            {
082                Tuple<Dn, E> tuple = new Tuple<>();
083                tuple.setKey( new Dn( in.readUTF() ) );
084                
085                String[] tokens = in.readUTF().split( ":" );
086                
087                long offset = Long.parseLong( tokens[0] );
088                
089                int length = Integer.parseInt( tokens[1] );
090                
091                raf.seek( offset );
092                
093                byte[] data = new byte[length];
094                
095                raf.read( data, 0, length );
096                
097                try ( LdifReader ldifReader = new LdifReader() )
098                {
099                    LdifEntry ldifEntry = ldifReader.parseLdif( new String( data, StandardCharsets.UTF_8 ) ).get( 0 );
100                    Entry entry = new DefaultEntry( schemaManager, ldifEntry.getEntry() );
101    
102                    tuple.setValue( ( E ) entry );
103                }
104                
105                return tuple;
106            }
107        }
108        catch ( Exception e )
109        {
110            LOG.error( "Failed to read a sorted tuple", e );
111        }
112        
113        return null;
114    }
115
116
117    @Override
118    public Tuple<Dn, E> readUnsortedTuple( DataInputStream in )
119    {
120        try
121        {
122            if ( reader == null )
123            {
124                reader = new LdifReader( in );
125            }
126        }
127        catch ( Exception e )
128        {
129            String msg = "Failed to open the LDIF input stream";
130            LOG.error( msg, e );
131
132            throw new RuntimeException( msg, e );
133        }
134
135        Tuple<Dn, E> t = null;
136
137        if ( reader.hasNext() )
138        {
139            LdifEntry ldifEntry = reader.next();
140
141            if ( ldifEntry == null )
142            {
143                throw new IllegalStateException(
144                    "Received null entry while parsing, check the LDIF file for possible incorrect/corrupted entries" );
145            }
146
147            t = new Tuple<>();
148
149            t.setKey( ldifEntry.getDn() );
150            t.setValue( ( E ) ( ldifEntry.getOffset() + ":" + ldifEntry.getLengthBeforeParsing() ) );
151        }
152
153        return t;
154    }
155
156
157    @Override
158    public void storeSortedTuple( Tuple<Dn, E> t, DataOutputStream out ) throws IOException
159    {
160        out.writeUTF( t.getKey().getName() );
161        out.writeUTF( ( String ) t.getValue() );
162    }
163
164}