Package uk.ac.open.kmi.smartproducts.sesame.sail.datastore

Source Code of uk.ac.open.kmi.smartproducts.sesame.sail.datastore.IDFile

/*
* Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2010.
*
* Licensed under the Aduna BSD-style license.
*/
package uk.ac.open.kmi.smartproducts.sesame.sail.datastore;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;

import info.aduna.io.NioFile;

/**
* Class supplying access to an ID file. An ID file maps IDs (integers >= 1)
* to file pointers (long integers). There is a direct correlation between IDs
* and the position at which the file pointers are stored; the file pointer for
* ID X is stored at position 8*X.
*
* @author Arjohn Kampman
*/
public class IDFile {

  /*-----------*
   * Constants *
   *-----------*/

  /**
   * Magic number "Native ID File" to detect whether the file is actually an ID
   * file. The first three bytes of the file should be equal to this magic
   * number.
   */
  private static final byte[] MAGIC_NUMBER = new byte[] { 'n', 'i', 'f' };

  /**
   * File format version, stored as the fourth byte in ID files.
   */
  private static final byte FILE_FORMAT_VERSION = 1;

  /**
   * The size of the file header in bytes. The file header contains the
   * following data: magic number (3 bytes) file format version (1 byte) and 4
   * dummy bytes to align data at 8-byte offsets.
   */
  private static final long HEADER_LENGTH = 8;

  private static final long ITEM_SIZE = 8L;

  /*-----------*
   * Variables *
   *-----------*/

  private final NioFile nioFile;

  private final boolean forceSync;

  /*--------------*
   * Constructors *
   *--------------*/

  public IDFile(File file)
    throws IOException
  {
    this(file, false);
  }

  public IDFile(File file, boolean forceSync)
    throws IOException
  {
    this.nioFile = new NioFile(file);
    this.forceSync = forceSync;

    if (nioFile.size() == 0L) {
      // Empty file, write header
      nioFile.writeBytes(MAGIC_NUMBER, 0);
      nioFile.writeByte(FILE_FORMAT_VERSION, 3);
      nioFile.writeBytes(new byte[] { 0, 0, 0, 0 }, 4);

      sync();
    }
    else if (nioFile.size() < HEADER_LENGTH) {
      throw new IOException("File too small to be a compatible ID file");
    }
    else {
      // Verify file header
      if (!Arrays.equals(MAGIC_NUMBER, nioFile.readBytes(0, MAGIC_NUMBER.length))) {
        throw new IOException("File doesn't contain compatible ID records");
      }

      byte version = nioFile.readByte(MAGIC_NUMBER.length);
      if (version > FILE_FORMAT_VERSION) {
        throw new IOException("Unable to read ID file; it uses a newer file format");
      }
      else if (version != FILE_FORMAT_VERSION) {
        throw new IOException("Unable to read ID file; invalid file format version: " + version);
      }
    }

  }

  /*---------*
   * Methods *
   *---------*/

  public final File getFile() {
    return nioFile.getFile();
  }

  /**
   * Gets the largest ID that is stored in this ID file.
   *
   * @return The largest ID, or <tt>0</tt> if the file does not contain any
   *         data.
   * @throws IOException
   *         If an I/O error occurs.
   */
  public int getMaxID()
    throws IOException
  {
    return (int)(nioFile.size() / ITEM_SIZE) - 1;
  }

  /**
   * Stores the offset of a new data entry, returning the ID under which is
   * stored.
   */
  public int storeOffset(long offset)
    throws IOException
  {
    long fileSize = nioFile.size();
    nioFile.writeLong(offset, fileSize);
    return (int)(fileSize / ITEM_SIZE);
  }

  /**
   * Sets or updates the stored offset for the specified ID.
   *
   * @param id
   *        The ID to set the offset for, must be larger than 0.
   * @param offset
   *        The (new) offset for the specified ID.
   */
  public void setOffset(int id, long offset)
    throws IOException
  {
    assert id > 0 : "id must be larger than 0, is: " + id;
    nioFile.writeLong(offset, ITEM_SIZE * id);
  }

  /**
   * Gets the offset of the data entry with the specified ID.
   *
   * @param id
   *        The ID to get the offset for, must be larger than 0.
   * @return The offset for the ID.
   */
  public long getOffset(int id)
    throws IOException
  {
    assert id > 0 : "id must be larger than 0, is: " + id;
    return nioFile.readLong(ITEM_SIZE * id);
  }

  /**
   * Discards all stored data.
   *
   * @throws IOException
   *         If an I/O error occurred.
   */
  public void clear()
    throws IOException
  {
    nioFile.truncate(HEADER_LENGTH);
  }

  /**
   * Syncs any unstored data to the hash file.
   */
  public void sync()
    throws IOException
  {
    if (forceSync) {
      nioFile.force(false);
    }
  }

  /**
   * Closes the ID file, releasing any file locks that it might have.
   *
   * @throws IOException
   */
  public void close()
    throws IOException
  {
    nioFile.close();
  }
}
TOP

Related Classes of uk.ac.open.kmi.smartproducts.sesame.sail.datastore.IDFile

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.