Package com.alibaba.wasp.fserver.redo

Source Code of com.alibaba.wasp.fserver.redo.RedoLog

/**
* 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 com.alibaba.wasp.fserver.redo;

import com.alibaba.wasp.EntityGroupInfo;
import com.alibaba.wasp.meta.StorageTableNameBuilder;
import com.alibaba.wasp.plan.action.Primary;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.io.hfile.Compression.Algorithm;
import org.apache.hadoop.hbase.util.Bytes;

import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
* Wasp uses this class to support transaction feature.
*
*/
public class RedoLog extends Redo {

  public static final Log LOG = LogFactory.getLog(RedoLog.class);

  /** transaction table **/
  private HTable transcationTable;

  /** column family of transaction table **/
  private final byte[] fEntityValue = Bytes.toBytes("i"); // info

  /** info column name **/
  private final byte[] cEntityValue = Bytes.toBytes("i"); // info

  /** commit column name **/
  private final byte[] cCommit = Bytes.toBytes("c"); // commit

  private final byte[] emptyStringByte = Bytes.toBytes("");

  /** Uncommited is 0 **/
  private final byte[] unCommited = Bytes.toBytes(0);

  /** Commited is 1 **/
  private final byte[] commited = Bytes.toBytes(1);

  private WALEdit lastCommitedTransaction;

  protected BlockingQueue<WALEdit> editQueue = new LinkedBlockingQueue<WALEdit>(
      Runtime.getRuntime().availableProcessors() * 100);

  private boolean initlized = false;

  private volatile long maxTransactionID = Long.MIN_VALUE;

  /**
   * Default constructor.
   */
  public RedoLog(EntityGroupInfo egi, Configuration conf) throws IOException {
    super(egi, conf);
  }

  /**
   *
   * @see com.alibaba.wasp.fserver.redo.Redo#initlize()
   */
  public void initlize() throws IOException {
    HBaseAdmin admin = new HBaseAdmin(this.conf);
    String tTableName = StorageTableNameBuilder.buildTransactionTableName(egi
        .getEncodedName());
    if (!admin.tableExists(tTableName)) {
      HColumnDescriptor family = new HColumnDescriptor(fEntityValue);
      family.setCompressionType(Algorithm.GZ);
      HTableDescriptor tableDes = new HTableDescriptor(tTableName);
      tableDes.addFamily(family);
      admin.createTable(tableDes);
    }
    admin.close();
    this.transcationTable = new HTable(this.conf, tTableName);
    redo();
    this.initlized = true;
    if (lastCommitedTransaction != null) {
      maxTransactionID = lastCommitedTransaction.getT().getTransactionID();
    }
    if (editQueue.size() > 0) {
      maxTransactionID = editQueue.peek().getT().getTransactionID();
    }
    LOG.info("Init " + egi.toString() + " redolog, maxTransactionID = "
        + maxTransactionID);
  }

  /**
   *
   * @see com.alibaba.wasp.fserver.redo.Redo#append(com.alibaba.wasp.fserver.redo.Transaction)
   */
  @Override
  public void append(Primary action, Transaction t)
      throws NotInitlizedRedoException, RedoLogNotServingException, IOException {
    checkInit();
    if (maxTransactionID >= t.getTransactionID()) {
      throw new AlreadyExsitsTransactionIdException("TransactionId:"
          + t.getTransactionID() + " <=  lastAppendTransaction "
          + maxTransactionID);
    }
    byte[] rowKey = t.getKey();
    Put put = new Put(rowKey);
    put.add(fEntityValue, cEntityValue, t.getTransactionEntity());
    put.add(fEntityValue, cCommit, unCommited);
    if (!transcationTable.checkAndPut(t.getKey(), fEntityValue, cEntityValue,
        null, put)) {
      throw new AlreadyExsitsTransactionIdException("TransactionId:"
          + t.getTransactionID() + " already exsits.");
    }
    if (LOG.isDebugEnabled()) {
      LOG.debug("RedoLog Append Transaction:" + t.transactionID);
    }
    try {
      editQueue.put(new WALEdit(action, t));
    } catch (InterruptedException e) {
      throw new IOException(e);
    }
    maxTransactionID = t.getTransactionID();
  }

