Package org.xtreemfs.babudb.api.dev.transaction

Source Code of org.xtreemfs.babudb.api.dev.transaction.TransactionInternal

/*
* Copyright (c) 2011, Jan Stender, Bjoern Kolbeck, Mikael Hoegqvist,
*                     Felix Hupfeld, Felix Langner, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.babudb.api.dev.transaction;

import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import org.xtreemfs.babudb.api.database.DatabaseRequestResult;
import org.xtreemfs.babudb.api.dev.transaction.OperationInternal;
import org.xtreemfs.babudb.api.exception.BabuDBException;
import org.xtreemfs.babudb.api.index.ByteRangeComparator;
import org.xtreemfs.babudb.api.transaction.Operation;
import org.xtreemfs.babudb.api.transaction.Transaction;
import org.xtreemfs.babudb.lsmdb.BabuDBTransaction;
import org.xtreemfs.babudb.lsmdb.InsertRecordGroup;
import org.xtreemfs.babudb.lsmdb.LSMDatabase;
import org.xtreemfs.babudb.snapshots.SnapshotConfig;
import org.xtreemfs.foundation.buffer.ReusableBuffer;
import org.xtreemfs.foundation.logging.Logging;

/**
* Internal interface for BabuDB's lightwight transactions.
*
* @author flangner
* @since 05/06/2011
*/
public abstract class TransactionInternal extends LinkedList<OperationInternal>
        implements Transaction, Iterable<OperationInternal> {
    private static final long serialVersionUID = 1383031301195486005L;
   
    private Map<String, DatabaseRequestResult<AtomicBoolean>> databaseLockFutureMap = null;
   
    /* (non-Javadoc)
     * @see org.xtreemfs.babudb.api.transaction.Transaction#createSnapshot(java.lang.String,
     *          org.xtreemfs.babudb.snapshots.SnapshotConfig)
     */
    @Override
    public abstract TransactionInternal createSnapshot(String databaseName, SnapshotConfig config);
   
    /* (non-Javadoc)
     * @see org.xtreemfs.babudb.api.transaction.Transaction#deleteSnapshot(java.lang.String,
     *          java.lang.String)
     */
    @Override
    public abstract TransactionInternal deleteSnapshot(String databaseName, String snapshotName);
       
    /* (non-Javadoc)
     * @see org.xtreemfs.babudb.api.transaction.Transaction#createDatabase(java.lang.String, int)
     */
    @Override
    public abstract TransactionInternal createDatabase(String databaseName, int numIndices);
   
    /* (non-Javadoc)
     * @see org.xtreemfs.babudb.api.transaction.Transaction#createDatabase(java.lang.String, int,
     *          org.xtreemfs.babudb.api.index.ByteRangeComparator[])
     */
    @Override
    public abstract TransactionInternal createDatabase(String databaseName, int numIndices,
            ByteRangeComparator[] comparators);
   
    /* (non-Javadoc)
     * @see org.xtreemfs.babudb.api.transaction.Transaction#copyDatabase(java.lang.String,
     *          java.lang.String)
     */
    @Override
    public abstract TransactionInternal copyDatabase(String sourceName, String destinationName);
   
    /* (non-Javadoc)
     * @see org.xtreemfs.babudb.api.transaction.Transaction#deleteDatabase(java.lang.String)
     */
    @Override
    public abstract TransactionInternal deleteDatabase(String databaseName);
   
    /* (non-Javadoc)
     * @see org.xtreemfs.babudb.api.transaction.Transaction#insertRecord(java.lang.String, int,
     *          byte[], byte[])
     */
    @Override
    public abstract TransactionInternal insertRecord(String databaseName, int indexId, byte[] key,
            byte[] value);
   
    /* (non-Javadoc)
     * @see org.xtreemfs.babudb.api.transaction.Transaction#deleteRecord(java.lang.String, int,
     *          byte[])
     */
    @Override
    public abstract TransactionInternal deleteRecord(String databaseName, int indexId, byte[] key);
   
    /* (non-Javadoc)
     * @see java.util.AbstractCollection#toString()
     */
    @Override
    public abstract String toString();
   
    /**
     * There are 3 kinds of database manipulating operations covered by transactions:
     * <ol>
     * <li>database create/copy/delete
     * <li>snapshots
     * <li>database key-value inserts/deletes
     * </ol>
     * These form different level of isolation that have to be respected by the replication for
     * example. This method aggregates all occurrences of operation to make it possible to
     * comprehend the level of restriction for this transaction.
     *
     * @return an aggregation of all types of operation occurring in this transaction.
     */
    public final byte aggregateOperationTypes() {
       
        // initial value, if transaction contains no operation
        byte result = 0;
        for (Operation op : this) {
            result |= 1 << op.getType();
        }
        return result;
    }
   
    /**
     * @return a set of names of databases affected by this transaction.
     */
    public final Set<String> databasesAffected() {
       
        Set<String> result = new HashSet<String>();
        for (Operation op : this) {
            result.add(op.getDatabaseName());
        }
       
        return result;
    }
   
    /**
     * Mapping of databases to lock futures for the worker threads being responsible for them.
     *
     * @param databaseLockFutureMap - a map of lock futures for database workers affected by this
     *                           transaction.
     */
    public final synchronized void updateWorkerLocks(
            Map<String, DatabaseRequestResult<AtomicBoolean>> databaseLockFutureMap) {
       
        this.databaseLockFutureMap = databaseLockFutureMap;
    }
   
    /**
     * Method to lock the worker responsible for database with databaseName.
     *
     * @param databaseName
     * @throws BabuDBException if the lock could not have been acquired.
     */
    public final synchronized void lockResponsibleWorker(String databaseName)
            throws BabuDBException {
       
        if (databaseLockFutureMap != null) {
            DatabaseRequestResult<AtomicBoolean> lockFuture =
                databaseLockFutureMap.get(databaseName);
           
            if (lockFuture != null) {
                lockFuture.get();
            }
        }
    }
   
    /**
     * Method to unlock the worker threads that have been locked during this transaction.
     */
    public final synchronized void unlockWorkers() {
        if (databaseLockFutureMap != null) {
            Set<DatabaseRequestResult<AtomicBoolean>> lockFutures =
                new HashSet<DatabaseRequestResult<AtomicBoolean>>(databaseLockFutureMap.values());
            for (DatabaseRequestResult<AtomicBoolean> lockFuture : lockFutures) {
               
                try {
                    final AtomicBoolean workerLock = lockFuture.get();
                    synchronized (workerLock) {
                        workerLock.set(false);
                        workerLock.notify();
                    }
                } catch (BabuDBException be) {
                    Logging.logMessage(Logging.LEVEL_DEBUG, this, "The worker lock could not have" +
                        " been acquired for unlock.");
                }
            }
        }
    }
   
    /**
     * Counterpart to aggregateOperationTypes. Proves existence of given type.
     *
     * @param aggregate
     * @param type
     * @return true if the transaction with the aggregate of operation types contains at least one
     *         operation of <code>type</code>, false otherwise.
     */
    public final static boolean containsOperationType(byte aggregate, byte type) {
        return ((aggregate >>> type) & 1) == 1;
    }
   
    /**
     * Add a new group insert operation to this transaction.
     *
     * @param databaseName - the name of the database.
     * @param irg - insert group.
     *           
     * @return the resulting Transaction.
     */
    public abstract TransactionInternal insertRecordGroup(String databaseName,
            InsertRecordGroup irg);
   
    /**
     * Add a new group insert operation to this transaction.
     *
     * @param databaseName - the name of the database.
     * @param db - where the group has to be inserted.
     * @param irg - insert group.
     *           
     * @return the resulting Transaction.
     */
    public abstract TransactionInternal insertRecordGroup(String databaseName,
            InsertRecordGroup irg, LSMDatabase db);
       
    /**
     * Adds a custom operation to the transaction.
     *
     * @param op
     */
    public abstract TransactionInternal addOperation(OperationInternal op);
   
    /**
     * @return the size of this transaction in bytes if serialized.
     * @throws IOException
     */
    public abstract int getSize() throws IOException;
   
    /**
     * Serializes the transaction to a buffer.
     * <p>
     * The following format is used:
     * <ol>
     * <li> length of the list of all database names (4 bytes)
     * <li> all database names (4 bytes for the length + #chars)
     * <li> length of the list of operations (4 bytes)
     * <li> all operations (variable size)
     * </ol>
     *
     * Resulting buffer needs to be flip()-ed before usage.
     * </p>
     *
     * @param buffer the buffer
     * @throws IOException
     *
     * @return the buffer.
     */
    public abstract ReusableBuffer serialize(ReusableBuffer buffer) throws IOException;
   
    /**
     * Drops operations from position on. reason for dropping the operations.
     *
     * @param position
     */
    public abstract void cutOfAt(int position, BabuDBException reason);
   
    /**
     * @return an exception describing irregularities that occurred during execution, or null, if
     *         this transaction was executed correctly.
     */
    public abstract BabuDBException getIrregularities();
   
    /**
     * Deserializes the transaction.
     *
     * @param buffer
     * @return the deserialized transaction.
     * @throws IOException
     */
    public final static TransactionInternal deserialize(ReusableBuffer buffer) throws IOException {
       
        BabuDBTransaction txn = new BabuDBTransaction();
       
        // check whether the transaction used to be empty
        if (buffer.remaining() > 0 || buffer.limit() > 0) {
           
            assert(buffer.remaining() > 0);
           
            // deserialize the list of database names
            int length = buffer.getInt();
            String[] dbNames = new String[length];
            for (int i = 0; i < length; i++) {
                byte[] bytes = new byte[buffer.getInt()];
                buffer.get(bytes);
                dbNames[i] = new String(bytes);
            }
           
            // deserialize the list of operations
            length = buffer.getInt();
            for (int i = 0; i < length; i++) {
                txn.addOperation(OperationInternal.deserialize(dbNames, buffer));
            }
        }
        return txn;
    }
}
TOP

Related Classes of org.xtreemfs.babudb.api.dev.transaction.TransactionInternal

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.