Package com.arjuna.ats.internal.arjuna.abstractrecords

Source Code of com.arjuna.ats.internal.arjuna.abstractrecords.PersistenceRecord

/*
* JBoss, Home of Professional Open Source
* Copyright 2006, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA  02110-1301, USA.
*
* (C) 2005-2006,
* @author JBoss Inc.
*/
/*
* Copyright (C) 1998, 1999, 2000, 2001,
*
* Arjuna Solutions Limited,
* Newcastle upon Tyne,
* Tyne and Wear,
* UK.
*
* $Id: PersistenceRecord.java 2342 2006-03-30 13:06:17Z  $
*/

package com.arjuna.ats.internal.arjuna.abstractrecords;

import com.arjuna.ats.arjuna.ObjectType;
import com.arjuna.ats.arjuna.StateManager;
import com.arjuna.ats.arjuna.logging.tsLogger;
import com.arjuna.ats.arjuna.logging.FacilityCode;

import com.arjuna.ats.arjuna.coordinator.*;
import com.arjuna.ats.arjuna.common.arjPropertyManager;
import com.arjuna.ats.arjuna.objectstore.ObjectStore;
import com.arjuna.ats.arjuna.common.*;
import com.arjuna.ats.arjuna.state.*;
import com.arjuna.ats.arjuna.objectstore.ObjectStoreType;
import java.io.PrintWriter;

import com.arjuna.common.util.logging.*;

import com.arjuna.ats.arjuna.exceptions.ObjectStoreException;
import java.io.IOException;

/**
* A PersistenceRecord is created whenever a persistent object is
* created/read/modified within the scope of a transaction. It is responsible
* for ensuring that state changes are committed or rolled back on behalf of the
* object depending upon the outcome of the transaction.
*
* @author Mark Little (mark@arjuna.com)
* @version $Id: PersistenceRecord.java 2342 2006-03-30 13:06:17Z  $
* @since JTS 1.0.
*
*
* @message com.arjuna.ats.arjuna.PersistenceRecord_1
*          [com.arjuna.ats.arjuna.PersistenceRecord_1]
*          PersistenceRecord::topLevelCommit() : About to commit state, uid =
*          {0}, ObjType = {1}
* @message com.arjuna.ats.arjuna.PersistenceRecord_2
*          [com.arjuna.ats.arjuna.PersistenceRecord_2]
*          PersistenceRecord::topLevelCommit - commit_state call failed for {0}
* @message com.arjuna.ats.arjuna.PersistenceRecord_3
*          [com.arjuna.ats.arjuna.PersistenceRecord_3]
*          PersistenceRecord::topLevelCommit - no state to commit!
* @message com.arjuna.ats.arjuna.PersistenceRecord_4
*          [com.arjuna.ats.arjuna.PersistenceRecord_4]
*          PersistenceRecord::topLevelCommit - caught exception: {0}
* @message com.arjuna.ats.arjuna.PersistenceRecord_5
*          [com.arjuna.ats.arjuna.PersistenceRecord_5]
*          PersistenceRecord::topLevelCommit - no object store specified!
* @message com.arjuna.ats.arjuna.PersistenceRecord_6
*          [com.arjuna.ats.arjuna.PersistenceRecord_6]
*          PersistenceRecord::topLevelCommit - commit_state error
* @message com.arjuna.ats.arjuna.PersistenceRecord_7
*          [com.arjuna.ats.arjuna.PersistenceRecord_7] PersistenceRecord
*          deactivate error
* @message com.arjuna.ats.arjuna.PersistenceRecord_8
*          [com.arjuna.ats.arjuna.PersistenceRecord_8]
*          PersistenceRecord.topLevelPrepare - setup error!
* @message com.arjuna.ats.arjuna.PersistenceRecord_9
*          [com.arjuna.ats.arjuna.PersistenceRecord_9]
*          PersistenceRecord::restore_state: Just unpacked object store type =
*          {0}
* @message com.arjuna.ats.arjuna.PersistenceRecord_10
*          [com.arjuna.ats.arjuna.PersistenceRecord_10]
*          PersistenceRecord::restore_state: Failed to unpack object store type
* @message com.arjuna.ats.arjuna.PersistenceRecord_11
*          [com.arjuna.ats.arjuna.PersistenceRecord_11]
*          PersistenceRecord::save_state - type of store is unknown
* @message com.arjuna.ats.arjuna.PersistenceRecord_12
*          [com.arjuna.ats.arjuna.PersistenceRecord_12]
*          PersistenceRecord::save_state: Packed object store type = {0}
* @message com.arjuna.ats.arjuna.PersistenceRecord_13
*          [com.arjuna.ats.arjuna.PersistenceRecord_13]
*          PersistenceRecord::save_state: Packed object store root
* @message com.arjuna.ats.arjuna.PersistenceRecord_14
*          [com.arjuna.ats.arjuna.PersistenceRecord_14]
*          PersistenceRecord::save_state - packing top level state failed
* @message com.arjuna.ats.arjuna.PersistenceRecord_15
*          [com.arjuna.ats.arjuna.PersistenceRecord_15]
*          PersistenceRecord::save_state - failed
* @message com.arjuna.ats.arjuna.PersistenceRecord_16
*          [com.arjuna.ats.arjuna.PersistenceRecord_16]
*          PersistenceRecord::save_state - no object store defined for object
* @message com.arjuna.ats.arjuna.PersistenceRecord_17
*          [com.arjuna.ats.arjuna.PersistenceRecord_17]
*          PersistenceRecord::PersistenceRecord() - crash recovery constructor
* @message com.arjuna.ats.arjuna.PersistenceRecord_18
*          [com.arjuna.ats.arjuna.PersistenceRecord_18]
*          PersistenceRecord::topLevelAbort() - Expecting state but found none!
* @message com.arjuna.ats.arjuna.PersistenceRecord_20
*          [com.arjuna.ats.arjuna.PersistenceRecord_20]
*          PersistenceRecord::topLevelAbort() - Received ObjectStoreException
*          {0}
* @message com.arjuna.ats.arjuna.PersistenceRecord_21
*          [com.arjuna.ats.arjuna.PersistenceRecord_21]
*          PersistenceRecord.topLevelPrepare - write_uncommitted error
*/

