Package com.sun.messaging.jmq.jmsserver.persist.file

Source Code of com.sun.messaging.jmq.jmsserver.persist.file.BaseTransactionManager

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License.  You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

package com.sun.messaging.jmq.jmsserver.persist.file;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.sun.messaging.jmq.jmsserver.Globals;
import com.sun.messaging.jmq.jmsserver.data.BaseTransaction;
import com.sun.messaging.jmq.jmsserver.data.TransactionState;
import com.sun.messaging.jmq.jmsserver.data.TransactionUID;
import com.sun.messaging.jmq.jmsserver.data.TransactionWork;
import com.sun.messaging.jmq.jmsserver.data.TransactionWorkMessage;
import com.sun.messaging.jmq.jmsserver.persist.Store;
import com.sun.messaging.jmq.jmsserver.util.BrokerException;
import com.sun.messaging.jmq.util.log.Logger;

public abstract class BaseTransactionManager {

  public static final Logger logger = Globals.getLogger();

  PreparedTxnStore preparedTxnStore;
  TransactionLogManager transactionLogManager;

  Set<TransactionUID> playingToMessageStore = Collections.synchronizedSet(new HashSet<TransactionUID>());
  Map<TransactionUID, BaseTransaction> completeStored = new Hashtable<TransactionUID, BaseTransaction>();
  Map<TransactionUID, BaseTransaction> incompleteUnstored = new Hashtable<TransactionUID, BaseTransaction>();
  Map<TransactionUID, BaseTransaction> incompleteStored = new Hashtable<TransactionUID, BaseTransaction>();

  BaseTransactionManager(TransactionLogManager transactionLogManager) {
    this.transactionLogManager = transactionLogManager;
    preparedTxnStore = transactionLogManager.preparedTxnStore;
  }

  abstract String getPrefix();

  public List<BaseTransaction> getAllIncompleteTransactions() {
    List<BaseTransaction> result = new ArrayList<BaseTransaction>();
    if (Store.getDEBUG()) {
      String msg = getPrefix() + " getAllIncompleteTransactions  "
          + " num incompleteUnstored = " + incompleteUnstored.size()
          + " num incompleteStored = " + incompleteStored.size();
      logger.log(Logger.DEBUG, msg);
    }
    result.addAll(incompleteUnstored.values());
    result.addAll(incompleteStored.values());
    return result;
  }
 
  public HashMap getAllTransactionsMap() {
    List<BaseTransaction> txns = getAllIncompleteTransactions();
    HashMap map = new HashMap(txns.size());
    Iterator<BaseTransaction> itr = txns.iterator();
    while (itr.hasNext()) {
      BaseTransaction txn = itr.next();
      TransactionState txnState = new TransactionState(txn
          .getTransactionState());
      map.put(txn.getTid(), txnState);
    }
    return map;
  }

  public void addToCompleteStored(BaseTransaction baseTxn) {
    completeStored.put(baseTxn.getTid(), baseTxn);
    if (Store.getDEBUG()) {
      String msg = getPrefix() + " adding  " + baseTxn.getTid()
          + "  to completeStored. Total = " + completeStored.size();
      logger.log(Logger.DEBUG, msg);
    }
  }

  public void removeFromCompleteStored(TransactionUID tid) {
    completeStored.remove(tid);
    if (Store.getDEBUG()) {
      String msg = getPrefix() + " removing " + tid
          + " from completeStored. Total = " + completeStored.size();
      logger.log(Logger.DEBUG, msg);
    }
  }

  void addToIncompleteStored(BaseTransaction baseTxn) {
    incompleteStored.put(baseTxn.getTid(), baseTxn);
    if (Store.getDEBUG()) {
      String msg = getPrefix()

      + " adding  " + baseTxn.getTid()
          + "  to incompleteStored. Total = "
          + incompleteStored.size();
      logger.log(Logger.DEBUG, msg);
    }
  }

  BaseTransaction removeFromIncompleteStored(TransactionUID tid) {
    BaseTransaction result = incompleteStored.remove(tid);
    if (Store.getDEBUG()) {
      String msg = getPrefix()

      + " removing  " + tid + " from incompleteStored. Total = "
          + incompleteStored.size();
      logger.log(Logger.DEBUG, msg);
    }
    return result;
  }

  void addToIncompleteUnstored(BaseTransaction baseTxn) {
    incompleteUnstored.put(baseTxn.getTid(), baseTxn);
    if (Store.getDEBUG()) {
      String msg = getPrefix()

      + " adding  " + baseTxn.getTid()
          + "  to incompleteUnstored. Total = "
          + incompleteUnstored.size();
      logger.log(Logger.DEBUG, msg);
    }
  }

  BaseTransaction removeFromIncompleteUnstored(TransactionUID tid) {
    BaseTransaction result = incompleteUnstored.remove(tid);
    if (Store.getDEBUG()) {
      String msg = getPrefix()

      + " removing  " + tid + " from incompleteUnstored. Total = "
          + incompleteUnstored.size();
      logger.log(Logger.DEBUG, msg);
    }
    return result;
  }

