Package org.helidb.impl.txn.log

Source Code of org.helidb.impl.txn.log.LoggingTransactionalDatabase

/* HeliDB -- A simple database for Java, http://www.helidb.org
* Copyright (C) 2008, 2009 Karl Gustafsson
*
* This file is a part of HeliDB.
*
* HeliDB is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeliDB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.helidb.impl.txn.log;

import java.util.concurrent.locks.Lock;

import org.entityfs.EFile;
import org.entityfs.RandomAccess;
import org.entityfs.ReadWritableFile;
import org.entityfs.support.io.RandomAccessMode;
import org.entityfs.support.log.LogAdapterHolder;
import org.helidb.backend.DatabaseBackend;
import org.helidb.impl.txn.AbstractTransactionalDatabase;
import org.helidb.impl.txn.SharedReadLockReadOnlyTxnCollaborator;
import org.helidb.lang.serializer.Serializer;
import org.helidb.txn.TransactionCollaborator;

/**
* This {@link org.helidb.Database} implementation keeps a rollback log for
* read/write transactions. If the transaction is rolled back the rollback log
* is replayed to restore the database state. The rollback log is also used for
* restoring the database state when a new database object is created after the
* old one has crashed.
* <p>
* Read/write transactions hold an exclusive write lock on the entire database.
* Read only transactions hold a shared read lock that can be shared with other
* read only transactions.
* <p>
* Since the database uses its own locking, the database and log files should
* not be in a locking file system.
* <p>
* ACID:ity is guaranteed in the following way:
* <dl>
* <dt>Atomicity</dt>
* <dd>When a read/write transaction is rolled back, its rollback log is played
* back to restore the database to the state it had when the transaction
* started. When a read/write transaction is committed, the rollback log is
* discarded.</dd>
* <dt>Consistency</dt>
* <dd>If a transaction is committed, all its changes are already persisted in
* the database. If it is rolled back, its rollback log is played back to
* restore the database state. If the database crashes during the transaction,
* the rollback log can be used to restore its state.</dd>
* <dt>Isolation</dt>
* <dd>Isolation is achieved by locking the database pessimistically when
* writing to it.</dd>
* <dt>Durability</dt>
* <dd>When the transaction is committed, the contents of the database file is
* updated.</dd>
* <p>
* This database is thread safe.
* <p>
* The {@code equals} and {@code hashCode} methods are not implemented according
* to the contract in {@link java.util.Map}. See
* {@link AbstractTransactionalDatabase}.
* @author Karl Gustafsson
* @since 1.0
* @param <K> The type of the keys in the database.
* @param <V> The type of the values in the database.
* @param <P> The type of positions used by the
* {@link org.helidb.backend.DatabaseBackend} to locate records.
*/
public class LoggingTransactionalDatabase<K, V, P> extends AbstractTransactionalDatabase<K, V, P>
{
  private final DatabaseBackend<K, V, P> m_backend;
  // private final DatabaseFiles m_backendFiles;
  private final ReadWritableFile m_logFile;
  private final Serializer<K> m_keySerializer;
  private final Serializer<V> m_valueSerializer;

  /**
   * Constructor.
   * <p>
   * The {@link LoggingTransactionalDatabaseBuilder} may be more convenient to
   * use than this constructor.
   * @param backend The database backend.
   * @param logFile The rollback log file. If it is not empty, it is replayed
   * to restore the database state.
   * @param keySerializer Serializer for database keys.
   * @param valueSerializer Serializer for database values.
   * @param lah A log adapter holder.
   */
  public LoggingTransactionalDatabase(DatabaseBackend<K, V, P> backend, ReadWritableFile logFile, Serializer<K> keySerializer, Serializer<V> valueSerializer, LogAdapterHolder lah)
  {
    super(lah);

    // Null checks
    backend.getClass();
    // backendFiles.getClass();
    logFile.getClass();
    keySerializer.getClass();
    valueSerializer.getClass();

    if ((logFile instanceof EFile) && ((EFile) logFile).getFileSystem().isLocking())
    {
      throw new IllegalArgumentException("The log file " + logFile + " is in a locking file system. Locking file systems are not supported by this database");
    }

    m_backend = backend;
    // m_backendFiles = backendFiles;
    m_logFile = logFile;
    m_keySerializer = keySerializer;
    m_valueSerializer = valueSerializer;

    if (logFile.getSize() > 0)
    {
      lah.logWarning("Rollback transaction log not empty. Restoring database state to last checkpoint.");
      boolean successful = false;
      getLock().writeLock().lock();
      try
      {
        TransactionCollaborator<K, V, P> collab = createReadWriteCollaborator(getLock().writeLock());
        collab.rollback();
        successful = true;
      }
      finally
      {
        if (!successful)
        {
          getLock().writeLock().unlock();
        }
      }
    }
  }

  @Override
  protected TransactionCollaborator<K, V, P> createReadOnlyCollaborator(Lock readLock)
  {
    return new SharedReadLockReadOnlyTxnCollaborator<K, V, P>(m_backend, readLock, getLogAdapterHolder());
  }

  @Override
  protected TransactionCollaborator<K, V, P> createReadWriteCollaborator(Lock writeLock)
  {
    RandomAccess ra = m_logFile.openForRandomAccess(RandomAccessMode.READ_WRITE);
    return new LoggingReadWriteTxnCollaborator<K, V, P>(this, m_backend, ra, writeLock, m_keySerializer, m_valueSerializer, getCloseObservable(), getLogAdapterHolder());
  }

  @Override
  protected void closeBackend()
  {
    m_backend.close();
  }
}
TOP

Related Classes of org.helidb.impl.txn.log.LoggingTransactionalDatabase

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.