public class PersistenceRecord extends RecoveryRecord
{

  /**
   * This constructor is used to create a new instance of PersistenceRecord.
   */

  public PersistenceRecord (OutputObjectState os, ObjectStore objStore, StateManager sm)
  {
    super(os, sm);

    if (tsLogger.arjLogger.isDebugEnabled())
    {
      tsLogger.arjLogger.debug(DebugLevel.CONSTRUCTORS, VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_ABSTRACT_REC, "PersistenceRecord::PersistenceRecord("
          + os + ", " + sm.get_uid() + ")");
    }

    shadowMade = false;
    store = objStore;
    topLevelState = null;
  }

  /**
   * Redefintions of abstract functions inherited from RecoveryRecord.
   */

  public int typeIs ()
  {
    return RecordType.PERSISTENCE;
  }

  /**
   * topLevelAbort may have to remove the persistent state that was written
   * into the object store during the processing of topLevelPrepare. It then
   * does the standard abort processing.
   */

  public int topLevelAbort ()
  {
    if (tsLogger.arjLogger.isDebugEnabled())
    {
      tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_ABSTRACT_REC, "PersistenceRecord::topLevelAbort() for "
          + order());
    }

    Uid uid = null;
    String type = null;

    if (shadowMade) // state written by StateManager instance
    {
      uid = order();
      type = getTypeOfObject();
    }
    else
    {
      if (topLevelState == null) // hasn't been prepared, so no state
      {
        return nestedAbort();
      }
      else
      {
        uid = topLevelState.stateUid();
        type = topLevelState.type();
      }
    }

    try
    {
      if (!store.remove_uncommitted(uid, type))
      {
        if (tsLogger.arjLoggerI18N.isWarnEnabled())
        {
          tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.PersistenceRecord_19");
        }

        return TwoPhaseOutcome.FINISH_ERROR;
      }
    }
    catch (ObjectStoreException e)
    {
      if (tsLogger.arjLoggerI18N.isWarnEnabled())
      {
        tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.PersistenceRecord_20", new Object[] { e }, e);
      }

      return TwoPhaseOutcome.FINISH_ERROR;
    }

    return nestedAbort();
  }

  /**
   * commit the state saved during the prepare phase.
   */

  public int topLevelCommit ()
  {
    if (tsLogger.arjLogger.isDebugEnabled())
    {
      tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_ABSTRACT_REC, "PersistenceRecord::topLevelCommit() for "
          + order());
    }

    if (tsLogger.arjLoggerI18N.isDebugEnabled())
    {
      tsLogger.arjLoggerI18N.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_ABSTRACT_REC, "com.arjuna.ats.arjuna.PersistenceRecord_1", new Object[]
      { order(), getTypeOfObject() });
    }

    if (tsLogger.arjLogger.isDebugEnabled())
    {
      if (store != null)
      {
        tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_ABSTRACT_REC, ", store = "
            + store + "(" + store.typeIs() + ")");
      }
      else
      {
        tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_ABSTRACT_REC, "");
      }
    }

    boolean result = false;

    if (store != null)
    {
      try
      {
        if (shadowMade)
        {
          result = store.commit_state(order(), super.getTypeOfObject());

          if (!result)
          {
            if (tsLogger.arjLoggerI18N.isWarnEnabled())
            {
              tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.PersistenceRecord_2", new Object[]
              { order() });
            }
          }
        }
        else
        {
          if (topLevelState != null)
          {
            result = store.write_committed(order(), super.getTypeOfObject(), topLevelState);
          }
          else
          {
            if (tsLogger.arjLoggerI18N.isWarnEnabled())
              tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.PersistenceRecord_3");
          }
        }
      }
      catch (ObjectStoreException e)
      {
        if (tsLogger.arjLoggerI18N.isWarnEnabled())
          tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.PersistenceRecord_4", new Object[]
          { e });

        result = false;
      }
    }
    else
    {
      if (tsLogger.arjLoggerI18N.isWarnEnabled())
        tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.PersistenceRecord_5");
    }

    if (!result)
    {
      if (tsLogger.arjLoggerI18N.isWarnEnabled())
        tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.PersistenceRecord_6");
    }

    super.forgetAction(true);

    return ((result) ? TwoPhaseOutcome.FINISH_OK
        : TwoPhaseOutcome.FINISH_ERROR);
  }

  /**
   * topLevelPrepare attempts to save the object. It will either do this in
   * the action intention list or directly in the object store by using the
   * 'deactivate' function of the object depending upon the size of the state.
   * To ensure that objects are correctly hidden while they are in an
   * uncommitted state if we use the abbreviated protocol then we write an
   * EMPTY object state as the shadow state - THIS MUST NOT BE COMMITTED.
   * Instead we write_committed the one saved in the intention list. If the
   * store cannot cope with being given an empty state we revert to the old
   * protocol.
   */

  public int topLevelPrepare ()
  {
    if (tsLogger.arjLogger.isDebugEnabled())
    {
      tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_ABSTRACT_REC, "PersistenceRecord::topLevelPrepare() for "
          + order());
    }

    int result = TwoPhaseOutcome.PREPARE_NOTOK;
    StateManager sm = super.objectAddr;

    if ((sm != null) && (store != null))
    {
        /*
         * Get ready to create our state to be saved. At this stage we're not
         * sure if the state will go into its own log or be written into the
         * transaction log for improved performance.
         */
       
      topLevelState = new OutputObjectState(sm.get_uid(), sm.type());

      if (writeOptimisation
          && (!store.fullCommitNeeded()
              && (sm.save_state(topLevelState, ObjectType.ANDPERSISTENT)) && (topLevelState.size() <= PersistenceRecord.MAX_OBJECT_SIZE)))
      {
          /*
           * We assume that crash recovery will always run before
           * the object can be reactivated!
           */

        if (PersistenceRecord.classicPrepare)
        {
          OutputObjectState dummy = new OutputObjectState(
              Uid.nullUid(), null);

          /*
           * Write an empty shadow state to the store to indicate one
           * exists, and to prevent bogus activation in the case where
           * crash recovery hasn't run yet.
           */

          try
          {
            store.write_uncommitted(sm.get_uid(), sm.type(), dummy);
            result = TwoPhaseOutcome.PREPARE_OK;
          }
          catch (ObjectStoreException e)
          {
            tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.PersistenceRecord_21", e);
          }

          dummy = null;
        }
        else
        {
            /*
             * Don't write anything as our state will go into the log.
             */
           
          result = TwoPhaseOutcome.PREPARE_OK;
        }
      }
      else
      {
        if (sm.deactivate(store.getStoreName(), false))
        {
          shadowMade = true;

          result = TwoPhaseOutcome.PREPARE_OK;
        }
        else
        {
          if (tsLogger.arjLoggerI18N.isWarnEnabled())
            tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.PersistenceRecord_7");
        }
      }
    }
    else
    {
      if (tsLogger.arjLoggerI18N.isWarnEnabled())
        tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.PersistenceRecord_8");
    }

    return result;
  }

  /**
   * topLevelCleanup must leave the persistent state that was written in the
   * object store during the processing of topLevelPrepare intact. Crash
   * recovery will take care of its resolution
   */

  public int topLevelCleanup ()
  {
    if (tsLogger.arjLogger.isDebugEnabled())
    {
      tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_ABSTRACT_REC, "PersistenceRecord::topLevelCleanup() for "
          + order());
    }

    return TwoPhaseOutcome.FINISH_OK;
  }

  /**
   * @return <code>true</code>
   */

  public boolean doSave ()
  {
    return true;
  }

  @SuppressWarnings("unchecked")
    public boolean restore_state (InputObjectState os, int ot)
  {
    if (tsLogger.arjLogger.isDebugEnabled())
    {
      tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_ABSTRACT_REC, "PersistenceRecord::restore_state() for "
          + order());
    }

    boolean res = false;
    int objStoreType = 0;

    topLevelState = null;
   
    try
    {
      objStoreType = os.unpackInt();

      if (tsLogger.arjLoggerI18N.isDebugEnabled())
      {
        tsLogger.arjLoggerI18N.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_ABSTRACT_REC, "com.arjuna.ats.arjuna.PersistenceRecord_9", new Object[]
        { Integer.toString(objStoreType) });
      }

      if (ObjectStoreType.valid(objStoreType))
      {
        /* discard old store before creating new */

        if (store == null)
        {
            Class oc = ObjectStoreType.typeToClass(objStoreType);
           
            store = (ObjectStore) oc.newInstance();
        }

        store.unpack(os);
        shadowMade = os.unpackBoolean();

        // topLevelState = null;

        if (!shadowMade)
        {
          topLevelState = new OutputObjectState(os);
          res = topLevelState.valid();
        }
        else
          res = true;

        return (res && super.restore_state(os, ot));
      }
    }
    catch (final Exception e)
    {
      if (tsLogger.arjLoggerI18N.isWarnEnabled())
        tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.PersistenceRecord_10");
    }

    return res;
  }

  public boolean save_state (OutputObjectState os, int ot)
  {
    if (tsLogger.arjLogger.isDebugEnabled())
    {
      tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_ABSTRACT_REC, "PersistenceRecord::save_state() for "
          + order());
    }

    boolean res = true;

    if (store != null)
    {
      if (!ObjectStoreType.valid(store.typeIs()))
      {
        if (tsLogger.arjLoggerI18N.isWarnEnabled())
        {
          tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.PersistenceRecord_11");
        }

        res = false;
      }
      else
      {
        try
        {
          os.packInt(store.typeIs());

          if (tsLogger.arjLoggerI18N.isDebugEnabled())
          {
            tsLogger.arjLoggerI18N.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_ABSTRACT_REC, "com.arjuna.ats.arjuna.PersistenceRecord_12", new Object[]
            { Integer.toString(store.typeIs()) });
          }

          store.pack(os);

          if (tsLogger.arjLoggerI18N.isDebugEnabled())
          {
            tsLogger.arjLoggerI18N.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_ABSTRACT_REC, "com.arjuna.ats.arjuna.PersistenceRecord_13");
          }

          os.packBoolean(shadowMade);

          /*
           * If we haven't written a shadow state, then pack the state
           * into the transaction log. There MUST be a state at this
           * point.
           */

          if (!shadowMade)
          {
            res = (topLevelState != null);

            if (res)
              topLevelState.packInto(os);
            else
            {
              if (tsLogger.arjLoggerI18N.isWarnEnabled())
                tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.PersistenceRecord_14");
            }
          }
        }
        catch (IOException e)
        {
          res = false;

          if (tsLogger.arjLoggerI18N.isWarnEnabled())
            tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.PersistenceRecord_15");
        }
      }
    }
    else
    {
      if (tsLogger.arjLoggerI18N.isWarnEnabled())
        tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.PersistenceRecord_16");

      try
      {
        os.packString(null);
      }
      catch (IOException e)
      {
        res = false;
      }
    }

    return res && super.save_state(os, ot);
  }

  public void print (PrintWriter strm)
  {
    super.print(strm); /* bypass RecoveryRecord */

    strm.println("PersistenceRecord with state:\n" + super.state);
  }

  public String type ()
  {
    return "/StateManager/AbstractRecord/RecoveryRecord/PersistenceRecord";
  }

  /**
   * Creates a 'blank' persistence record. This is used during crash recovery
   * when recreating the prepared list of a server atomic action.
   */

  public PersistenceRecord ()
  {
    super();

    if (tsLogger.arjLoggerI18N.isDebugEnabled())
    {
      tsLogger.arjLoggerI18N.debug(DebugLevel.CONSTRUCTORS, VisibilityLevel.VIS_PROTECTED, FacilityCode.FAC_ABSTRACT_REC, "com.arjuna.ats.arjuna.PersistenceRecord_17");
    }

    shadowMade = false;
    store = null;
    topLevelState = null;
  }

  /**
   * Cadaver records force write shadows. This operation supresses to
   * abbreviated commit This should never return false
   */

  protected boolean shadowForced ()
  {
    if (topLevelState == null)
    {
      shadowMade = true;

      return true;
    }

    /* I've already done the abbreviated protocol so its too late */

    return false;
  }

  // this value should really come from the object store implementation!

  public static final int MAX_OBJECT_SIZE = 4096; // block size

  protected boolean shadowMade;
  protected ObjectStore store;
  protected OutputObjectState topLevelState;
  protected static boolean classicPrepare = false;

  private static boolean writeOptimisation = false;

  static
  {
        classicPrepare = arjPropertyManager.getCoordinatorEnvironmentBean().isClassicPrepare();

        writeOptimisation = arjPropertyManager.getCoordinatorEnvironmentBean().isWriteOptimisation();
  }
}
TOP

Related Classes of com.arjuna.ats.internal.arjuna.abstractrecords.PersistenceRecord

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.