Package com.sun.messaging.jmq.jmsserver.data

Source Code of com.sun.messaging.jmq.jmsserver.data.TransactionListLoader

/*
* 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.data;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import com.sun.messaging.jmq.io.Packet;
import com.sun.messaging.jmq.io.SysMessageID;
import com.sun.messaging.jmq.jmsserver.Globals;
import com.sun.messaging.jmq.jmsserver.core.BrokerAddress;
import com.sun.messaging.jmq.jmsserver.core.ConsumerUID;
import com.sun.messaging.jmq.jmsserver.core.Destination;
import com.sun.messaging.jmq.jmsserver.core.DestinationUID;
import com.sun.messaging.jmq.jmsserver.core.PacketReference;
import com.sun.messaging.jmq.jmsserver.persist.Store;
import com.sun.messaging.jmq.jmsserver.resources.BrokerResources;
import com.sun.messaging.jmq.jmsserver.util.BrokerException;
import com.sun.messaging.jmq.util.DestType;
import com.sun.messaging.jmq.util.log.Logger;

public class TransactionListLoader {

  static Logger logger = Globals.getLogger();
  static boolean loaded = false;


  // txn log

  public static void loadTransactions(Store store, TransactionList transactionList) throws BrokerException, IOException {
    logger.log(Logger.INFO, BrokerResources.I_PROCESSING_TRANS);
    // This method is called after the message store has been loaded
    // and after the transaction log has been replayed.

    // The state of the system should be :
    // 1) All committed transactions since the last checkpoint should
    // have been replayed and persisted to the message store.
    // 2) There should be no incomplete transactions
    // (a partial write of a transaction will have been discarded).
    // 3) The message store will contain a set of prepared transactions
    // either from XA or from clustered/remote transactions.
    loadLocalTransactions(store,transactionList);
    loadClusterTransactions(store,transactionList);
    loadRemoteTransactions(store,transactionList);

  }
 
 
 
  public static void rollbackAllTransactions(Store store)
  {
    logger.log(Logger.INFO, "rolling back all transactions");
    store.rollbackAllTransactions();
   
  }
 
 
 
  private static void loadDestinations() throws BrokerException {
    if (!loaded) {
      loaded = true;
      Destination.loadDestinations();
      Iterator itr = Destination.getAllDestinations();
      while (itr.hasNext()) {
        Destination d = (Destination) itr.next();
        d.load();
      }
    }
  }

  private static void loadLocalTransactions(Store store, TransactionList transactionList) throws BrokerException, IOException {

    List<BaseTransaction> incompleteTxns = store
        .getIncompleteTransactions(BaseTransaction.LOCAL_TRANSACTION_TYPE);

    String msg = " loading " + incompleteTxns.size()
        + " incomplete Local transactions:  ";
    logger.log(Logger.DEBUG, msg);

    Iterator<BaseTransaction> iter = incompleteTxns.iterator();
    while (iter.hasNext()) {
      BaseTransaction baseTxn = iter.next();
      TransactionUID tid = baseTxn.getTid();

      msg = " loadTransactions: processing local transaction " + tid;
      logger.log(Logger.DEBUG, msg);

      TransactionState state = baseTxn.getTransactionState();
      transactionList.addTransactionID(tid, state, false);
      TransactionWork txnWork = baseTxn.getTransactionWork();
      handleTransactionWork(transactionList,tid, txnWork);
    }
  }

  private static void loadClusterTransactions(Store store, TransactionList transactionList) throws BrokerException, IOException {

    List<BaseTransaction> incompleteTxns = store
        .getIncompleteTransactions(BaseTransaction.CLUSTER_TRANSACTION_TYPE);
    String msg = " loading " + incompleteTxns.size()
        + " incomplete cluster transactions:  ";
    logger.log(Logger.DEBUG, msg);
    Iterator<BaseTransaction> iter = incompleteTxns.iterator();
    while (iter.hasNext()) {
      ClusterTransaction clusterTxn = (ClusterTransaction) iter.next();
      TransactionUID tid = clusterTxn.getTid();

      msg = " loadTransactions: processing cluster transaction " + tid;
      logger.log(Logger.DEBUG, msg);

      TransactionState state = clusterTxn.getTransactionState();
      transactionList.addTransactionID(tid, state, false);

      TransactionBroker[] transactionBrokers = clusterTxn
          .getTransactionBrokers();
      transactionList.logClusterTransaction(tid, state,
          transactionBrokers, true, false);
      TransactionWork txnWork = clusterTxn.getTransactionWork();
      if (state.getState() == TransactionState.PREPARED) {
        handleTransactionWork(transactionList, tid, txnWork);
      } else if (state.getState() == TransactionState.COMMITTED) {
        // incomplete cluster transaction
        // the work has already been committed locally but
        // there may be remote brokers that have not confirmed they have
        // committed this transaction
        // Add to transaction reaper
        transactionList.removeTransaction(tid, false);
      }
       
    }
  }
 
  private static void loadRemoteTransactions(Store store, TransactionList transactionList) throws BrokerException, IOException {

    List<BaseTransaction> incompleteTxns = store
        .getIncompleteTransactions(BaseTransaction.REMOTE_TRANSACTION_TYPE);
    String msg = " loading " + incompleteTxns.size()
        + " incomplete remote transactions:  ";
    logger.log(Logger.DEBUG, msg);
    Iterator<BaseTransaction> iter = incompleteTxns.iterator();
    while (iter.hasNext()) {
      RemoteTransaction remoteTxn = (RemoteTransaction)iter.next();
      TransactionUID tid = remoteTxn.getTid();

   
      TransactionState state = remoteTxn.getTransactionState();
      TransactionAcknowledgement  tas[] = remoteTxn.getTxnAcks();
      DestinationUID  destIds[] = remoteTxn.getDestIds();
      msg = " loadTransactions: processing remote transaction " + tid + " state= "+state;
      logger.log(Logger.DEBUG, msg);
      BrokerAddress remoteTransactionHomeBroker = remoteTxn.getTxnHomeBroker();
     
      transactionList.logRemoteTransaction(tid, state, tas,
          remoteTransactionHomeBroker, true, true, false);
     
      for(int i=0;i<tas.length;i++)
      {
        TransactionAcknowledgement ta = tas[i];
        DestinationUID destId = destIds[i];
        unrouteLoadedTransactionAckMessage(destId,ta.getSysMessageID(),ta.getStoredConsumerUID());
      }
    }
  }

  static void  handleTransactionWork(TransactionList transactionList,TransactionUID tid, TransactionWork txnWork)
      throws BrokerException {
   
   
   
    handleSentMessages(transactionList, txnWork);
    handleMessageAcks(transactionList,tid,txnWork);
   
  }
 
  static void  handleSentMessages(TransactionList transactionList, TransactionWork txnWork) throws BrokerException
  {
    for (int i = 0; i < txnWork.numSentMessages(); i++) {

      TransactionWorkMessage msg = txnWork.getSentMessages().get(i);
      Packet packet = msg.getMessage();

      DestinationUID duid = msg.getDestUID();

      logger.log(Logger.DEBUG,
          " handleSentMessages: duid= "+duid);
           
      PacketReference pr = PacketReference.createReference(packet, duid,
          null);
      Destination d = Destination.getDestination(duid);
      if (d == null) {
        // Could be an auto-created dest that was reaped on load.
        // Lets recreate it here.
        try {
          int type = (duid.isQueue() ? DestType.DEST_TYPE_QUEUE
              : DestType.DEST_TYPE_TOPIC);
          d = Destination.getDestination(duid.getName(), type, true,
              true);
        } catch (IOException e) {
          throw new BrokerException("Could not recreate destination "
              + duid, e);
        }
      }
     
      // check it is loaded
      d.load();
     
      logger.log(Logger.DEBUG,
          " loadTransactions: processing prepared sent message "
              + packet.getMessageID()) ;

      // queue message
      boolean result = d.queueMessage(pr, true);

      // store (should not really be persisted as we are using txnLog)
      // pr.store();

      // add message to transaction
      transactionList.addMessage(pr.getTransactionID(), pr
          .getSysMessageID(), true);

    }
  }
 
  static void handleMessageAcks(TransactionList transactionList,TransactionUID tid, TransactionWork txnWork)
      throws BrokerException {
    for (int i = 0; i < txnWork.numMessageAcknowledgments(); i++) {
      TransactionWorkMessageAck msgAck = txnWork
          .getMessageAcknowledgments().get(i);     
      DestinationUID destID = msgAck.getDestUID();
      handleAck(transactionList,tid, destID, msgAck.getSysMessageID(), msgAck.getConsumerID());

    }
  }
 
 
  static void handleAck(TransactionList transactionList,TransactionUID tid, DestinationUID destID, SysMessageID ackedSysMsgID,
      ConsumerUID consumerID) throws BrokerException {
    logger.log(Logger.DEBUG,
        " loadTransactions: processing prepared acknowledged message "
            + ackedSysMsgID);

    transactionList.addAcknowledgement(tid, ackedSysMsgID, consumerID,
        consumerID, true, false);
    transactionList
        .addOrphanAck(tid, ackedSysMsgID, consumerID, consumerID);

    unrouteLoadedTransactionAckMessage(destID, ackedSysMsgID, consumerID);

  }

  static void unrouteLoadedTransactionAckMessage(DestinationUID destID, SysMessageID ackedSysMsgID,
      ConsumerUID consumerID) throws BrokerException {
    logger.log(Logger.DEBUG,
        " trying to unroute prepared acknowledged message: destID =  "
            + destID + " ackedMsgId=" + ackedSysMsgID);
   
    Destination dest = null;
    PacketReference ackedMessage = null;
    if (destID != null) {
      dest = Destination.getDestination(destID);
      if (dest != null) {
        dest.load();
        ackedMessage = dest.getMessage(ackedSysMsgID);
        if (ackedMessage == null) {

          String msg = "Could not find packet for " + ackedSysMsgID
              + "in dest " + dest;
          logger.log(Logger.WARNING, msg);
          return;
        }
      } else {
        // this could happen e.g. if empty auto dest has been destroyed
        String msg = "Could not find destination for " + destID;
        logger.log(Logger.WARNING, msg);
        return;
      }

    } else {
      // no destid stored for some reason so need to load all dests
      logger.log(Logger.WARNING,
          "No dest ID for acked message. Will need to load all dests "
              + ackedSysMsgID);
      loadDestinations();

      ackedMessage = Destination.get(ackedSysMsgID);
      dest = ackedMessage.getDestination();
    }

    // need to unroute messages that have been consumed in a prepared
    // transaction.
    // they cannot be redelivered unless the transaction rolls back.

    dest.unrouteLoadedTransactionAckMessage(ackedMessage, consumerID);

  }

}
TOP

Related Classes of com.sun.messaging.jmq.jmsserver.data.TransactionListLoader

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.