  abstract void processStoredTxnOnStartup(BaseTransaction baseTxn);

  public void waitForPlayingToMessageStoreCompletion() {
    synchronized (playingToMessageStore) {
      if (Store.getDEBUG()) {
        String msg = getPrefix() + " num playingToMessageStore ="
            + playingToMessageStore.size();
        logger.log(Logger.DEBUG, msg);
      }
      try {
        while (playingToMessageStore.size() > 0) {
          if (Store.getDEBUG()) {
            String msg = getPrefix() + " waiting for "
                + playingToMessageStore.size()
                + " playingToMessageStore";
            logger.log(Logger.DEBUG, msg);
          }
          playingToMessageStore.wait(1000);
        }
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

  }

  /*
   * this method is called by transactionHandler to notify that
   * the committed transaction has been written to the message store.
   *
   * Keeping track of committed transactions and when they have been written to the message store
   * allows the TransactionlogManager to know when it is safe to do a checkpoint.
   */
  public void playingToMessageStoreComplete(TransactionUID tid) {
    if (Store.getDEBUG()) {
      String msg = getPrefix() + " playingToMessageStoreComplete " + tid;
      logger.log(Logger.DEBUG, msg);
    }
    synchronized (playingToMessageStore) {
      Object found = playingToMessageStore.remove(tid);
      if (found == null) {
        String msg = getPrefix()
            + " playingToMessageStoreComplete(): could not find "
            + tid;
        logger.log(Logger.WARNING, msg);
      }
      playingToMessageStore.notify();
    }
    if (Store.getDEBUG()) {
      String msg = getPrefix()
          + " remove transaction from  playingToMessageStore."
          + " tid=" + tid + " size = " + playingToMessageStore.size();
      logger.log(Logger.DEBUG, msg);
    }
  }

  // on checkpoint, we need to store any newly logged prepared transactions to the preparedTxnStore
  // as the transaction log is about to be reset
  void writePreparedTransactionsToPreparedTxnStoreOnCheckpoint()
      throws BrokerException {
    if (Store.getDEBUG()) {
      String msg = getPrefix()
          + " writePreparedTransactionsToPreparedTxnStoreOnCheckpoint"
          + " num incompleteUnstored=" + incompleteUnstored.size();
      logger.log(Logger.DEBUG, msg);
    }

    ArrayList<TransactionUID> incmps = null;
    synchronized(incompleteUnstored) {
      incmps = new ArrayList<TransactionUID>(incompleteUnstored.keySet());
    }

    TransactionUID tid = null;
    BaseTransaction baseTxn = null;
    Iterator<TransactionUID> iter = incmps.iterator();
    while (iter.hasNext()) {
      tid = iter.next();
      if (!preparedTxnStore.containsTransaction(tid)) {
        baseTxn = (BaseTransaction)incompleteUnstored.get(tid);
        if (baseTxn == null) {
          continue;
        }
        if (Store.getDEBUG()) {
          String msg = getPrefix()
              + " transaction storing preparedTransaction "
              + baseTxn;
          logger.log(Logger.DEBUG, msg);
        }
        try {         
          preparedTxnStore.storeTransaction(baseTxn, true);
          addToIncompleteStored(baseTxn);
        } catch (IOException ioe) {
          throw new BrokerException(
              "failed to store transaction in preparedTxnStore "
                  + baseTxn, ioe);
        }
      } else {

       
          String msg = getPrefix()
              + " transaction already exists in preparedTxnStore "
              + tid+"["+incompleteUnstored.get(tid)+"]";
          logger.log(Logger.INFO, msg);
       
      }
    }
    incompleteUnstored.clear();
  }

  void removeCompleteTransactionsAfterCheckpoint() throws BrokerException {
    if (Store.getDEBUG()) {
      String msg = getPrefix()
          + " removeCompleteTransactionsAfterCheckpoint"
          + "num completeStored=" + completeStored.size();
      logger.log(Logger.DEBUG, msg);
    }

    ArrayList cmptids = null;
    synchronized(completeStored) {
      cmptids = new ArrayList(completeStored.keySet());
    }
    Iterator<TransactionUID> iter = cmptids.iterator();
    while (iter.hasNext()) {
      TransactionUID tid = iter.next();
      if (preparedTxnStore.containsTransaction(tid)) {
        preparedTxnStore.removeTransaction(tid, true);

        if (Store.getDEBUG()) {
          String msg = getPrefix() + " removed transaction " + tid;
          logger.log(Logger.DEBUG, msg);
        }
      } else {

        if (Store.getDEBUG()) {
          String msg = getPrefix()
              + " Could not find transaction in preparedTxnStore "
              + tid;
          logger.log(Logger.DEBUG, msg);
        }
      }
    }
    completeStored.clear();

  }
 
  void rollbackAllTransactions() {
    if (Store.getDEBUG()) {
      String msg = getPrefix()
          + " rollbackAllTransactions"
          + " num incompleteStored=" + incompleteStored.size()
          + " num incompleteUnstored=" + incompleteUnstored.size();
      logger.log(Logger.DEBUG, msg);
    }
    Collection<BaseTransaction> storedTxns = incompleteStored.values();
    Collection<BaseTransaction> storedTxnsCopy = new ArrayList<BaseTransaction>(
        storedTxns);
    rollbackTransactions(storedTxnsCopy);
   
    Collection<BaseTransaction> unstoredTxns = incompleteUnstored.values();
    Collection<BaseTransaction> unstoredTxnsCopy = new ArrayList<BaseTransaction>(
        unstoredTxns);
    rollbackTransactions(unstoredTxnsCopy);

  }
 
  void rollbackTransactions(Collection<BaseTransaction> txns) {
    Iterator<BaseTransaction> iter = txns.iterator();
    while (iter.hasNext()) {
      BaseTransaction txn = iter.next();
      try {
        processTxnCompletion(txn.getTid(), TransactionState.ROLLEDBACK,
            true);
      } catch (IOException ioe) {
        logger.log(Logger.ERROR, "could not rollback " + txn, ioe);

      } catch (BrokerException be) {
        logger.log(Logger.ERROR, "could not rollback " + txn, be);
      }

    }

  }

  abstract void processTxn(BaseTransaction baseTxn) throws IOException,
      BrokerException;

  abstract TransactionEvent generateEvent(BaseTransaction baseTxn, boolean completion)
      throws IOException, BrokerException;

  abstract BaseTransaction processTxnCompletion(TransactionUID tid, int state)
      throws IOException, BrokerException;

  BaseTransaction processTxnCompletion(TransactionUID tid, int state,
      boolean fullyComplete) throws IOException, BrokerException {

    // We are committing a prepared entry.
    // Check if it is in the prepared transaction store
    // If it is mark it as committed, so that it can be cleaned up after next checkpoint
    if(state==TransactionState.COMMITTED)
    {
      this.playingToMessageStore.add(tid);
      if (Store.getDEBUG()) {
        String msg = getPrefix()
            + " add transaction to  playingToMessageStore."
            + " tid=" + tid + " size = " + playingToMessageStore.size();
        logger.log(Logger.DEBUG, msg);
      }
    }
   
    BaseTransaction existingTxn = null;
    boolean stored = false;
    existingTxn = incompleteUnstored.get(tid);
    if (existingTxn == null) {
      existingTxn = incompleteStored.get(tid);
      if (existingTxn != null) {
        stored = true;
      } else {
        String msg = getPrefix() + " processTxnCompletion: Could not find txn for " + tid;
        logger.log(Logger.WARNING, msg);
        throw new BrokerException(msg);
      }
    }
    existingTxn.getTransactionDetails().setState(state);

    if (stored) {
      // update the stored transaction from prepared to committed/rolledback state     
      //update state on file by writing at fixed offset

      updateStoredState(tid, state);

      if (fullyComplete) {
        incompleteStored.remove(tid);
        completeStored.put(tid, existingTxn);
      }

    } else {
      if (fullyComplete) {
        removeFromIncompleteUnstored(tid);
      }
    }
    messageListLogged(existingTxn);
   

    return existingTxn;

  }
 
  protected void messageListLogged(BaseTransaction baseTxn) {
    TransactionWork txnWork = baseTxn.getTransactionWork();
    if (txnWork != null) {
      List<TransactionWorkMessage> sentMessages = txnWork
          .getSentMessages();
      if (sentMessages != null) {
        transactionLogManager.loggedMessageHelper
            .messageListLogged(sentMessages);
      }
    }
  }
 

  void updateStoredState(TransactionUID tid, int state) throws IOException,
      BrokerException {
    preparedTxnStore.updateTransactionState(tid, state, true);

    if (Store.getDEBUG()) {
      String msg = getPrefix()
          + " updated transaction state of stored prepared transaction to "
          + TransactionState.toString(state);
      logger.log(Logger.DEBUG, msg);
    }
  }

  void updateStoredCompletion(TransactionUID tid, boolean complete)
      throws IOException, BrokerException {
    preparedTxnStore.updateTransactionCompletion(tid, complete, true);

    if (Store.getDEBUG()) {
      String msg = getPrefix()
          + " updated completion status of stored transaction to "
          + complete;
      logger.log(Logger.DEBUG, msg);
    }
  }

  abstract void replayTransactionEvent(TransactionEvent localTxnEvent,
      HashSet dstLoadedSet) throws BrokerException, IOException;

}
TOP

Related Classes of com.sun.messaging.jmq.jmsserver.persist.file.BaseTransactionManager

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.