All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tech.sourced.siva.IndexReader Maven / Gradle / Ivy

There is a newer version: 0.1.3
Show newest version
package tech.sourced.siva;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.file.attribute.FileTime;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

public class IndexReader {
    private static final int INDEX_VERSION = 1;
    private static final int INDEX_FOOTER_SIZE = 24;
    private static final byte[] INDEX_SIGNATURE = {'I', 'B', 'A'};

    private final RandomAccessFile sivaFile;
    private final String sivaFileName;

    IndexReader(RandomAccessFile sivaFile, String sivaFileName) {
        this.sivaFile = sivaFile;
        this.sivaFileName = sivaFileName;
    }

    /**
     * getFilteredIndex will return an index with all the deleted or modified elements already filtered.
     *
     * @return Index with the last entry of each file. Delete files will not appear in this index.
     * @throws SivaException If some error happens reading or validating the index.
     */
    public synchronized Index getFilteredIndex() throws SivaException {
        return this.readIndex(new FilteredIndex());
    }

    /**
     * getCompleteIndex will return all the entries into the siva file, even modified or delete files.
     *
     * @return Index with all the entries in the siva file.
     * @throws SivaException If some error happens reading or validating the index.
     */
    public synchronized Index getCompleteIndex() throws SivaException {
        return this.readIndex(new CompleteIndex());
    }

    private Index readIndex(BaseIndex index) throws SivaException {
        try {
            // go to the end of the file
            this.sivaFile.seek(this.sivaFile.length());
            while (true) {
                if (this.sivaFile.getFilePointer() == 0) {
                    break;
                }

                long block = this.sivaFile.getFilePointer();

                this.sivaFile.seek(this.sivaFile.getFilePointer() - INDEX_FOOTER_SIZE);
                IndexFooter indexFooter = this.readIndexFooter();
                this.sivaFile.seek(this.sivaFile.getFilePointer() - INDEX_FOOTER_SIZE - indexFooter.getIndexSize());

                this.readSignature();
                this.readIndexVersion();

                for (int i = 0; i < indexFooter.getEntryCount(); i++) {
                    index.add(this.readEntry(indexFooter, block));
                }

                index.endIndexBlock();

                // go to the next index
                this.sivaFile.seek(this.sivaFile.getFilePointer() - indexFooter.getBlockSize() + INDEX_FOOTER_SIZE);
            }

            return index;
        } catch (IOException e) {
            throw new SivaException("Error reading index of " + this.sivaFileName + " file.", e);
        }
    }

    private IndexEntry readEntry(IndexFooter indexFooter, long block) throws IOException {
        int entryNameLength = this.sivaFile.readInt();
        byte[] name = new byte[entryNameLength];
        this.sivaFile.readFully(name);

        int fileMode = this.sivaFile.readInt();

        FileTime modificationTime = FileTime.from(this.sivaFile.readLong(), TimeUnit.NANOSECONDS);

        long fileOffset = this.sivaFile.readLong();
        long fileSize = this.sivaFile.readLong();
        int crc32 = this.sivaFile.readInt();

        Flag flag = Flag.fromInteger(this.sivaFile.readInt());

        return new IndexEntry(
                new String(name),
                modificationTime,
                FileModeUtils.posixFilePermissions(fileMode),
                flag,
                fileOffset,
                fileSize,
                crc32,
                (block - indexFooter.getBlockSize()) + fileOffset
        );
    }

    private IndexFooter readIndexFooter() throws IOException {
        return new IndexFooter(
                this.sivaFile.readInt(),
                this.sivaFile.readLong(),
                this.sivaFile.readLong(),
                this.sivaFile.readInt()
        );
    }

    private void readIndexVersion() throws IOException, SivaException {
        int version = this.sivaFile.readByte();
        if (version != INDEX_VERSION) {
            throw new SivaException("Invalid index version at " + this.sivaFileName + " file.");
        }
    }

    private void readSignature() throws IOException, SivaException {
        byte[] sig = new byte[3];
        this.sivaFile.readFully(sig);
        if (!Arrays.equals(sig, INDEX_SIGNATURE)) {
            throw new SivaException("Invalid index signature at " + this.sivaFileName + " file.");
        }
    }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy