Package org.jacorb.transaction

Source Code of org.jacorb.transaction.TransactionCurrentImpl

/*
*        JacORB - a free Java ORB
*
*   Copyright (C) 1999-2004 Gerald Brose
*
*   This library is free software; you can redistribute it and/or
*   modify it under the terms of the GNU Library General Public
*   License as published by the Free Software Foundation; either
*   version 2 of the License, or (at your option) any later version.
*
*   This library is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*   Library General Public License for more details.
*
*   You should have received a copy of the GNU Library General Public
*   License along with this library; if not, write to the Free
*   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
package org.jacorb.transaction;

import java.util.Hashtable;
import org.slf4j.Logger;
import org.jacorb.orb.ORB;
import org.omg.CORBA.Any;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.CosTransactions.Control;
import org.omg.CosTransactions.ControlHelper;
import org.omg.CosTransactions.Current;
import org.omg.CosTransactions.HeuristicHazard;
import org.omg.CosTransactions.HeuristicMixed;
import org.omg.CosTransactions.InvalidControl;
import org.omg.CosTransactions.NoTransaction;
import org.omg.CosTransactions.PropagationContext;
import org.omg.CosTransactions.PropagationContextHelper;
import org.omg.CosTransactions.Status;
import org.omg.CosTransactions.SubtransactionsUnavailable;
import org.omg.CosTransactions.TransIdentity;
import org.omg.CosTransactions.TransactionFactory;
import org.omg.CosTransactions.TransactionFactoryHelper;
import org.omg.CosTransactions.otid_t;

/**
* This class represents the transaction current.
* It is a very simple implementation wich mostly
* maps to the methods in the control.
*
* @author Nicolas Noffke
* @author Vladimir Mencl
* @version $Id: TransactionCurrentImpl.java,v 1.19 2009-05-03 21:36:59 andre.spiegel Exp $
*/

public class TransactionCurrentImpl
    extends org.omg.CORBA.LocalObject
    implements Current
{
    private static final int DEFAULT_TIMEOUT = 30;
 
    private Hashtable contexts = null;
    private Hashtable timeouts = null;
    private ORB orb = null;
    private static int slot_id = -1; /* used from static getControl */

    /** there will only be ony logger instance for all TX services in a process...*/
    private static Logger logger;

    private TransactionFactory factory = null;
 
    public TransactionCurrentImpl(ORB orb, int slot_id)
    {
        this.orb = orb;
        this.slot_id = slot_id;
        logger =   
            orb.getConfiguration().getLogger("jacorb.tx_service.current");

        contexts = new Hashtable();
        timeouts = new Hashtable();

        try
        {
            NamingContextExt nc =
                NamingContextExtHelper.narrow(orb.resolve_initial_references("NameService"));
            NameComponent [] name = new NameComponent[1];
            name[0] = new NameComponent( "TransactionService", "service");
            factory = TransactionFactoryHelper.narrow(nc.resolve(name));   
        }
        catch (Exception e)
        {
            if (logger.isErrorEnabled())
                logger.error("Unable to obtain Transaction Service reference. Giving up.", e );
            throw new Error(e.getMessage());
        }
    }

    /**
     * Creates a non-functional current.
     */
    public TransactionCurrentImpl()
    {
        contexts = new Hashtable();
        timeouts = new Hashtable();
    }

    /**
     * This method is a convenience method for the server
     * programmer the exctract the Control from the
     * PICurrent.
     */
    public static Control getControl(org.omg.CORBA.ORB orb)
    {
        try
        {
            org.omg.PortableInterceptor.Current pi_current =
                (org.omg.PortableInterceptor.Current)orb.resolve_initial_references("PICurrent");

            PropagationContext context = PropagationContextHelper.extract
                (pi_current.get_slot(slot_id));

            return ControlHelper.extract(context.implementation_specific_data);
        }
        catch(Exception e)
        {
            if (logger.isDebugEnabled())
                logger.debug("Unable to obtain Transaction Service reference. Giving up.", e );
        }

        return null;
    }

    // implementation of org.omg.CosTransactions.CurrentOperations interface
    /**
     * Start a new transaction. The propagation context will be transfered
     * on ALL communication (~1k extra data) from now on, until
     * the transaction is committed or rolled back. <br>
     * NOTICE: the PropagationContext might not be set up fully
     * compliant to the Spec.
     */
    public void begin()
        throws SubtransactionsUnavailable
    {
        Thread thread = Thread.currentThread();

        if (contexts.containsKey(thread))
            throw new SubtransactionsUnavailable();

        int timeout = (timeouts.containsKey(thread))?
            ((Integer) timeouts.get(thread)).intValue() : DEFAULT_TIMEOUT;

        Control control = factory.create(timeout);
        contexts.put(thread, control);
   
        try
        {
            org.omg.PortableInterceptor.Current pi_current =
                (org.omg.PortableInterceptor.Current) orb.resolve_initial_references("PICurrent");

            // the info inserted here is actually never needed and mostly a waste of
            // space/bandwidth, since the control itself is transfered also.
            TransIdentity id = new TransIdentity(control.get_coordinator(),
                                                 control.get_terminator(),
                                                 new otid_t(0, 0, new byte[0]));
     
            Any control_any = orb.create_any();
            ControlHelper.insert(control_any, control);

            PropagationContext context = new PropagationContext(timeout,
                                                                id, new TransIdentity[0],
                                                                control_any);
            Any context_any = orb.create_any();
            PropagationContextHelper.insert(context_any, context);

            pi_current.set_slot(slot_id, context_any);
        }
        catch (Exception e)
        {
            if (logger.isDebugEnabled())
                logger.debug("Exception: ", e);
        }
    }

    public void commit(boolean report_heuristics)
        throws NoTransaction, HeuristicMixed, HeuristicHazard
    {
        Thread current = Thread.currentThread();

        if (! contexts.containsKey(current))
            throw new NoTransaction();

  Control control = null;
        try
        {
            control = (Control) contexts.get(current);
            control.get_terminator().commit(report_heuristics);   
            control._release();

            removeContext(current);
  }
        catch (org.omg.CORBA.TRANSACTION_ROLLEDBACK tr)
        {
      // Transaction was rolledback.
            if (logger.isDebugEnabled())
                logger.debug("TRANSACTION_ROLLEDBACK: ", tr);

      control._release();
      removeContext(current);
      throw tr; // re-throw the exception
        }
        catch (Exception e)
        {
            if (logger.isDebugEnabled())
                logger.debug("Exception: ", e);
        }
    }

    /**
     * This and the following method should actually throw
     * NoTransaction, but that is against the spec.
     */
    public Control get_control()
    {
        return (Control) contexts.get(Thread.currentThread());
    }

    public Status get_status()
    {
        Thread current = Thread.currentThread();

        if (! contexts.containsKey(current))
            return null;

        try
        {
            return ((Control) contexts.get(current)).get_coordinator().get_status();
        }
        catch (Exception e)
        {
            if (logger.isDebugEnabled())
                logger.debug("Exception: ", e);
        }
        return null;
    }

    public String get_transaction_name()
    {
        Thread current = Thread.currentThread();

        if (! contexts.containsKey(current))
            return null;

        try
        {           
            return ((Control) contexts.get(current)).get_coordinator().get_transaction_name();
        }
        catch (Exception e)
        {
            if (logger.isDebugEnabled())
                logger.debug("Exception: ", e);
        }
        return null;
    }

    public void resume(Control which)
        throws InvalidControl
    {
  setCurrentThreadContext(which);
    }

    public void rollback()
        throws NoTransaction
    {
        Thread current = Thread.currentThread();

        if (! contexts.containsKey(current))
            throw new NoTransaction();
        try
        {
            Control control = (Control) contexts.get(current);
            control.get_terminator().rollback();
  
            control._release();

            removeContext(current);
        }
        catch (Exception e)
        {
            if (logger.isDebugEnabled())
                logger.debug("Exception: ", e);
        }
    }

    public void rollback_only()
        throws NoTransaction
    {
        Thread current = Thread.currentThread();

        if (! contexts.containsKey(current))
            throw new NoTransaction();
        try
        {
            Control control = (Control) contexts.get(current);
            control.get_coordinator().rollback_only();      
            control._release();

            removeContext(current);
        }
        catch (Exception e){
            if (logger.isDebugEnabled())
                logger.debug("Exception: ", e);
        }
    }

    public void set_timeout(int seconds)
    {
        timeouts.put(Thread.currentThread(), new Integer(seconds));
    }

    public Control suspend()
    {
        Control result = get_control();
        removeContext(Thread.currentThread());
        return result;
    }

    public void setCurrentThreadContext(Control control)
    {
        Thread thread = Thread.currentThread();

        contexts.put(thread, control);
   
        try
        {
            org.omg.PortableInterceptor.Current pi_current =
                (org.omg.PortableInterceptor.Current)orb.resolve_initial_references("PICurrent");

            // the info inserted here is actually never needed and mostly a waste of
            // space/bandwidth, since the control itself is transfered also.
            TransIdentity id =
                new TransIdentity(control.get_coordinator(),
                                  control.get_terminator(),
                                  new otid_t(0, 0, new byte[0]));
     
            Any control_any = orb.create_any();
            ControlHelper.insert(control_any, control);

            int timeout =
                (timeouts.containsKey(thread))?
                ((Integer) timeouts.get(thread)).intValue() :
                DEFAULT_TIMEOUT;

            PropagationContext context =
                new PropagationContext(timeout,
                                       id,
                                       new TransIdentity[0],
                                       control_any);

            Any context_any = orb.create_any();
            PropagationContextHelper.insert(context_any, context);
            pi_current.set_slot(slot_id, context_any);
        }
        catch (Exception e)
        {
            if (logger.isDebugEnabled())
                logger.debug("Exception: ", e);
        }
    }

    private void removeContext(Thread current)
    {
        //remove control from Hashtable
        contexts.remove(current);

        try
        {
            org.omg.PortableInterceptor.Current pi_current =
                (org.omg.PortableInterceptor.Current)orb.resolve_initial_references("PICurrent");

            //remove control from PICurrent by overwriting it with
            //an empty any
            Any empty = orb.create_any();    
            pi_current.set_slot(slot_id, empty);
        }
        catch (Exception e)
        {
            if (logger.isDebugEnabled())
                logger.debug("Exception: ", e);
        }
    }
} // TransactionCurrentImpl





TOP

Related Classes of org.jacorb.transaction.TransactionCurrentImpl

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.