  /**
   *
   * @see com.alibaba.wasp.fserver.redo.Redo#commit(com.alibaba.wasp.fserver.redo.Transaction)
   */
  @Override
  public boolean commit(WALEdit edit) throws NotInitlizedRedoException,
      RedoLogNotServingException, AlreadyCommitTransactionException {
    checkInit();
    Transaction t = edit.getT();
    byte[] rowKey = t.getKey();
    Put put = new Put(rowKey);
    put.add(fEntityValue, cCommit, commited);
    try {
      boolean success = transcationTable.checkAndPut(t.getKey(), fEntityValue,
          cCommit, unCommited, put);
      if (!success) {
        throw new AlreadyCommitTransactionException(t);
      }
      lastCommitedTransaction = edit;
      t.commit(t.getTransactionID());
      if (LOG.isDebugEnabled()) {
        LOG.debug("RedoLog Commit Transaction:" + t.transactionID);
      }
      return true;
    } catch (IOException e) {
      LOG.error("Failed to commit transaction:" + t.getKeyStr(), e);
      return false;
    }
  }

  /**
   *
   * @see com.alibaba.wasp.fserver.redo.Redo#lastCommitedTransaction()
   */
  @Override
  public WALEdit lastCommitedTransaction() throws IOException {
    checkInit();
    return lastCommitedTransaction;
  }

  /**
   *
   * @see com.alibaba.wasp.fserver.redo.Redo#lastUnCommitedTransaction()
   */
  @Override
  public WALEdit lastUnCommitedTransaction() throws InterruptedException,
      NotInitlizedRedoException, RedoLogNotServingException {
    checkInit();
    return this.editQueue.take();
  }

  /**
   * @throws NotInitlizedRedoException
   * @see com.alibaba.wasp.fserver.redo.Redo#peekLastUnCommitedTransaction()
   */
  @Override
  public WALEdit peekLastUnCommitedTransaction() throws IOException {
    checkInit();
    return this.editQueue.peek();
  }

  /**
   * @see com.alibaba.wasp.fserver.redo.Redo#redo()
   */
  @Override
  public void redo() throws IOException {
    Scan scan = new Scan(emptyStringByte);
    ResultScanner scanner = transcationTable.getScanner(scan);
    Result result;
    try {
      while ((result = scanner.next()) != null) {
        byte[] commitBytes = result.getValue(fEntityValue, cCommit);
        int commit = Bytes.toInt(commitBytes);
        if (commit == Bytes.toInt(commited)) {
          this.lastCommitedTransaction = new WALEdit(null,
              Transaction.convert(result.getValue(fEntityValue, cEntityValue)));
          break;
        } else if (commit == Bytes.toInt(unCommited)) {
          Transaction t = Transaction.convert(result.getValue(fEntityValue,
              cEntityValue));
          try {
            this.editQueue.put(new WALEdit(null, t));
          } catch (InterruptedException e) {
            throw new IOException(e);
          }
        } else if (commitBytes == null) {
          // nothing
        } else {
          throw new IOException("Unkown commit state.");
        }
      }
    } finally {
      scanner.close();
    }
  }

  /**
   *
   * @throws NotInitlizedRedoException
   */
  private void checkInit() throws NotInitlizedRedoException {
    if (!initlized) {
      throw new NotInitlizedRedoException();
    }
  }

  /**
   * Interrupt Transaction.
   *
   * @see java.io.Closeable#close()
   */
  @Override
  public void close() throws IOException {
    transcationTable.close();
  }

  /**
   * @see com.alibaba.wasp.fserver.redo.Redo#size()
   */
  @Override
  public int size() {
    return this.editQueue.size();
  }
}
TOP

Related Classes of com.alibaba.wasp.fserver.redo.RedoLog

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.