Package org.apache.sandesha2.storage.inmemory

Source Code of org.apache.sandesha2.storage.inmemory.InMemoryTransaction

/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* Licensed 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 org.apache.sandesha2.storage.inmemory;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.sandesha2.i18n.SandeshaMessageHelper;
import org.apache.sandesha2.i18n.SandeshaMessageKeys;
import org.apache.sandesha2.storage.SandeshaStorageException;
import org.apache.sandesha2.storage.Transaction;
import org.apache.sandesha2.storage.beans.RMBean;
import org.apache.sandesha2.workers.SandeshaThread;

/**
* This class does not really implement transactions, but it is a good
* place to implement locking for the in memory storage manager.
*/

public class InMemoryTransaction implements Transaction {

  private static final Log log = LogFactory.getLog(InMemoryTransaction.class);

  private InMemoryStorageManager manager;
  private String threadName;
  private int    threadId;
  private ArrayList enlistedBeans = new ArrayList();
  private InMemoryTransaction waitingForTran = null;
  private boolean sentMessages = false;
  private boolean receivedMessages = false;
  private boolean active = true;
 
  InMemoryTransaction(InMemoryStorageManager manager, String threadName, int id) {
    if(log.isDebugEnabled()) log.debug("Entry: InMemoryTransaction::<init>");
    this.manager = manager;
    this.threadName = threadName;
    this.threadId = id;
    if(log.isDebugEnabled()) log.debug("Exit: InMemoryTransaction::<init>, " + this);
  }
 
  public void commit() {
    releaseLocks();
    if(sentMessages) manager.getSender().wakeThread();
    if(receivedMessages) {
      SandeshaThread invoker = manager.getInvoker();
      if(invoker != null) invoker.wakeThread();
    }
    active = false;
  }

  public void rollback() {
    releaseLocks();
    active = false;
  }
 
  public boolean isActive () {
    return active;
  }

  public void enlist(RMBean bean) throws SandeshaStorageException {
    if(log.isDebugEnabled()) log.debug("Entry: InMemoryTransaction::enlist, " + bean);
    if(bean != null) {
      synchronized (bean) {
        InMemoryTransaction other = (InMemoryTransaction) bean.getTransaction();
        while(other != null && other != this) {
          // Put ourselves into the list of waiters
          waitingForTran = other;

          // Look to see if there is a loop in the chain of waiters
          if(!enlistedBeans.isEmpty()) {
            HashSet set = new HashSet();
            set.add(this);
            while(other != null) {
              if(set.contains(other)) {
                String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.deadlock, this.toString(), bean.toString());
                SandeshaStorageException e = new SandeshaStorageException(message);
               
                // Do our best to get out of the way of the other work in the system
                waitingForTran = null;
                releaseLocks();
               
                if(log.isDebugEnabled()) log.debug(message, e);
                throw e;
              }
              set.add(other);
              other = other.waitingForTran;
            }
          }

          try {
            if(log.isDebugEnabled()) log.debug("This " + this + " waiting for " + waitingForTran);
            bean.wait();
          } catch(InterruptedException e) {
            // Do nothing
          }
          other = (InMemoryTransaction) bean.getTransaction();
        }
       
        waitingForTran = null;
        if(other == null) {
          if(log.isDebugEnabled()) log.debug(this + " locking bean");
          bean.setTransaction(this);
          enlistedBeans.add(bean);
        }
      }
    }
   
    if(log.isDebugEnabled()) log.debug("Exit: InMemoryTransaction::enlist");
  }
 
  private void releaseLocks() {
    if(log.isDebugEnabled()) log.debug("Entry: InMemoryTransaction::releaseLocks, " + this);
    manager.removeTransaction(this);

    Iterator beans = enlistedBeans.iterator();
    while(beans.hasNext()) {
      RMBean bean = (RMBean) beans.next();
      synchronized (bean) {
        bean.setTransaction(null);
        bean.notifyAll();
      }
    }
    enlistedBeans.clear();
   
    if(log.isDebugEnabled()) log.debug("Exit: InMemoryTransaction::releaseLocks");
  }
 
  public String toString() {
    StringBuffer result = new StringBuffer();
    result.append("[InMemoryTransaction, id:");
    result.append(threadId);
    result.append(", name: ");
    result.append(threadName);
    result.append(", locks: ");
    result.append(enlistedBeans.size());
    result.append("]");
    return result.toString();
  }

  public void setReceivedMessages(boolean receivedMessages) {
    this.receivedMessages = receivedMessages;
  }

  public void setSentMessages(boolean sentMessages) {
    this.sentMessages = sentMessages;
  }
}


TOP

Related Classes of org.apache.sandesha2.storage.inmemory.InMemoryTransaction

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.