Package org.fusesource.hawtdb.api

Source Code of org.fusesource.hawtdb.api.PageFileFactory

/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fusesource.hawtdb.api;

import java.io.*;

import org.fusesource.hawtbuf.AsciiBuffer;
import org.fusesource.hawtbuf.Buffer;
import org.fusesource.hawtbuf.DataByteArrayInputStream;
import org.fusesource.hawtbuf.DataByteArrayOutputStream;
import org.fusesource.hawtdb.internal.io.MemoryMappedFileFactory;
import org.fusesource.hawtdb.internal.page.ExtentInputStream;
import org.fusesource.hawtdb.internal.page.ExtentOutputStream;
import org.fusesource.hawtdb.internal.page.HawtPageFile;
import org.fusesource.hawtdb.internal.util.Ranges;

/**
* A factory to create PageFile objects.
*
* @author <a href="http://hiramchirino.com">Hiram Chirino</a>
*/
public class PageFileFactory {

    static final AsciiBuffer HAWT_DB_PAGE_FILE_MAGIC;
    static {
        try {
            HAWT_DB_PAGE_FILE_MAGIC = new AsciiBuffer("HawtDB/PageFile/1.0".getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    private final MemoryMappedFileFactory mappedFileFactory = new MemoryMappedFileFactory();
    private HawtPageFile pageFile;

    protected int headerSize = 0;
    protected short pageSize = 512;
    protected int maxPages = Integer.MAX_VALUE;
    protected boolean storeFreePages = true;

    public PageFile getPageFile() {
        return pageFile;
    }

    /**
     * Opens the PageFile object. A subsequent call to {@link #getPageFile()} will return
     * the opened PageFile.
     */
    public void open() {

        if (pageFile == null) {
            if( pageSize <= 0 ) {
                throw new IllegalArgumentException("pageSize property must be greater than 0");
            }
            if( maxPages <= 0 ) {
                throw new IllegalArgumentException("maxPages property must be greater than 0");
            }
            if( headerSize < 0 ) {
                throw new IllegalArgumentException("headerSize property cannot be negative.");
            }
            if( storeFreePages && headerSize==0 ) {
                headerSize = 512;
            }
            try {

                boolean recover = storeFreePages && getFile().exists() && getFile().length() > 512;

                try {
                    mappedFileFactory.open();
                } catch (IOException e) {
                    throw new IOPagingException(e);
                }

                int freePageExtent = -1;
                if( storeFreePages ) {
                    if( recover ) {
                        Buffer header = new Buffer(512);
                        mappedFileFactory.getMemoryMappedFile().read(0, header);
                        DataByteArrayInputStream his = new DataByteArrayInputStream(header);

                        Buffer magic = new Buffer(HAWT_DB_PAGE_FILE_MAGIC.length());
                        his.readFully(magic.data, magic.offset, magic.length());
                        if( !magic.ascii().equals(HAWT_DB_PAGE_FILE_MAGIC)) {
                            throw new IOPagingException("File's magic does not match expected value");
                        }
                        freePageExtent = his.readInt();
                        headerSize = his.readInt();
                        pageSize = his.readShort();
                    } else {
                    }
                }

                pageFile = new HawtPageFile(mappedFileFactory.getMemoryMappedFile(), pageSize, headerSize, maxPages, storeFreePages);

                if( freePageExtent >=0 ) {
                    DataInputStream is = new DataInputStream(new ExtentInputStream(pageFile, freePageExtent));
                    pageFile.allocator().getFreeRanges().readExternal(is);
                    is.close();
                }

                if( pageFile.storeFreePages && !isReadOnly() ) {
                    writePageFileHeader(-1);
                }


            } catch (IOException e) {
                throw new IOPagingException(e);
            }
        }
    }

    private void writePageFileHeader(int freePageExtent) throws IOException {
        DataByteArrayOutputStream os = new DataByteArrayOutputStream();
        os.write(HAWT_DB_PAGE_FILE_MAGIC);
        os.writeInt(freePageExtent);
        os.writeInt(headerSize);
        os.writeShort(pageSize);
        os.close();
        mappedFileFactory.getMemoryMappedFile().write(0, os.toBuffer());
    }

    /**
     * Closes the previously opened PageFile object.  Subsequent calls to
     * {@link PageFileFactory#getPageFile()} will return null.
     */
    public void close() throws IOException {
        if (pageFile != null) {
            pageFile.flush();
            if( !isReadOnly() && pageFile.storeFreePages ) {
                Ranges ranges = pageFile.allocator().getFreeRanges().copy();
                int freePageExtent = pageFile.alloc();
                DataOutputStream os = new DataOutputStream(new ExtentOutputStream(pageFile, freePageExtent, (short)1, (short)200));
                ranges.writeExternal(os);
                os.close();
                writePageFileHeader(freePageExtent);
            }
            pageFile.flush();
            pageFile = null;
        }       
        mappedFileFactory.close();
    }

    public int getHeaderSize() {
        return headerSize;
    }
    public void setHeaderSize(int headerSize) {
        this.headerSize = headerSize;
    }

    public short getPageSize() {
        return pageSize;
    }
    public void setPageSize(short pageSize) {
        this.pageSize = pageSize;
    }

    public int getMaxPages() {
        return maxPages;
    }
    public void setMaxPages(int maxPages) {
        this.maxPages = maxPages;
    }
    public void setMaxFileSize(long size) {
        setMaxPages( (int)((size-getHeaderSize())/getPageSize()) );
    }
   
    public File getFile() {
        return mappedFileFactory.getFile();
    }

    public int getMappingSegementSize() {
        return mappedFileFactory.getMappingSegementSize();
    }

    public void setFile(File file) {
        mappedFileFactory.setFile(file);
    }

    public void setMappingSegementSize(int mappingSegementSize) {
        mappedFileFactory.setMappingSegementSize(mappingSegementSize);
    }

    public boolean isStoreFreePages() {
        return storeFreePages;
    }

    public void setStoreFreePages(boolean storeFreePages) {
        this.storeFreePages = storeFreePages;
    }

    public boolean isReadOnly() {
        return mappedFileFactory.isReadOnly();
    }

    public void setReadOnly(boolean readOnly) {
        mappedFileFactory.setReadOnly(readOnly);
    }
}
TOP

Related Classes of org.fusesource.hawtdb.api.PageFileFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.