/*!**************************************************************************

  module      : Log_Transaction.cpp

  -------------------------------------------------------------------------

  responsible : UweH

  special area: Logging
  description : 


  last changed: 2001-01-15  15:59
  see also    : 

  -------------------------------------------------------------------------

  copyright:    (c) 2001-2004 SAP AG

    ========== licence begin  GPL
    Copyright (c) 2001-2005 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end


*****************************************************************************/



/*===========================================================================*
 *  INCLUDES                                                                 *
 *===========================================================================*/

#include "SAPDBCommon/ErrorsAndMessages/SAPDBErr_Assertions.hpp"
#include "SAPDBCommon/Tracing/SAPDBTrace_Usage.hpp"
#include "SAPDBCommon/MemoryManagement/SAPDBMem_NewDestroy.hpp"
#include "DataAccess/Data_Exceptions.hpp"
#include "Logging/Log_Types.hpp"
#include "Logging/Log_Transaction.hpp"
#include "Logging/Log_Volume.hpp"
#include "Logging/Log_UndoFile.hpp"
#include "Restart/Rst_RedoFile.hpp"
#include "Logging/Log_AfterImage.hpp"
#include "Logging/Log_BeforeImage.hpp"
#include "Logging/Log_IAction.hpp"
#include "Logging/Log_ActionCopyUpdBlob.hpp"
#include "Logging/Log_ActionCreateDropFile.hpp"
#include "Logging/Log_ActionInsDelRec.hpp"
#include "Logging/Log_ActionModifyTable.hpp"
#include "Logging/Log_ActionObject.hpp"
#include "Logging/Log_ActionObjectFile.hpp"
#include "Logging/Log_ActionDeleteAllObjects.hpp"
#include "Logging/Log_ActionRefreshSurrogSeq.hpp"
#include "Logging/Log_ActionReorganizeFile.hpp"
#include "Logging/Log_ActionReloadFile.hpp"
#include "Logging/Log_ActionSetFileState.hpp"
#include "Logging/Log_ActionUnloadFile.hpp"
#include "Logging/Log_ActionUpdateRec.hpp"
#include "Logging/Log_ActionPartialRollback.hpp"
#include "Logging/Log_ActionSavepoint.hpp"
#include "Restart/Rst_IRedoTrafficControl.hpp"
#include "Logging/Log_Exceptions.hpp"
#include "Logging/Log_History.hpp"
#include "Logging/Log_Savepoint.hpp"
#include "GarbageCollector/GC_IGCController.hpp" /* PTS 1120151 FF 2003-JAN-31 */
#include "hkb50.h"  // k50my_state
#include "hkb54.h"  // k54rollback_temp
#include "hkb57.h"  // k57surrogates_to_log
#include "hgg01.h"  // g01is_livecache()
#include "RunTime/Configuration/RTEConf_ParameterAccessKernelInterface.hpp"

/*===========================================================================*
 *  DEFINES                                                                  *
 *===========================================================================*/
 
// #define TEST_DEBUG 1
 
/*===========================================================================*
 *  LOCAL *
 *===========================================================================*/

/// 0 means is not set
static SAPDB_UInt LocalRedoBufferSize = 0; // PTS 1131107 UH 2004-08-24 added

/* -------------------------------------------------------------------------------- */
static void TraceEntry ( const char*          title,
                         const tgg91_TransNo &TransNo,
                         Log_IOSequenceNo     SubTransNo, // PTS 1124727 mb 2003-10-29
                         Log_EntrySequence    sequence,
                         Log_ActionType       actionType)
{
    Kernel_VTrace() << title
                    << ": T" << TransNo.gg90GetInt4()
                    << "/"   << SubTransNo
                    << " ("  << sequence
                    << ") '" << Log_GetActionTypeString(actionType)
                    << "'";
}

/*===========================================================================*
 *  METHODS                                                                  *
 *===========================================================================*/

/* -------------------------------------------------------------------------------- */
bool Log_Transaction::CreateUndoFile ()
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::CreateUndoFile", LogTrans_Trace, 5);
    SAPDBERR_ASSERT_STATE   ( IsInitialized() );
    if ( ! m_pUndoFile->Create () ) // PTS 1121659 UH 2003-04-30
        return false;
    kb50EnterTransRegion (m_pTrans->trTaskId_gg00, m_pTrans->trIndex_gg00);
    m_Context.UndoFileRootPageNo = m_pUndoFile->GetRootId().PageNo();
    kb50LeaveTransRegion (m_pTrans->trTaskId_gg00, m_pTrans->trIndex_gg00);
    return true;
}
                                    
/* -------------------------------------------------------------------------------- */
void Log_Transaction::DropUndoFile()
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::DropUndoFile", LogTrans_Trace, 5);
    
    if ( m_pTrans != NULL )
        kb50EnterTransRegion (m_pTrans->trTaskId_gg00, m_pTrans->trIndex_gg00);
    
    m_Context.UndoFileRootPageNo = SAPDB_MAX_INT4;
    
    if ( m_pTrans != NULL )
        kb50LeaveTransRegion (m_pTrans->trTaskId_gg00, m_pTrans->trIndex_gg00);
    
    if ( m_pUndoFile != NULL
         &&
         m_pUndoFile->IsCreated() )
    {
        m_pUndoFile->Drop();
    }
}
                                    
/* -------------------------------------------------------------------------------- */
void Log_Transaction::CreateRedoFile (tgg00_TransContext &redoReaderTrans)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::CreateRedoFile", LogTrans_Trace, 5);
    SAPDBERR_ASSERT_STATE   ( IsInitializedForRedoCopy() );
    if ( ! m_pRedoFile->Create () ) // PTS 1121659 UH 2003-04-30
        RTE_Crash( SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED,"redo file creation") );
    kb50EnterTransRegion (m_pTrans->trTaskId_gg00, m_pTrans->trIndex_gg00);
    m_Context.RedoFileRootPageNo = m_pRedoFile->GetRootId().PageNo();
    kb50LeaveTransRegion (m_pTrans->trTaskId_gg00, m_pTrans->trIndex_gg00);
}
                                    
/* -------------------------------------------------------------------------------- */
void Log_Transaction::DropRedoFile()
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::DropRedoFile", LogTrans_Trace, 5);
    
    if ( m_pTrans != NULL )
        kb50EnterTransRegion (m_pTrans->trTaskId_gg00, m_pTrans->trIndex_gg00);
    
    m_Context.RedoFileRootPageNo = SAPDB_MAX_INT4;
    
    if ( m_pTrans != NULL )
        kb50LeaveTransRegion (m_pTrans->trTaskId_gg00, m_pTrans->trIndex_gg00);
    
    if ( m_pRedoFile != NULL
         &&
         m_pRedoFile->IsCreated() )
    {
        m_pRedoFile->Drop();
    }
}
                                    
/* -------------------------------------------------------------------------------- */
bool Log_Transaction::IsInitialized()
{
    return m_TransType      != illegalTransType && 
           m_pTrans         != NULL             &&
           m_pAllocator     != NULL             &&
           m_pSubtransStack != NULL             &&
           m_pUndoFile      != NULL;
}

/* -------------------------------------------------------------------------------- */
bool Log_Transaction::Initialize (tgg00_TransContext &Trans)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::Initialize", LogTrans_Trace, 5);

    SAPDBERR_ASSERT_STATE ( ! IsInitialized() );

    m_pTrans     = &Trans;
    m_pAllocator = REINTERPRET_CAST(SAPDBMem_IRawAllocator*, Trans.trAllocator_gg00);
    m_pQueue     = 0;

    if ( Log_Volume::IsReadyForWriting()
         &&
         Log_Volume::Instance().IsDevspaceEnabled(Trans.trTaskId_gg00) )
    {
        m_pQueue = Log_Volume::Instance().GetQueue(Trans.trTaskId_gg00);
	}

    m_pSubtransStack = new (Allocator()) SubtransStack (Allocator());
    if ( m_pSubtransStack == NULL )
    {
        Delete();
        return false;
    }
    
    m_pUndoFile = new (Allocator()) Log_UndoFile ( Trans,
                                                   m_Context.UndoFileRootPageNo,
                                                   m_Context.UndoFileLastPageNo );
    if ( m_pUndoFile == NULL )
    {
        Delete();
        return false;
    }

    if ( ! m_pSubtransStack->Initialize(LOG_DEFAULT_SUBTRANS_STACK_CAPACITY) )
    {
        Delete();
        return false;
    }

	// PTS 1131107 UH 2004-08-24
    if ( LocalRedoBufferSize != 0
         &&
         ! m_LocalRedoEntries.Initialize(Allocator(),LocalRedoBufferSize) )
    {
        Delete();
        return false;
    }
    
    return true;
}

/* -------------------------------------------------------------------------------- */
void Log_Transaction::Delete()
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::Delete", LogTrans_Trace, 5);
    if ( m_pUndoFile != NULL  )
    {
        DropUndoFile();
        destroy (m_pUndoFile, Allocator());
    }
    if (m_pRedoFile != NULL )
    {
        DropRedoFile();
        destroy (m_pRedoFile, Allocator());
    }
    if (m_pSubtransStack != NULL)
    {
        destroy (m_pSubtransStack, Allocator());
    }
    
    m_LocalRedoEntries.Delete();
    
    m_pTrans          = NULL;
    m_pAllocator      = NULL;
}

/* -------------------------------------------------------------------------------- */
bool Log_Transaction::IsInitializedForRedoCopy()
{
    return m_TransType  != illegalTransType
           && 
           m_pRedoFile  != NULL
           &&
           m_pTrans     != NULL
           &&
           m_pAllocator != NULL;
}

/* -------------------------------------------------------------------------------- */
bool Log_Transaction::InitializeForRedoCopy (tgg00_TransContext     &redoReaderTrans,
                                             const tgg91_TransNo    &transNo,
                                             SAPDBMem_IRawAllocator &allocator)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::InitializeForRedoCopy", LogTrans_Trace, 5);

    SAPDBERR_ASSERT_STATE ( ! IsInitializedForRedoCopy() );

    m_Context.TransNo = transNo;
    m_TransType       = redoRead;
    m_pAllocator      = &allocator;
    m_pTrans          = &redoReaderTrans;

    m_pRedoFile = new (allocator) Rst_RedoFile ( redoReaderTrans,
                                                 m_Context.RedoFileRootPageNo,
                                                 m_Context.RedoFileLastPageNo);
    if ( m_pRedoFile == NULL )
        RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,
                   SAPDBERR_ASSERT_STATE_FAILED,
                   "Log_Transaction::InitializeForRedo() allocation failed") );
    
	// PTS 1131107 UH 2004-08-24
    if ( LocalRedoBufferSize != 0
         &&
         ! m_LocalRedoEntries.Initialize(Allocator(),LocalRedoBufferSize) )
    {
        Delete();
        return false;
    }

    return true;
}

/* -------------------------------------------------------------------------------- */
void Log_Transaction::DeleteAfterRedoCopy()
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::DeleteAfterRedoCopy", LogTrans_Trace, 5);
    if ( m_pRedoFile != 0 && m_pAllocator == 0 )
        RTE_Crash( SAPDBErr_Exception(__CONTEXT__, SAPDBERR_ASSERT_STATE_FAILED,
                   "Log_Transaction::DeleteAfterRedoCopy() allocator not assigned") );
    if ( m_pRedoFile != 0 )
    {
        m_pRedoFile->Delete();                // PTS 1131935 mb 2004-10-14
        Allocator().Deallocate(m_pRedoFile); // PTS 1131935 mb 2004-10-14
        m_pRedoFile = 0;
    }
    m_pAllocator  = 0;
    m_pTrans      = 0;
    
    m_LocalRedoEntries.Delete();
}

/* -------------------------------------------------------------------------------- */
bool Log_Transaction::IsInitializedForRedo()
{
    return m_TransType  != illegalTransType && 
           m_pTrans     != NULL             &&
           m_pAllocator != NULL;
}

/* -------------------------------------------------------------------------------- */
bool Log_Transaction::InitializeForRedo (tgg00_TransContext &redoExecuteTrans)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::InitializeForRedo", LogTrans_Trace, 5);
    SAPDBERR_ASSERT_STATE   ( m_pRedoFile == NULL );
    SAPDBERR_ASSERT_STATE   ( m_pUndoFile == NULL );
    
    redoExecuteTrans.trLogContext_gg00 = this;
    
    m_pTrans          = &redoExecuteTrans;
    m_pAllocator      = REINTERPRET_CAST(SAPDBMem_IRawAllocator*, redoExecuteTrans.trAllocator_gg00);
    m_TransType       = redoExecute;

    if ( m_Context.UndoFileRootPageNo != SAPDB_MAX_INT4 )
    {
        m_pUndoFile = new (Allocator()) Log_UndoFile ( redoExecuteTrans,
                                                       m_Context.UndoFileRootPageNo,
                                                       m_Context.UndoFileLastPageNo);
        if ( m_pUndoFile == NULL )
        {
            RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,
                       SAPDBERR_ASSERT_STATE_FAILED,
                       "allocation of Log_UndoFile failed") );
            return false;
        }
    }        

    if ( m_Context.RedoFileRootPageNo != SAPDB_MAX_INT4 )
    {
        m_pRedoFile = new (Allocator()) Rst_RedoFile ( redoExecuteTrans,
                                                       m_Context.RedoFileRootPageNo,
                                                       m_Context.RedoFileLastPageNo);
        if ( m_pRedoFile == NULL )
        {
            RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,
                       SAPDBERR_ASSERT_STATE_FAILED,
                       "allocation of Rst_RedoFile failed") );
            return false;
        }
    }        
    
    return true;
}

/* -------------------------------------------------------------------------------- */
void Log_Transaction::DeleteAfterRedo()
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::DeleteAfterRedo", LogTrans_Trace, 5);
    Delete();
}

/* -------------------------------------------------------------------------------- */
Log_Transaction& Log_Transaction::CopyFromRedoReaderToRedoJobList(const Log_Transaction& srcTrans)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::operator =", LogTrans_Trace, 5);
    m_Context                      = srcTrans.m_Context;
    m_MaxSubtransNo                = srcTrans.m_MaxSubtransNo;
    m_TransType                    = illegalTransType;
    m_WasOpenInLastSavepoint       = srcTrans.m_WasOpenInLastSavepoint;
    m_OldestKnownIOSequence        = srcTrans.m_OldestKnownIOSequence;
    return *this;
}

/* -------------------------------------------------------------------------------- */
void Log_Transaction::WritePersistentFormat (SAPDB_Byte* Space,
                                             SAPDB_UInt  Length)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::WritePersistentFormat", LogTrans_Trace, 5);
    
    SAPDBERR_ASSERT_STATE (Space != NULL);
    SAPDBERR_ASSERT_STATE (Length == GetPersistentLength());

    m_PersistentAccess.Lock();
    *(REINTERPRET_CAST(Persistent*,Space)) = m_Context;
    m_PersistentAccess.Unlock();
}

/* -------------------------------------------------------------------------------- */
void Log_Transaction::ReadPersistentFormat (const SAPDB_Byte* Space,
                                            SAPDB_UInt        Length)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::ReadPersistentFormat", LogTrans_Trace, 5);

    SAPDBERR_ASSERT_STATE (Space != NULL);
    SAPDBERR_ASSERT_STATE (Length == GetPersistentLength());

    m_Context = *(REINTERPRET_CAST(const Persistent*,Space));
    m_WasOpenInLastSavepoint = true;
}

/* -------------------------------------------------------------------------------- */
void Log_Transaction::WriteToTrace (const char *Title) const
{
    if ( Title != NULL )
        Kernel_VTrace() << Title;
    
    Kernel_VTrace trace;
    
    trace         << "Dump of T" << m_Context.TransNo.gg90GetInt4()
                  << (m_TransType==online?" (online):":(m_TransType==redoRead?" (redoRead):":" (redoExecute):")) << " State: "
                  << ((GetTransState() == opened)       ? "open" :
                      (GetTransState() == committed)  ? "committed" :
                      (GetTransState() == rollbacked) ? "rollbacked" : "unknown")
                  << "[" << m_Context.EOT_IOSequenceNo << "]"
                  << (m_WasOpenInLastSavepoint?" was open in last savepoint":"")
                  << FlushLine;
    trace         << "Undo: root: "   << m_Context.UndoFileRootPageNo
                  << ", last: "       << m_Context.UndoFileLastPageNo
                  << ", lastseq: "    << m_Context.LastUndoEntrySequence
                  << FlushLine;
    trace         << "Redo: root: "   << m_Context.RedoFileRootPageNo
                  << ", last: "       << m_Context.RedoFileLastPageNo
                  << ", lastseq: "    << m_Context.LastRedoEntrySequence
                  << ", lastcopseq: " << m_Context.LastCopiedRedoEntrySequence
                  << FlushLine;

    if ( m_pTrans == NULL )
        trace     << "pTrans: NIL\n";
    else
        trace     << "pTrans: "     << m_pTrans->trSessionId_gg00.gg90GetInt4()
                  << "."            << m_pTrans->trWriteTransId_gg00.gg90GetInt4()
                  << "/"            << m_pTrans->trSubtransId_gg00
                  << " ("           << m_pTrans->trTransId_gg00.gg90GetInt4()
                  << ") view: "     << m_pTrans->trConsistView_gg00.gg90GetInt4()
                  << " task: "      << m_pTrans->trTaskId_gg00
                  << " index: "     << m_pTrans->trIndex_gg00
                  << " error: "     << m_pTrans->trError_gg00
                  << FlushLine;

    if ( m_pQueue == NULL  )
        trace     << "ArchivLog: disabled\n";
    else
        trace     << "ArchivLog: enabled\n";

    if ( m_pUndoFile == NULL )
        trace     << "UndoFile: NULL\n";
    else
    {
        trace     << (m_Context.BeforeImagesNeededByHistory?"history relevant":"")
                  << FlushLine;
        m_pUndoFile->WriteToTrace();
    }

    if ( m_pRedoFile == NULL )
        trace << "RedoFile: NULL\n";
    else
        m_pRedoFile->WriteToTrace();
}

/* -------------------------------------------------------------------------------- */
void Log_Transaction::BeginSubtrans()
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::BeginSubtrans", LogTrans_Trace, 5);
    
    SAPDBERR_ASSERT_STATE ( IsInitialized() );
    SAPDBERR_ASSERT_STATE ( opened == GetTransState() );
    
    ++m_MaxSubtransNo;
    m_pTrans->trSubtransId_gg00 = m_MaxSubtransNo;

    SubtransStackElem NewElem;
    NewElem.SubtransNo       = m_pTrans->trSubtransId_gg00;
    NewElem.UndoStopSequence = m_Context.LastUndoEntrySequence + 1;
    NewElem.RedoStopSequence = m_Context.LastRedoEntrySequence + 1;

    if ( ! m_pSubtransStack->Push(NewElem) )
    {
        RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,
                                      SAPDBERR_ASSERT_STATE_FAILED,
                                      "BeginSubtrans:Push failed") );
    }
    SAPDBTRACE_WRITELN (LogTrans_Trace, 6, "NewSubtransNo: " << NewElem.SubtransNo << \
                        ", UndoStopSeq: " << NewElem.UndoStopSequence << \
                        ", RedoStopSeq: " << NewElem.RedoStopSequence);
}
    
/* -------------------------------------------------------------------------------- */
bool Log_Transaction::EndSubtrans()
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::EndSubtrans", LogTrans_Trace, 5);

    SAPDBERR_ASSERT_STATE ( IsInitialized() );
    SAPDBERR_ASSERT_STATE ( opened == GetTransState() );

    if ( m_pSubtransStack->IsEmpty() )
    {
        return false;
    }

    SAPDBTRACE_WRITELN (LogTrans_Trace, 6, "OldSubtransNo: " << m_pSubtransStack->Top().SubtransNo << \
                        ", UndoStopSeq: " << m_pSubtransStack->Top().UndoStopSequence << \
                        ", RedoStopSeq: " << m_pSubtransStack->Top().RedoStopSequence);

    (void)m_pSubtransStack->Pop();

    if ( m_pSubtransStack->IsEmpty() )
    {
        // ++ until temp logging is written new
        // m_MaxSubtransNo             = LOG_NIL_SUBTRANS_NO;
        m_pTrans->trSubtransId_gg00 = LOG_NIL_SUBTRANS_NO;
    }
    else
        m_pTrans->trSubtransId_gg00 = m_pSubtransStack->Top().SubtransNo;

    SAPDBTRACE_WRITELN (LogTrans_Trace, 6, "NewSubtransNo: " << m_pTrans->trSubtransId_gg00);
    
    return true;
}
    

/* -------------------------------------------------------------------------------- */
tgg00_SubtransNo Log_Transaction::
PopUntilSubtransFound (tgg00_SubtransNo   SubtransNo,
                       Log_EntrySequence &UndoStopSequence,
                       Log_EntrySequence &RedoStopSequence)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::PopUntilSubtransFound", LogTrans_Trace, 5);
    
    while ( ! m_pSubtransStack->IsEmpty() )
    {
        if ( m_pSubtransStack->Top().SubtransNo == SubtransNo )
        {
            UndoStopSequence = m_pSubtransStack->Top().UndoStopSequence;
            RedoStopSequence = m_pSubtransStack->Top().RedoStopSequence;
            (void)m_pSubtransStack->Pop();
            if ( m_pSubtransStack->IsEmpty() )
            {
                // ++ until temp logging is written new
                // m_MaxSubtransNo = LOG_NIL_SUBTRANS_NO;
                return LOG_NIL_SUBTRANS_NO;
            }
            return m_pSubtransStack->Top().SubtransNo;
        }
        (void)m_pSubtransStack->Pop();
    }
    
    RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,
                                  SAPDBERR_ASSERT_STATE_FAILED,
                                  "PopUntilSubtransFound: SubtransNo not found") );
    return LOG_NIL_SUBTRANS_NO;
}
    
/* -------------------------------------------------------------------------------- */
void Log_Transaction::EndOfTransHandling (TransState State)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::EndOfTransHandling", LogTrans_Trace, 5);

    SAPDBTRACE_WRITELN (LogTrans_Trace, 6, \
                        "State: " << ((State == opened)     ? "open" : \
                                      (State == committed)  ? "committed" : \
                                      (State == rollbacked) ? "rollbacked" : "unknown"));

    #ifdef SAPDB_QUICK
    if ( m_Context.LastRedoEntrySequence.IsValid()
         ||
         m_Context.LastUndoEntrySequence.IsValid() )
    {
        if ( (void*)k50GetLogTransaction (m_pTrans->trIndex_gg00) != (void*)this )
            RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,SAPDBERR_ASSERT_STATE_FAILED,
                       "Log_Transaction::EndOfTransHandling() logtransptr lost1") );
    }
    #endif
    
    if ( m_pTrans->trState_gg00.includes(tsSurrogateUpd_egg00) )
        k57surrogates_to_log (*m_pTrans);

    kb50EnterTransRegion (m_pTrans->trTaskId_gg00, m_pTrans->trIndex_gg00);
    SetTransState (State);
    kb50LeaveTransRegion (m_pTrans->trTaskId_gg00, m_pTrans->trIndex_gg00);

    #ifdef SAPDB_QUICK
    if ( online == m_TransType
         &&
         (m_Context.LastRedoEntrySequence.IsValid()
          ||
          m_Context.LastUndoEntrySequence.IsValid()) )
    {
        if ( (void*)k50GetLogTransaction (m_pTrans->trIndex_gg00) != (void*)this )
            RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,SAPDBERR_ASSERT_STATE_FAILED,
                       "Log_Transaction::EndOfTransHandling() logtransptr lost2") );
    }
    #endif

    if ( online == m_TransType
         &&
         (m_Context.LastRedoEntrySequence.IsValid()
         ||
         m_Context.LastUndoEntrySequence.IsValid()) ) // PTS 1136623 UH 2005-08-29
    {
        if ( ! WriteEndOfTransEntry (State) )
            RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,
                                          SAPDBERR_ASSERT_STATE_FAILED,
                                          "WriteEndOfTransEntry failed") );
    }

    SAPDBTRACE_WRITELN (LogTrans_Trace, 6, "EndOfTrans: T" << m_Context.TransNo.gg90GetInt4() <<
                                           " iosequence: " << m_Context.EOT_IOSequenceNo);

    bool undoFileWasDropped = false;
    
    if ( m_Context.LastUndoEntrySequence.IsValid()
         &&
         m_pUndoFile != NULL
         &&
         m_pUndoFile->IsCreated() )
    {
        undoFileWasDropped = true;

        /* PTS 1112554 UH 2001-11-14 for livecache the undofile is always given to the history */
        if ( 1 == g01is_livecache() ) 
        {
            GiveUndoFileToHistory();
            GC_IGCController::Instance().TriggerGarbageCollection(); /* PTS 1120151 FF 2003-JAN-31 */
        }
        else
        {
			if ( LogTrans_Check.ChecksLevel(5) && m_Context.BeforeImagesNeededByHistory )
            {
                WriteToTrace("CHECK DROP UNDO FILE");
                RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,
                                              SAPDBERR_ASSERT_STATE_FAILED,
                                              "WriteEndOfTransEntry: DROP UNDO FILE NOT ALLOWED") );
            }
            DropUndoFile();
        }
    }

    // reset the persistent part of the transaction
    m_PersistentAccess.Lock();
    m_Context.init();
    m_PersistentAccess.Unlock();

    if ( online == m_TransType )
    {
        (void)m_pSubtransStack->Empty();
        // ++ until temp logging is written new
        // m_MaxSubtransNo                 = LOG_NIL_SUBTRANS_NO;
        m_pTrans->trSubtransId_gg00     = LOG_NIL_SUBTRANS_NO;
    }
}

/* -------------------------------------------------------------------------------- */
Log_UndoFile::WriteBeforeImageResult
     Log_Transaction::WriteUndoEntry (Log_BeforeImage   &BeforeImage,
                                      const Log_IAction &Action,
                                      Data_PageNo       &pageno,
                                      Data_PageOffset   &offset)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::WriteUndoEntry", LogTrans_Trace, 5);

    // PTS 1114653 UH 2002-03-05 it must be allowed to write undo entries during redo.
    #ifdef SAPDB_QUICK
    switch (m_TransType)
    {
        case online:
            if ( ! IsInitialized() )
                RTE_Crash(SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED,"not initialized correctly"));
            break;
        case redoRead:
            if ( ! IsInitializedForRedoCopy() )
                RTE_Crash(SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED,"not initialized correctly"));
            break;
        case redoExecute:
            if ( ! IsInitializedForRedo() )
                RTE_Crash(SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED,"not initialized correctly"));
            break;
        default:
            RTE_Crash(SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED,"m_TransType unexpected"));
    }
    #endif

    if ( m_Context.LastUndoEntrySequence.IsValid() )
    {
        SAPDBERR_ASSERT_STATE ( m_pUndoFile->IsCreated() );
        ++m_Context.LastUndoEntrySequence;
        if ( m_pTrans->trWriteTransId_gg00 != m_Context.TransNo )
            RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,SAPDBERR_ASSERT_STATE_FAILED,
                       "Log_Transaction::WriteUndoEntry: writetrans differs") );
    }
    else
    {
        SAPDBERR_ASSERT_STATE ( ! m_pUndoFile->IsCreated() );
        if ( ! CreateUndoFile() ) // PTS 1121659 UH 2003-04-30
        {
            if ( m_TransType != online ) // PTS 1121659 UH 2003-04-30
                RTE_Crash( SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED,
                           "undo file creation") );
            return Log_UndoFile::writeBeforeImageNoSpaceAvailable; // PTS 1121659 UH 2003-04-30
        }
        m_Context.LastUndoEntrySequence = LOG_FIRST_ENTRY_SEQUENCE;
        m_Context.TransNo = m_pTrans->trWriteTransId_gg00;
        // PTS 1127009 UH 2004-01-09 added m_OldestKnownIOSequence, PTS 1127704 mb 2004-02-11
        m_OldestKnownIOSequence = Log_Savepoint::GetLastSavepointIOSequence();
        SAPDBERR_ASSERT_STATE ( m_OldestKnownIOSequence.IsValid() );        
    }

    #ifdef SAPDB_QUICK
    if ( (void*)k50GetLogTransaction (m_pTrans->trIndex_gg00) != (void*)this )
        RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,SAPDBERR_ASSERT_STATE_FAILED,
                   "Log_Transaction::WriteUndoEntry() logtransptr lost") );
    #endif

    BeforeImage.SetConsistentView (m_pTrans->trConsistView_gg00);
    // before or after write ?, what is with the savepoint ?
    BeforeImage.SetSequence         (m_Context.LastUndoEntrySequence);
    BeforeImage.SetLastRedoSequence (m_Context.LastRedoEntrySequence);

    if ( BeforeImage.GetActionType() == Log_NoOp )
        BeforeImage.SetActionType ( Action.GetType() );

    Log_ActionType type = BeforeImage.GetActionType();

	if ( LogTrans_Trace.TracesLevel(6) )
    	TraceEntry ( "WriteUndoEntry",
        	         m_Context.TransNo,
            	     m_pTrans->trSubtransId_gg00,
                	 m_Context.LastUndoEntrySequence,
                 	type);

    SAPDBERR_ASSERT_STATE ( m_pUndoFile != NULL && m_pUndoFile->IsCreated() );

    
    m_Context.BeforeImagesNeededByHistory = ( type == Log_NewObject        || 
                                              type == Log_InsertObject     || 
                                              type == Log_UpdateObject     || 
                                              type == Log_DeleteObject     || 
                                              type == Log_LockObject );

    // PTS 1121659 UH 2003-04-30
    const Log_UndoFile::WriteBeforeImageResult writeResult = 
        m_pUndoFile->WriteUndoEntry (BeforeImage, Action, pageno, offset);
    m_Context.UndoFileLastPageNo = pageno;

    SAPDBTRACE_WRITELN (LogTrans_Trace, 6, "beforeimage ins: " << pageno << "." << offset);
    SAPDBTRACE_WRITELN (LogTrans_Trace, 6, "end: " << (writeResult == Log_UndoFile::writeBeforeImageOk ? "ok" : "ERROR"));

    return writeResult; // PTS 1121659 UH 2003-04-30
}


/* -------------------------------------------------------------------------------- */
Log_Transaction::RollbackResult Log_Transaction::
    Rollback (RollbackKind      rollbackKind,
              tgg00_SubtransNo  SubtransNo,
              Log_EntrySequence undoStopSequence ) // PTS 1113230 UH 2001-12-20
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::Rollback", LogTrans_Trace, 5);

    bool isRedoPartialRollback = undoStopSequence.IsValid(); // PTS 1113230 UH 2001-12-20
    
    if ( m_pTrans != NULL )
        m_pTrans->trError_gg00 = e_ok;
    
#   ifdef SAPDB_QUICK
    if ( online == m_TransType && ! IsInitialized() )
        RTE_Crash( SAPDBErr_Exception(__CONTEXT__, SAPDBERR_ASSERT_STATE_FAILED,
                   "Log_Transaction::Rollback: TransType / Initialization1") );
    if ( redoExecute == m_TransType && ! IsInitializedForRedo() )
        RTE_Crash( SAPDBErr_Exception(__CONTEXT__, SAPDBERR_ASSERT_STATE_FAILED,
                   "Log_Transaction::Rollback: TransType / Initialization2") );
#   endif
    
    if ( m_TransType != online
         &&
         ! isRedoPartialRollback ) // PTS 1113230 UH 2001-12-20
    {
        DropRedoFile();
        SAPDBERR_ASSERT_STATE ( m_pUndoFile != NULL );
    }

    RollbackResult Result = undoOk;

#   ifdef SAPDB_SLOW
    if ( LogTrans_Trace.TracesLevel(6) )
        WriteToTrace("CurrentTrans");

    if ( endOfTrans == rollbackKind
         &&
         SubtransNo != LOG_NIL_SUBTRANS_NO )
        RTE_Crash( SAPDBErr_Exception(
                   __FILE__, __LINE__,
                   SAPDBERR_ASSERT_STATE_FAILED,
                   "Log_Transaction::Rollback: SubtransNo is not nil") );
#   endif

    if ( endOfTrans != rollbackKind
         &&
         ! isRedoPartialRollback // PTS 1113230 UH 2001-12-20
         &&
         m_pSubtransStack->IsEmpty() )
        return undoNoOpenSubtrans;

    // ++++ TEMP LOGGING SHOULD BE OBSOLETE
    if ( m_pTrans->trState_gg00.includes (tsTempUpdated_egg00) )
    {
        if ( rollbackKind == endOfTrans )
            k54rollback_temp (*m_pTrans, mm_rollback);
        else if ( rollbackKind == command
                  &&
                  m_pTrans->trState_gg00.includes (tsFunctRollbSet_egg00) )
            k54rollback_temp (*m_pTrans, mm_nil);
        else if ( rollbackKind == subTrans )
            k54rollback_temp (*m_pTrans, mm_subtrans);
        if ( m_pTrans->trError_gg00 != e_ok )
            RTE_Crash( SAPDBErr_Exception(
                       __FILE__, __LINE__,
                       SAPDBERR_ASSERT_STATE_FAILED,
                       "Log_Transaction::Rollback: k54rollback_temp() failed") );
    }
    // ++++ TEMP LOGGING SHOULD BE OBSOLETE

    if ( ! m_Context.LastUndoEntrySequence.IsValid() )
    {
        if ( endOfTrans == rollbackKind )
            EndOfTransHandling(rollbacked);
        else
            if ( ! isRedoPartialRollback // PTS 1113230 UH 2001-12-20 
                 &&
                 ! EndSubtrans() )
                return undoNoOpenSubtrans;
        return undoOk;
    }

    SAPDBERR_ASSERT_STATE ( m_pUndoFile->IsCreated() );

    Log_EntrySequence UndoStopSequence = LOG_FIRST_ENTRY_SEQUENCE;
    Log_EntrySequence RedoStopSequence = LOG_FIRST_ENTRY_SEQUENCE;
    Log_EntrySequence PrevSequence     = LOG_FIRST_ENTRY_SEQUENCE;

    if ( isRedoPartialRollback ) // PTS 1113230 UH 2001-12-20 begin
        UndoStopSequence = undoStopSequence;
    else                         // PTS 1113230 UH 2001-12-20 end
    {
        if ( LOG_NIL_SUBTRANS_NO != SubtransNo )
        {
            m_pTrans->trSubtransId_gg00 =
                PopUntilSubtransFound (SubtransNo,
                                       UndoStopSequence,
                                       RedoStopSequence);

            SAPDBTRACE_WRITELN (LogTrans_Trace, 6,
                                "PartialRollback:SubtransNo: " << SubtransNo <<
                                (endOfTrans == rollbackKind?" eot ":command == rollbackKind?" command":" partial ")
                                << "=> UndoStopSequence: " << UndoStopSequence
                                << (UndoStopSequence == m_Context.LastUndoEntrySequence + 1 ? " => nothing to do." : ""));
    
            if ( UndoStopSequence == m_Context.LastUndoEntrySequence + 1 )
                return undoOk;
        }
    }
    
    Log_UndoFile::Iterator& iter = m_pUndoFile->GetIterator(); // PTS ? UH 2002-03-15

    m_pUndoFile->GetLastUndoEntry(Data_ForUpdate, iter); // PTS ? UH 2002-03-15

    Data_SplitSpaceReader   Reader (*iter, true); // PTS 1114994 UH 2002-04-17 added releasable
    Log_BeforeImage         BeforeImage;
    SAPDB_UInt              EntryCount = 0;

    #ifdef SAPDB_QUICK
    if ( ! iter.CheckAccessMode(Data_ForUpdate) )
    {
        iter.WriteToTrace("ErrorSplitSpace: wrong accessmode");
        BeforeImage.WriteToTrace("RollbackErrorImage");
        WriteToTrace("RollbackErrorTrans");
        RTE_Crash( SAPDBErr_Exception( __FILE__, __LINE__,
                                       SAPDBERR_ASSERT_STATE_FAILED,
                                       "Log_Transaction::Rollback() accessmode not update1" ) );
    }
    #endif

    if ( m_pTrans->trError_gg00 != e_ok ) // PTS 1117126 UH 2002-08-07
        Result = undoReadError;

    while ( iter.IsValid() )
    {
        Reader.Reset();
        bool isOK = true;
        BeforeImage.ReadPersistentFormat (Reader, isOK);
        if ( ! isOK )
        {
            Result = undoReadError;
            Kernel_VTrace() << "undo: (" << BeforeImage.GetSequence() << ") '"
                            << Log_GetActionTypeString(BeforeImage.GetActionType()) << "'";
            WriteToTrace("RollbackErrorTrans");
            Kernel_VTrace() << "ROLLBACK-ERROR: cannot read image";
            break;
        }


        if ( LOG_FIRST_ENTRY_SEQUENCE != PrevSequence )
        {
            if ( (PrevSequence - 1) != BeforeImage.GetSequence() )
            {
                Result = undoWrongEntry;
                Kernel_VTrace() << "undo: (" << BeforeImage.GetSequence() << ") '"
                                << Log_GetActionTypeString(BeforeImage.GetActionType()) << "'";
                iter.WriteToTrace("wrong sequences");
                BeforeImage.WriteToTrace("RollbackErrorImage");
                WriteToTrace("RollbackErrorTrans");
                Kernel_VTrace() << "ROLLBACK-ERROR: sequences not continguous";
                break;
            }
        }
        PrevSequence = BeforeImage.GetSequence();

        #ifdef SAPDB_QUICK
        if ( ! iter.CheckAccessMode(Data_ForUpdate) )
        {
            Kernel_VTrace() << "EntryCount: " << EntryCount;
            iter.WriteToTrace("ErrorSplitSpace: wrong accessmode");
            BeforeImage.WriteToTrace("RollbackErrorImage");
            WriteToTrace("RollbackErrorTrans");
            RTE_Crash( SAPDBErr_Exception( __FILE__, __LINE__,
                                           SAPDBERR_ASSERT_STATE_FAILED,
                                           "Log_Transaction::Rollback() accessmode not update1" ) );
        }
        #endif
        
        if ( BeforeImage.IsRollbacked(false)
             ||
             BeforeImage.IsDeleted(false) ) // PTS 1115828 UH 2002-05-17
		{
            if ( LogTrans_Trace.TracesLevel(6) )
            {
                Kernel_VTrace() << "skipped undo entry: (" << BeforeImage.GetSequence() << ") '"
                                << Log_GetActionTypeString(BeforeImage.GetActionType()) << "'";
                if ( BeforeImage.GetActionType() == Log_NewObject )
                {
                    Log_ActionObject action;
                    action.ReadPersistentFormat (Reader, Allocator(), isOK);
                    if ( isOK )
                        action.WriteToTrace("skipped undo entry: ");
                }
                if ( LogTrans_Trace.TracesLevel(7) )
                {
                    iter.WriteToTrace("skipped undo entry");
                    BeforeImage.WriteToTrace("skipped undo entry");
                }
            }
		}
        else
        {
            ++EntryCount;

            bool isOK = false;

            ExecuteUndoAction (BeforeImage, Reader, iter, isOK);

            if ( ! isOK )
            {
                Kernel_VTrace() << "ROLLBACK-ERROR: after ExecuteUndoAction: TrError: " << m_pTrans->trError_gg00;
                Kernel_VTrace() << "entry: ("
                                << BeforeImage.GetSequence() << ") '"
                                << Log_GetActionTypeString(BeforeImage.GetActionType()) << "'";
                BeforeImage.WriteToTrace("RollbackErrorImage");
                WriteToTrace("RollbackErrorTrans");
                Result = undoExecuteError;
                break;
            }
            #ifdef SAPDB_QUICK
            if ( ! iter.CheckAccessMode(Data_ForUpdate) )
            {
                Kernel_VTrace() << "EntryCount: " << EntryCount;
                iter.WriteToTrace("ErrorSplitSpace: wrong accessmode");
                BeforeImage.WriteToTrace("RollbackErrorImage");
                WriteToTrace("RollbackErrorTrans");
                RTE_Crash( SAPDBErr_Exception( __FILE__, __LINE__,
                                               SAPDBERR_ASSERT_STATE_FAILED,
                                               "Log_Transaction::Rollback() accessmode not update3" ) );
            }
            #endif
            
            // This MUST be placed AFTER the undo action.
            if ( BeforeImage.GetActionType() == Log_DeleteObject )
                BeforeImage.SetDeleted(true); // PTS 1115828 UH 2002-05-17
            else
                BeforeImage.SetRollbacked(true); // PTS 1114840 UH 2002-03-14
        }

        if ( (UndoStopSequence != LOG_FIRST_ENTRY_SEQUENCE)
             &&
             (UndoStopSequence == BeforeImage.GetSequence()) )
        {
            SAPDBTRACE_WRITELN (LogTrans_Trace, 6, "ROLLBACK-INFO: stop sequence reached");
            break;
        }

        --iter;
        *iter; // really assign the space
    }
    // release all resources (pages)
    iter.Invalidate();

    if ( undoOk == Result )
        if ( endOfTrans == rollbackKind )
            EndOfTransHandling (rollbacked);
        else
            // there was anything rollbacked and there are entries,
            // which must be skipped during redo
            if ( EntryCount > 0
                 &&
                 m_Context.LastRedoEntrySequence.IsValid()
                 &&
                 RedoStopSequence < m_Context.LastRedoEntrySequence + 1
                 &&
                 ! isRedoPartialRollback ) // PTS 1113230 UH 2001-12-20
            {
                switch  ( WritePartialRollbackEntry (UndoStopSequence,RedoStopSequence) )
                {
                    case Log_Transaction::noError:    
                        break;
                    case Log_Transaction::logFull:  
                        Result = undoLogFull;
                        Kernel_VTrace() << "ROLLBACK-ERROR: WritePartialRollbackEntry() logFull";
                        WriteToTrace("RollbackErrorTrans");
                        break;
                    case Log_Transaction::logError: 
                        Result = undoWriteError; 
                        Kernel_VTrace() << "ROLLBACK-ERROR: WritePartialRollbackEntry() logError";
                        WriteToTrace("RollbackErrorTrans");
                        break;
                    default:                        
                        RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,SAPDBERR_ASSERT_STATE_FAILED,
                        "Log_Transaction::Rollback(): invalid result of WriteRedoEntry") );
                }
            }

    if ( Result != undoOk )
        Kernel_VTrace() << "end-error: " << Result;

    return Result;
}

/* --------------------------------------------------------------------------- */
void Log_Transaction::ExecuteUndoAction
    (Log_BeforeImage        &BeforeImage,
     Data_SplitSpaceReader  &Reader,
     Log_UndoFile::Iterator &iter,
     bool                   &isOK)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::ExecuteUndoAction", LogTrans_Trace, 5);

    switch ( BeforeImage.GetActionType() )
    {
    case Log_NoOp:
        SAPDBTRACE_WRITELN (LogTrans_Trace, 6, "NoOp not possible");
        isOK = false;
        break;
    
    case Log_NewObject:
    case Log_InsertObject:
    case Log_UpdateObject:
    case Log_DeleteObject:
    case Log_LockObject:
        {
            Log_ActionObject ActionObject;
            
            ActionObject.ReadPersistentFormat (Reader, Allocator(), isOK);
            
            if ( ! isOK )
            {
                Kernel_VTrace() << "Log_Transaction::ExecuteUndoAction() action read failed.";
                return;
            }
            
            // the undo file resources must be released to avoid
            // a deadlock
            
            Data_PageNo       pageno;
            Data_PageOffset   offset;
            Log_EntrySequence checkSequence = BeforeImage.GetSequence();
            
            iter.GetPosition (pageno, offset);
            
            iter.Break();

            if ( LogTrans_Trace.TracesLevel(6) )
                ActionObject.WriteToTrace("Undo: ");
                
            ActionObject.Undo (*m_pTrans, BeforeImage, pageno, offset);
            
            isOK = (e_ok == m_pTrans->trError_gg00);
            
            if ( isOK )
            {
                iter.Continue();
                if ( ! iter.IsValid()  )
                {
                    Kernel_VTrace() << "*** ERROR: Continue() failed";
                    WriteToTrace("ExecuteUndoAction-trans");
                    BeforeImage.WriteToTrace("ExecuteUndoAction-image");
                    ActionObject.WriteToTrace("ExecuteUndoAction-action");
                    isOK = false;
                    return;
                }
                Reader.Reset();
                BeforeImage.ReadPersistentFormat (Reader, isOK);
                if ( ! isOK
                     ||
                     checkSequence != BeforeImage.GetSequence() )
                {
                    WriteToTrace("ExecuteUndoAction-trans");
                    BeforeImage.WriteToTrace("ExecuteUndoAction-image");
                    ActionObject.WriteToTrace("ExecuteUndoAction-action");
                    Kernel_VTrace() << "isOK: " << isOK;
                    isOK = false;
                }
            }
            else
            {
                ActionObject.WriteToTrace("UndoAction-Error");
                Kernel_VTrace() << "Log_Transaction::ExecuteUndoAction() action undo failed.";
                return;
            }
            break;
        }
    case Log_CreateObjectFile:
    case Log_DropObjectFile:
        Kernel_VTrace() << "Log_CreateObjectFile and Log_DropObjectFile are not allowed for undo.";
        m_pTrans->trError_gg00 = e_not_implemented;
        isOK = false;
        return;

    case Log_ReorganizeFile:
        {
            Log_ActionReorganizeFile action;
            UndoRedoAction (BeforeImage, action, iter, Reader, isOK);
            break;
        }

    case Log_UnloadFile:
        {
            Log_ActionUnloadFile action;
            
            UndoRedoAction (BeforeImage, action, iter, Reader, isOK);
            break;
        }
        
    case Log_ReloadFile:
        Kernel_VTrace() << "Log_ReloadFile is not allowed for undo.";
        m_pTrans->trError_gg00 = e_not_implemented;
        isOK = false;
        return;
        
    case Log_SetFileState:
        {
            Log_ActionSetFileState action;
            
            UndoRedoAction (BeforeImage, action, iter, Reader, isOK);
            break;
        }
        
    case Log_InsertRecord:
    case Log_DeleteRecord:
        {
            const bool IsBeforeImage = true;
            
            Log_ActionInsDelRec ActionInsDelRec (BeforeImage.GetActionType(), IsBeforeImage);
            
            UndoRedoAction (BeforeImage, ActionInsDelRec, iter, Reader, isOK);
            break;
        }
        
    case Log_UpdateRecord:
        {
            Log_ActionUpdateRec ActionUpdateRec;
            
            UndoRedoAction (BeforeImage, ActionUpdateRec, iter, Reader, isOK);
            break;
        }
        
        // Log_ModifyTable: redo only
        
    case Log_ChangeFileType:
        {
            Log_ActionChangeFileType ActionChangeFileType;
            
            UndoRedoAction (BeforeImage, ActionChangeFileType, iter, Reader, isOK);
            break;
        }
        
    case Log_CreateFile:
        {
            Log_ActionDropFile ActionDropFile;
            
            UndoRedoAction (BeforeImage, ActionDropFile, iter, Reader, isOK);
            break;
        }
        
        // Log_CreateIndex: redo only
        
        // Log_CreateTable: redo only
        
    case Log_RenameFile:
        {
            Log_ActionRenameFile ActionRenameFile;
            
            UndoRedoAction (BeforeImage, ActionRenameFile, iter, Reader, isOK);
            break;
        }
        
    case Log_SuccFileVersion:
        {
            Log_ActionSuccFileVersion ActionSuccFileVersion;
            
            UndoRedoAction (BeforeImage, ActionSuccFileVersion, iter, Reader, isOK);
            break;
        }
        
    case Log_UpdFileStatistic:
        {
            Log_ActionUpdFileStatistic ActionUpdFileStatistic;
            
            UndoRedoAction (BeforeImage, ActionUpdFileStatistic, iter, Reader, isOK);
            break;
        }
        
    case Log_CopyBlob:
        {
            Log_ActionCopyBlob ActionCopyBlob;
            
            UndoRedoAction (BeforeImage, ActionCopyBlob, iter, Reader, isOK);
            break;
        }
        
        // Log_CopySameBlob: redo only
        
        // Log_ExpandBlob: redo only
        
    case Log_TruncateBlob:
        {
            Log_ActionTruncateBlob ActionTruncateBlob;
            
            UndoRedoAction (BeforeImage, ActionTruncateBlob, iter, Reader, isOK);
            break;
        }
        
        // Log_UpdateBlob: redo only
        
        // Log_RefreshSequence: redo only
        
        // Log_RefreshSurrogate: redo only
        
    default:
        SAPDBTRACE_WRITELN (LogTrans_Trace, 6, "WARNING: rollback action for this type not defined");
        break;
    }
}

/* --------------------------------------------------------------------------- */
void Log_Transaction::ExecuteRedoAction
    (Log_AfterImage         &AfterImage,
     Log_IOSequenceNo        IOSequence,
     Data_SplitSpaceReader  &Reader,
     Rst_RedoFile::Iterator &iter,
     bool                   &isOK)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::ExecuteRedoAction", LogTrans_Trace, 5);

    // PTS 1114994 2002-03-22 begin
    
    isOK = true;
    
    Rst_IRedoTrafficControl &redocontrol = Rst_IRedoTrafficControl::Instance();
    
    if ( redocontrol.CheckIoSeq ( m_pTrans->trTaskId_gg00,
                                  m_pTrans->trWaitContext_gg00,
                                  IOSequence ) )
    {
        iter.Break();
        redocontrol.WaitForIoSeq (m_pTrans->trTaskId_gg00);
        UndoRedoContinue(AfterImage, iter, Reader, isOK);
        if ( ! isOK )
            return;
    }
    
    isOK = AfterImage.GetTransNo() == m_Context.TransNo;
    if ( ! isOK )
    {
        Kernel_VTrace() << "afterimage from wrong transaction: "
                        << "current: T" << m_Context.TransNo.gg90GetInt4()
                        << ", found entry for T" << AfterImage.GetTransNo().gg90GetInt4();
        AfterImage.WriteToTrace("image");
        iter.WriteToTrace("iterator");
        Reader.WriteToTrace("reader");
        return;
    }
    
    // PTS 1114994 2002-03-22 end

    if ( LogTrans_Trace.TracesLevel(6) )
		TraceEntry ( "Execute",
			         m_Context.TransNo,
				     IOSequence,
					 AfterImage.GetSequence(),
					 AfterImage.GetActionType() );

    switch ( AfterImage.GetActionType() )
    {
    case Log_NewObject:
    case Log_InsertObject:
    case Log_UpdateObject:
    case Log_DeleteObject:
        {
            Log_ActionObject ActionObject;
            ActionObject.ReadPersistentFormat (Reader, Allocator(), isOK);
            if ( isOK )
            {
                iter.Break(); // PTS 1114994 2002-03-22
    
                if ( LogTrans_Trace.TracesLevel(6) )
                    ActionObject.WriteToTrace("Execute: ");
    
                ActionObject.Redo (*m_pTrans, AfterImage);
    
                isOK = (e_ok == m_pTrans->trError_gg00);

                if ( isOK )
                    UndoRedoContinue(AfterImage, iter, Reader, isOK); // PTS 1114994 2002-03-22
            }
            
            if ( ! isOK )
            {
                Kernel_VTrace() << "action redo failed: BasisError: " << m_pTrans->trError_gg00;
                ActionObject.WriteToTrace("action");
            }
            break;
        }
    case Log_LockObject:
    case Log_ReorganizeFile:
        isOK = false; // undo only
        break;
    case Log_ReloadFile:
        {
            Log_ActionReloadFile action;
            UndoRedoAction (AfterImage, action, iter, Reader, isOK);
            break;
        }
    case Log_UnloadFile:
        {
            Log_ActionUnloadFile action;
            UndoRedoAction (AfterImage, action, iter, Reader, isOK);
            break;
        }
    case Log_SetFileState:
        {
            Log_ActionSetFileState action;
            
            UndoRedoAction (AfterImage, action, iter, Reader, isOK);
            break;
        }
    case Log_CreateObjectFile:
    case Log_DropObjectFile:
        {
            Log_ActionObjectFile Action;
            Action.ReadPersistentFormat (Reader, Allocator(), isOK);
            if ( isOK )
            {
                iter.Break(); // PTS 1114994 2002-03-22
    
                if ( LogTrans_Trace.TracesLevel(6) )
                    Action.WriteToTrace("Execute: ");
    
                Action.Redo (*m_pTrans, AfterImage);
    
                isOK = (e_ok == m_pTrans->trError_gg00);

                if ( isOK )
                    UndoRedoContinue(AfterImage, iter, Reader, isOK); // PTS 1114994 2002-03-22
            }
            
            if ( ! isOK )
            {
                Kernel_VTrace() << "action redo failed: BasisError: " << m_pTrans->trError_gg00;
                Action.WriteToTrace("action");
            }
            break;
        }
    case Log_DeleteAllObjects:
        {
            isOK = false;
            Kernel_VTrace() << "ActionDeleteAllObjects.Redo() not implemented";
            break;
//            Log_ActionDeleteAllObjects Action;
//            Action.ReadPersistentFormat (Reader, Allocator(), isOK);
//            if ( ! isOK )
//                break;
//            Action.Redo (*m_pTrans, AfterImage);
//            if ( m_pTrans->trError_gg00 != e_ok )
//            {
//                isOK = false;
//                Action.WriteToTrace("REDO-ERROR");
//                Kernel_VTrace() << "ActionDeleteAllObjects.Redo() failed with " << m_pTrans->trError_gg00;
//            }
//            break;
        }
    case Log_InsertRecord:
    case Log_DeleteRecord:
        {
            const bool NOT_IsBeforeImage = false;
            
            Log_ActionInsDelRec ActionInsDelRec (AfterImage.GetActionType(), NOT_IsBeforeImage);
            
            UndoRedoAction (AfterImage, ActionInsDelRec, iter, Reader, isOK);
            break;
        }
        
    case Log_UpdateRecord:
        {
            Log_ActionUpdateRec ActionUpdateRec;
            
            UndoRedoAction (AfterImage, ActionUpdateRec, iter, Reader, isOK);
            break;
        }
        
    case Log_ModifyTable:
        {
            Log_ActionModifyTable ActionModifyTable;
            
            UndoRedoAction (AfterImage, ActionModifyTable, iter, Reader, isOK);
            break;
        }
        
    case Log_ChangeFileType:
        {
            Log_ActionChangeFileType ActionChangeFileType;
            
            UndoRedoAction (AfterImage, ActionChangeFileType, iter, Reader, isOK);
            break;
        }
        
    case Log_CreateFile:
        {
            Log_ActionCreateFile ActionCreateFile;
            
            UndoRedoAction (AfterImage, ActionCreateFile, iter, Reader, isOK);
            break;
        }
        
    case Log_CreateIndex:
        {
            Log_ActionCreateIndex ActionCreateIndex;
            
            UndoRedoAction (AfterImage, ActionCreateIndex, iter, Reader, isOK);
            break;
        }
        
    case Log_CreateTable:
        {
            Log_ActionCreateTable ActionCreateTable;
            
            UndoRedoAction (AfterImage, ActionCreateTable, iter, Reader, isOK);
            break;
        }
        
    case Log_RenameFile:
        {
            Log_ActionRenameFile ActionRenameFile;
            
            UndoRedoAction (AfterImage, ActionRenameFile, iter, Reader, isOK);
            break;
        }
        
    case Log_SuccFileVersion:
        {
            Log_ActionSuccFileVersion ActionSuccFileVersion;
            
            UndoRedoAction (AfterImage, ActionSuccFileVersion, iter, Reader, isOK);
            break;
        }
        
    case Log_UpdFileStatistic:
        {
            Log_ActionUpdFileStatistic ActionUpdFileStatistic;
            
            UndoRedoAction (AfterImage, ActionUpdFileStatistic, iter, Reader, isOK);
            break;
        }
        
    case Log_CopyBlob:
        {
            Log_ActionCopyBlob ActionCopyBlob;
            
            UndoRedoAction (AfterImage, ActionCopyBlob, iter, Reader, isOK);
            break;
        }
        
    case Log_CopySameBlob:
        {
            Log_ActionCopySameBlob ActionCopySameBlob;
            
            UndoRedoAction (AfterImage, ActionCopySameBlob, iter, Reader, isOK);
            break;
        }
        
    case Log_ExpandBlob:
        {
            Log_ActionExpandBlob ActionExpandBlob;
            
            UndoRedoAction (AfterImage, ActionExpandBlob, iter, Reader, isOK);
            break;
        }
        
    case Log_TruncateBlob:
        {
            Log_ActionTruncateBlob ActionTruncateBlob;
            
            UndoRedoAction (AfterImage, ActionTruncateBlob, iter, Reader, isOK);
            break;
        }
        
    case Log_UpdateBlob:
        {
            Log_ActionUpdateBlob ActionUpdateBlob;
            
            UndoRedoAction (AfterImage, ActionUpdateBlob, iter, Reader, isOK);
            break;
        }
        
    case Log_RefreshSequence:
        {
            Log_ActionRefreshSequence ActionRefreshSequence;
            
            UndoRedoAction (AfterImage, ActionRefreshSequence, iter, Reader, isOK);
            break;
        }
        
    case Log_RefreshSurrogate:
        {
            Log_ActionRefreshSurrogate ActionRefreshSurrogate;
            
            UndoRedoAction (AfterImage, ActionRefreshSurrogate, iter, Reader, isOK);
            break;
        }
        
    default:
        Kernel_VTrace() << "Log_Transaction::ExecuteRedoAction: redo action for entry not defined";
        isOK = false;
        break;
    }
}

/* -------------------------------------------------------------------------------- */
Data_SplitSpaceWriter Log_Transaction::ReserveSpaceForRedoEntryCopy
        (Data_SplitRecordLength Length,
         Data_RecordLength      MinimalLength,
         Log_EntrySequence      EntrySequence,
         Log_IOSequenceNo       IOSequence)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::ReserveSpaceForRedoEntryCopy", LogTrans_Trace, 5);
    SAPDBERR_ASSERT_STATE ( IsInitializedForRedoCopy() );
    if ( ! m_pRedoFile->IsCreated() )
    {
        CreateRedoFile(*m_pTrans);
        m_OldestKnownIOSequence = IOSequence; // PTS 1127704 mb 2004-02-11
    }
    SAPDBERR_ASSERT_STATE ( m_pRedoFile->IsCreated() );
    #ifdef SAPDB_SLOW
    Kernel_VTrace() << "Length:        " << Length        << ", MinimalLength: " << MinimalLength;
    Kernel_VTrace() << "EntrySequence: " << EntrySequence << ", IOSequence: " << IOSequence;
    #endif
    Data_SplitSpaceWriter Writer = m_pRedoFile->ReserveSpace ( Length,
                                                               MinimalLength,
                                                               EntrySequence,
                                                               IOSequence );
    m_Context.RedoFileLastPageNo          = m_pRedoFile->LastPageNo();
    m_Context.LastCopiedRedoEntrySequence = EntrySequence;
    return Writer;
}

/* -------------------------------------------------------------------------------- */
void Log_Transaction::ReleaseSpaceAfterRedoEntryCopy(bool isOK)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::ReleaseSpaceAfterRedoEntryCopy", LogTrans_Trace, 5);
    SAPDBERR_ASSERT_STATE ( IsInitializedForRedoCopy() );
    SAPDBERR_ASSERT_STATE ( m_pRedoFile->IsCreated() );
    m_pRedoFile->ReleaseSpace(isOK);
    if ( !isOK ) //PTS1128760 mb 2004-03-25
        m_Context.RedoFileLastPageNo = Data_PageNo(); // set to invalid value
    
}


/* -------------------------------------------------------------------------------- */
Log_Transaction::LogState 
Log_Transaction::WriteRedoEntry (Log_AfterImage    &AfterImage,
                                 const Log_IAction &Action)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::WriteRedoEntry", LogTrans_Trace, 5);
    
    SAPDBERR_ASSERT_STATE ( IsInitialized() );
    #ifdef SAPDB_QUICK
    if ( (void*)k50GetLogTransaction (m_pTrans->trIndex_gg00) != (void*)this )
        RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,SAPDBERR_ASSERT_STATE_FAILED,
                   "Log_Transaction::WriteRedoEntry() logtransptr lost") );
    #endif
    

    Log_EntrySequence savedLastRedoEntrySequence = m_Context.LastRedoEntrySequence;
    if ( m_Context.LastRedoEntrySequence.IsValid() )
    {
        ++m_Context.LastRedoEntrySequence;
        if ( m_pTrans->trWriteTransId_gg00 != m_Context.TransNo )
            RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,SAPDBERR_ASSERT_STATE_FAILED,
                       "Log_Transaction::WriteRedoEntry: writetrans differs1") );
    }
    else
    {
        m_Context.LastRedoEntrySequence = LOG_FIRST_ENTRY_SEQUENCE;
        if ( m_Context.LastUndoEntrySequence.IsValid() )
        {
            if ( m_pTrans->trWriteTransId_gg00 != m_Context.TransNo )
                RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,SAPDBERR_ASSERT_STATE_FAILED,
                           "Log_Transaction::WriteRedoEntry: writetrans differs2") );
        }
        else
            m_Context.TransNo = m_pTrans->trWriteTransId_gg00;
    }

    AfterImage.SetTransNo          (m_Context.TransNo);
    AfterImage.SetSequence         (m_Context.LastRedoEntrySequence);
    AfterImage.SetLastUndoSequence (m_Context.LastUndoEntrySequence);
    

    if ( LocalRedoBufferSize != 0 // PTS 1131107 UH 2004-08-24
         &&
         AfterImage.GetActionType() != Log_MultipleActions )
    {
        if ( Action.LocalRedoEntryCashingPossible() )
        {
            if ( m_LocalRedoEntries.Append(AfterImage, Action) )
            {
                if ( LogTrans_Check.ChecksLevel(5) )
                    TraceEntry ( "WriteRedoEntry-Append",
                                 m_Context.TransNo,
                                 m_pTrans->trSubtransId_gg00,
                                 m_Context.LastRedoEntrySequence,
                                    AfterImage.GetActionType() );
                return noError;
            }
            if ( ! m_LocalRedoEntries.IsEmpty() )
            {
                // local buffer is full so flush it and then append current entry
                Log_AfterImage image (Log_MultipleActions);
                const LogState result = WriteRedoEntry (image,m_LocalRedoEntries);
                if ( result != noError )
                    return result;
                m_LocalRedoEntries.Reset();
                if ( m_LocalRedoEntries.Append(AfterImage, Action) )
                {
                    if ( LogTrans_Check.ChecksLevel(5) )
                        TraceEntry ( "WriteRedoEntry-Append",
                                     m_Context.TransNo,
                                     m_pTrans->trSubtransId_gg00,
                                     m_Context.LastRedoEntrySequence,
                                        AfterImage.GetActionType() );
                    return noError;
                }
            }
            // here: appending is not possible write the entry to the log as usual
        }
        else
        {
            // cached redo entries must be flushed before end of trans log entry
            if ( ! m_LocalRedoEntries.IsEmpty() )
            {
                Log_AfterImage image (Log_MultipleActions);
                const LogState result = WriteRedoEntry (image,m_LocalRedoEntries);
                if ( result != noError )
                    return result;
                m_LocalRedoEntries.Reset();
            }
        }
    }

    if ( LogTrans_Trace.TracesLevel(6) )
    	TraceEntry ( "WriteRedoEntry",
        	         m_Context.TransNo,
            	     m_pTrans->trSubtransId_gg00,
                	 m_Context.LastRedoEntrySequence,
               		 AfterImage.GetActionType() );

    const Data_SplitRecordLength LengthToReserve = 
                                    AfterImage.GetPersistentLength() 
                                    +
                                    Action.GetPersistentLength();
    const Data_SplitRecordLength MinLengthToReserve = 
                                    AfterImage.GetPersistentLength() 
                                    +
                                    Action.GetMinimalPersistentLength();
    
    SAPDBERR_ASSERT_ARGUMENT ( LengthToReserve >= MinLengthToReserve );

    Log_AfterImageSpace Space (Allocator());
    if (!Space.Initialize())
    {
        RTE_Crash( SAPDBErr_Exception(
                   __FILE__, __LINE__,
                   SAPDBERR_ASSERT_STATE_FAILED,
                   "Log_Transaction::WriteRedoEntry: space init failed") );
    }

    if ( m_pQueue != NULL )
    {        
        SAPDB_UInt2 offsetInPage;
        
        if ( Action.WaitForLogWriting() ) 	// PTS 1117320 UH 2002-10-28
        {
            SAPDBERR_ASSERT_ARGUMENT ( LengthToReserve == MinLengthToReserve );

            m_pQueue->ReserveForEOT (m_pTrans->trTaskId_gg00,
                                     m_pTrans->trWaitContext_gg00,
                                     LengthToReserve,
                                     Space,
                                     offsetInPage);
        }
        else
        {
            if (!m_pQueue->Reserve (  m_pTrans->trTaskId_gg00,
                                      m_pTrans->trWaitContext_gg00,
                                      LengthToReserve,
                                      MinLengthToReserve,
                                      Action.ForceLogWriting() // PTS 1117320 UH 2002-10-28
                                      ||
                                      m_pTrans->trState_gg00.includes(tsDbFullNowait_egg00), // UH 2003-02-18
                                      Space))
            {
                m_Context.LastRedoEntrySequence=savedLastRedoEntrySequence;
                return logFull;
            }
        }
        SAPDBERR_ASSERT_STATE ( LengthToReserve == Space.Length() );

        Data_SplitSpaceWriter Writer (Space);

        bool isOK=true;
        AfterImage.WritePersistentFormat (Writer, isOK);

        if ( ! isOK )
        {
            Writer.WriteToTrace("Log_Transaction::WriteRedoEntry::Writer");
            RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,
                       SAPDBERR_ASSERT_STATE_FAILED,
                       "Log_Transaction::WriteRedoEntry: WritePersistentFormat1 failed") );
        }

        Action.WritePersistentFormat (Writer, isOK);

        if ( ! isOK )
        {
            Writer.WriteToTrace("Log_Transaction::WriteRedoEntry::Writer");
            AfterImage.WriteToTrace("WriteRedoEntry/image:");
            Action.WriteToTrace("WriteRedoEntry/action:");
            Kernel_VTrace() << "TrError: " << m_pTrans->trError_gg00;
            WriteToTrace("WriteRedoEntry/trans:");
            RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,
                       SAPDBERR_ASSERT_STATE_FAILED,
                       "Log_Transaction::WriteRedoEntry: WritePersistentFormat2 failed") );
        }

        if ( Action.WaitForLogWriting() ) // PTS 1117320 UH 2002-10-28
        {
            Log_RawDeviceOffset offsetOnDevice;

            m_pQueue->UserTaskEOTReady (m_pTrans->trTaskId_gg00,
                                        m_pTrans->trWaitContext_gg00,
                                        Space,
                                        m_Context.EOT_IOSequenceNo,
                                        offsetOnDevice);

            SAPDBTRACE_WRITELN (LogTrans_Trace, 6, "EOT-entry written to: " << offsetOnDevice << \
                                              "." << offsetInPage << \
                                              " [" << m_Context.EOT_IOSequenceNo << "]");
        }
        else
        {
            m_pQueue->UserTaskReady (m_pTrans->trTaskId_gg00, Space);
        }
        
        if (!isOK)
        {
            return logError;
        }
    }
    return noError;
}

/* -------------------------------------------------------------------------------- */
Log_Transaction::LogState 
Log_Transaction::WritePartialRollbackEntry (Log_EntrySequence  UndoStopSequence,
                                            Log_EntrySequence  RedoStopSequence)
{
    Log_AfterImage            AfterImage (Log_PartialRollback);
    Log_ActionPartialRollback Action;
    
    if ( UndoStopSequence > m_Context.LastUndoEntrySequence )
    {
        Kernel_VTrace() << "UndoStopSequence: " << UndoStopSequence
                        << "lastUndoSequence: " << m_Context.LastUndoEntrySequence;
        WriteToTrace("WritePartialRollbackEntry:");
        RTE_Crash(SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED,"UndoStopSequence is invalid"));
    }
    
    Action.Initialize (UndoStopSequence, RedoStopSequence);
    return WriteRedoEntry(AfterImage, Action);
}

/* -------------------------------------------------------------------------------- */
bool Log_Transaction::WriteEndOfTransEntry (TransState State)
{
    SAPDBERR_ASSERT_STATE (opened != State);
    
    if (State==committed)
    // prepare a commit-entry with timestamp
    {
        Log_AfterImage             AfterImage (Log_Commit);
        Log_ActionEndOfTransaction Action;
        Kernel_DateTime            currentTime;

        currentTime.DetermineTime();
        Action.Initialize (currentTime);
        return (noError == WriteRedoEntry(AfterImage, Action));     
    }
    else
    // write simple Rollback-entry
    {
        Log_AfterImage       AfterImage (Log_Rollback);
        return (noError == WriteRedoEntry (AfterImage, Log_ActionEndOfTransaction()));
    }
}

/* -------------------------------------------------------------------------------- */
void Log_Transaction::Commit ()
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::Commit", LogTrans_Trace, 5);

    SAPDBTRACE_IF (LogTrans_Trace, 6, WriteToTrace ("Log_Transaction::Commit"));
    
    SAPDBERR_ASSERT_STATE (opened == GetTransState());
    
    // ++++ TEMP LOGGING SHOULD BE OBSOLETE
    if ( m_pTrans->trState_gg00.includes (tsTempUpdated_egg00) )
        k54commit_temp (*m_pTrans);
    // ++++ TEMP LOGGING SHOULD BE OBSOLETE

    EndOfTransHandling (committed);
}

/* -------------------------------------------------------------------------------- */
Log_Transaction::RedoResult Log_Transaction::Redo()
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::Redo", LogTrans_Trace, 5);

    SAPDBERR_ASSERT_STATE ( IsInitializedForRedo() );

    SAPDBERR_ASSERT_STATE ( m_pRedoFile != NULL );

    // don't  remove undo file here, remove it at trans-end

    SAPDBTRACE_IF (LogTrans_Trace, 6, WriteToTrace ("CurrentTrans"));
    
    if ( ! m_pRedoFile->IsCreated() )
    {
        EndOfTransHandling(committed);
        return redoOk;
    }

    Rst_RedoFile::Iterator& iter = m_pRedoFile->GetFirstRedoEntry();
    Data_SplitSpaceReader   Reader (*iter, true); // PTS 1114994 UH 2002-04-17 added releasable
    Log_AfterImage          AfterImage;
//    Log_EntrySequence       PrevSequence       = LOG_FIRST_ENTRY_SEQUENCE;
    Log_EntrySequence       CurrSequence       = LOG_FIRST_ENTRY_SEQUENCE;
    RedoResult              Result             = redoOk;
    Log_IOSequenceNo        IOSequence;

    if ( m_pTrans->trError_gg00 != e_ok ) // PTS 1117126 UH 2002-08-07
        Result = redoReadError;
    
    while ( iter.IsValid() )
    {
        Reader.Reset();
        bool isOK = true;
        
        m_pRedoFile->GetEntryInfo (Reader, IOSequence, CurrSequence, isOK);
        
        if ( ! isOK )
        {
            Result = redoReadError;
            SAPDBTRACE_WRITELN (LogTrans_Trace, 6, "REDO-ERROR: cannot read IOSequence");
            break;
        }
        
        AfterImage.ReadPersistentFormat (Reader, isOK);
        
        if ( ! isOK )
        {
            Result = redoReadError;
            AfterImage.WriteToTrace("REDO-ERROR: image");
            WriteToTrace("REDO-ERROR: trans");
            Kernel_VTrace() << "REDO-ERROR: cannot read after image";
            Result = redoWrongEntry;
            break;
        }

        if ( m_Context.TransNo.gg90GetInt4() != AfterImage.GetTransNo().gg90GetInt4() )
        {
            AfterImage.WriteToTrace("REDO-ERROR: image");
            WriteToTrace("REDO-ERROR: trans");
            Kernel_VTrace() << "REDO-ERROR: contextTransNo: " << m_Context.TransNo.gg90GetInt4()
                            << ", entryTransNo: " << AfterImage.GetTransNo().gg90GetInt4();
            Result = redoWrongEntry;
            break;
        }
//        if ( LOG_FIRST_ENTRY_SEQUENCE != PrevSequence )
//        {
//            if ( (PrevSequence + 1) != AfterImage.GetSequence() )
//            {
//                Kernel_VTrace() << "REDO-ERROR: sequences not continguous";
//                Result = redoWrongEntry;
//                break;
//            }
//        }
//        PrevSequence = AfterImage.GetSequence();

        if ( AfterImage.IsDone() )
        {
            SAPDBTRACE_WRITELN (LogTrans_Trace, 6, "REDO-INFO: entry skipped");
        }
        else
        {
            bool isOK;
            ExecuteRedoAction (AfterImage, IOSequence, Reader, iter, isOK);
            if ( ! isOK )
            {
                Kernel_VTrace() << "REDO-EXECUTE-ERR: TrError: " << m_pTrans->trError_gg00;
                Kernel_VTrace() << "entry: ("
                                << AfterImage.GetSequence() << ") '"
                                << Log_GetActionTypeString(AfterImage.GetActionType()) << "'";
                AfterImage.WriteToTrace("REDO-EXECUTE-ERROR: image");
                WriteToTrace("REDO-EXECUTE-ERROR: trans");
                Result = redoExecuteError;
                break;
            }
            AfterImage.SetIsDone();
        }

        ++iter;
        *iter; // really assign the space
    }
    
    if ( Result != redoOk )
    {
        Data_PageNo     pageno;
        Data_PageOffset offset;
        iter.GetPosition (pageno, offset);
        Kernel_VTrace() << "redoposition: " << pageno << "." << offset;
    }
    
    // release all resources (pages)
    iter.Invalidate();

    if ( Result == redoOk )
        EndOfTransHandling (committed);

    SAPDBTRACE_WRITELN (LogTrans_Trace, 6, "end: " << (Result==redoOk?"ok":"ERROR"));

    return Result;
}

/* -------------------------------------------------------------------------------- */
void  Log_Transaction::RedoPartialRollback (Log_EntrySequence UndoStopSequence,
                                            Log_EntrySequence RedoStopSequence)
{
    // PTS 1113230 UH 2001-12-20 new (from TruncateRedoFile)
    
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::RedoPartialRollback", LogTrans_Trace, 5);
    SAPDBERR_ASSERT_STATE   ( m_pRedoFile != NULL );
    
	if ( LogTrans_Trace.TracesLevel(6) )
    {
        Kernel_VTrace() << "UndoStopSequence: " << UndoStopSequence
                        << ", RedoStopSequence: " << RedoStopSequence;
        WriteToTrace("RedoPartialRollback");
    }

    // PTS 1113230 UH 2001-12-20 begin
    if ( m_Context.LastUndoEntrySequence.IsValid()
         &&
         UndoStopSequence.IsValid()
         &&
         UndoStopSequence <= m_Context.LastUndoEntrySequence )
    {
        tgg91_TransNo auxTransNo = m_pTrans->trWriteTransId_gg00;
        
        m_pTrans->trWriteTransId_gg00 = m_Context.TransNo;
        
        // The partial rollback needs to go before the last savepoint.
        // These changes have to be rollbacked.
        m_pUndoFile = new (Allocator()) Log_UndoFile ( *m_pTrans,
                                                       m_Context.UndoFileRootPageNo,
                                                       m_Context.UndoFileLastPageNo );
        if ( m_pUndoFile == NULL )
            RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,
                       SAPDBERR_ASSERT_STATE_FAILED,
                       "allocation of Log_UndoFile failed") );
        m_pTrans->trLogContext_gg00 = this;
        RollbackResult result = Rollback (command, LOG_NIL_SUBTRANS_NO, UndoStopSequence);
        if ( result != undoOk )
        {
            Kernel_VTrace() << "result: " << result;
            WriteToTrace("redo-of-partial-rollback");
            RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,
                       SAPDBERR_ASSERT_STATE_FAILED,
                       "error during redo of partial rollback") );
        }
        m_pUndoFile->Invalidate();
        Allocator().Deallocate(m_pUndoFile);
        m_pUndoFile                   = NULL;
        m_pTrans->trLogContext_gg00   = NULL;
        m_pTrans->trWriteTransId_gg00 = auxTransNo;
    }
    // PTS 1113230 UH 2001-12-20 end
        
    if ( GetTransState() != opened || ! m_pRedoFile->IsCreated() )
        // The partial rollback entry may be the first entry read after the savepoint
        // for a transaction which was open during savepoint.
        // So there is no redofile which can be truncated.
        return;
    
    // StopSequence is the last Sequence which was rollbacked
    m_Context.LastCopiedRedoEntrySequence = RedoStopSequence-1;
    // the truncate synchronizes with the prepare phase of the savepoint
    // Truncate() truncates everything which is greater then the given sequence
    m_pRedoFile->Truncate(RedoStopSequence-1);
    // After truncation the context value must be updated
    m_Context.RedoFileLastPageNo = m_pRedoFile->LastPageNo(); // PTS 1111344 UH 2001-08-10
}

/* -------------------------------------------------------------------------------- */
void Log_Transaction::SetEOTInRedo (TransState        eotState,
                                    Log_IOSequenceNo  eotSequence)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::SetEOTInRedo", LogTrans_Trace, 5);
    
    SAPDBERR_ASSERT_STATE   ( m_pRedoFile != NULL   );
    SAPDBERR_ASSERT_STATE   ( m_TransType != online );
    
    m_Context.TransStatePersistent = eotState; // PTS 1114721 UH 2002-03-07 added again
    m_Context.EOT_IOSequenceNo     = eotSequence;
}

/* -------------------------------------------------------------------------------- */
bool Log_Transaction::IsSavepointRelevant()
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::IsSavepointRelevant", LogTrans_Trace, 5);
    
    bool isRelevant = (SAPDB_MAX_INT4 != m_Context.UndoFileRootPageNo
                       ||
                       SAPDB_MAX_INT4 != m_Context.RedoFileRootPageNo);

    SAPDBTRACE_WRITELN (LogTrans_Trace, 6, "isRelevant: " << isRelevant);
    
    return isRelevant;
}

/* -------------------------------------------------------------------------------- */
void Log_Transaction::GiveUndoFileToHistory()
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::GiveUndoFileToHistory", LogTrans_Trace, 5);
    kb50EnterTransRegion (m_pTrans->trTaskId_gg00, m_pTrans->trIndex_gg00);
    m_Context.UndoFileRootPageNo = SAPDB_MAX_INT4;
    kb50LeaveTransRegion (m_pTrans->trTaskId_gg00, m_pTrans->trIndex_gg00);
    Log_History::GetInstance().RegisterUndoFile (*m_pTrans, *m_pUndoFile);
    m_pUndoFile->Invalidate();
}

/* -------------------------------------------------------------------------------- */
void Log_Transaction::UpdateUndoRedoInfoForRestart(const Log_IOSequenceNo oldestKnownIOSeq)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::UpdateUndoRedoInfoForRestart", LogTrans_Trace, 5);

	SAPDBERR_ASSERT_STATE ( IsInitializedForRedoCopy() );
    
    m_pUndoFile = new (Allocator()) Log_UndoFile ( *m_pTrans,
                                                   m_Context.UndoFileRootPageNo,
                                                   m_Context.UndoFileLastPageNo );
    if ( m_pUndoFile == NULL )
        RTE_Crash( SAPDBErr_Exception(__FILE__, __LINE__,
                   SAPDBERR_ASSERT_STATE_FAILED,
                   "allocation of Log_UndoFile failed") );

    #ifdef SAPDB_QUICK
    if ( m_pUndoFile->IsCreated() )
    {
        Kernel_VTrace() << "UpdateUndoRedoInfoForRestart: UndoFileLastPageNo "
                        << m_Context.UndoFileLastPageNo << " -> "
                        << m_pUndoFile->LastPageNo() << FlushLine;
        Kernel_VTrace() << "UpdateUndoRedoInfoForRestart: LastUndoEntrySequence "
                        << m_Context.LastUndoEntrySequence << " -> "
                        << m_pUndoFile->GetLastEntrySequence() << FlushLine;
    }
    if ( m_pRedoFile->IsCreated() )
    {
        Kernel_VTrace() << "UpdateUndoRedoInfoForRestart: RedoFileLastPageNo "
                        << m_Context.RedoFileLastPageNo << " -> "
                        << m_pRedoFile->LastPageNo() << FlushLine;
        Kernel_VTrace() << "UpdateUndoRedoInfoForRestart: LastCopiedRedoEntrySequence "
                        << m_Context.LastRedoEntrySequence << " -> "
                        << m_pRedoFile->GetLastEntrySequence() << FlushLine;
    }
    #endif
    
    if ( m_pUndoFile->IsCreated() )
    {
        m_Context.UndoFileLastPageNo    = m_pUndoFile->LastPageNo();
        m_Context.LastUndoEntrySequence = m_pUndoFile->GetLastEntrySequence();
    }

    m_pUndoFile->Invalidate();
    destroy (m_pUndoFile, Allocator());
    m_pUndoFile = NULL;

    if ( m_pRedoFile->IsCreated() )
    {
        m_Context.RedoFileLastPageNo          = m_pRedoFile->LastPageNo();
        m_Context.LastCopiedRedoEntrySequence = m_pRedoFile->GetLastEntrySequence();
    }
    m_OldestKnownIOSequence = oldestKnownIOSeq; //PTS 1127704 mb 2004-02-16
}

/* -------------------------------------------------------------------------------- */
void Log_Transaction::UndoRedoContinue (Log_IImage             &image,
                                        Data_IBreakable        &iter,
                                        Data_SplitSpaceReader  &reader,
                                        bool                   &isOK)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::UndoRedoContinue", LogTrans_Trace, 5);
        
    Log_IOSequenceNo iosequence;

    isOK = iter.Continue();
    
    if ( ! isOK )
    {
        Kernel_VTrace() << "After Continue() error";
        TraceEntry ("entry",m_Context.TransNo,iosequence,image.GetSequence(),image.GetActionType());
        iter.WriteToTrace("iterator");
        return;
    }

    Log_EntrySequence checkSequence = image.GetSequence();
    
    reader.Reset();
    
    if ( image.IsAfterImage() )
    {
        Log_EntrySequence entrySequence;
        
        Rst_RedoFile::GetEntryInfo(reader, iosequence, entrySequence, isOK);
        
        if ( ! isOK )
        {
            Kernel_VTrace() << "After Continue() Error after reading redo file header";
            TraceEntry ("entry",m_Context.TransNo,iosequence,image.GetSequence(),image.GetActionType());
            iter.WriteToTrace("iterator");
            return;
        }
        
        isOK = checkSequence == entrySequence;
        
        if ( ! isOK )
        {
            Kernel_VTrace() << "After Continue() unexpetcted redo entry sequence: " << checkSequence << " != " << entrySequence;
            TraceEntry ("entry",m_Context.TransNo,iosequence,image.GetSequence(),image.GetActionType());
            iter.WriteToTrace("iterator");
            return;
        }
    }

    image.ReadPersistentFormat (reader, isOK);

    if ( ! isOK )
    {
        Kernel_VTrace() << "After Continue() error during read image";
        reader.WriteToTrace("reader");
        TraceEntry ("entry",m_Context.TransNo,iosequence,image.GetSequence(),image.GetActionType());
        iter.WriteToTrace("iterator");
        return;
    }
    
    isOK = image.GetSequence() == checkSequence;
           
    if ( ! isOK )
    {
        Kernel_VTrace() << "After Continue() wrong entry: "
                        << "checkSequence " << checkSequence
                        << " != "           << image.GetSequence();
        reader.WriteToTrace("reader");
        TraceEntry ("entry",m_Context.TransNo,iosequence,image.GetSequence(),image.GetActionType());
        iter.WriteToTrace("iterator");
        return;
    }
}

/* -------------------------------------------------------------------------------- */
void Log_Transaction::UndoRedoAction (Log_IImage             &image,
                                      Log_IAction            &action,
                                      Data_IBreakable        &iter,
                                      Data_SplitSpaceReader  &reader,
                                      bool                   &isOk)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::UndoRedoAction", LogTrans_Trace, 5);
    
    action.ReadPersistentFormat (reader, Allocator(), isOk);
    
    if ( ! isOk )
    {
        Kernel_VTrace() << "ExecuteUndoRedoAction() error during action read";
        return;
    }

    iter.Break();
    
    action.Execute (*m_pTrans);

    isOk = (e_ok == m_pTrans->trError_gg00);
    
    if ( isOk )
        UndoRedoContinue (image, iter, reader, isOk);
}

/* -------------------------------------------------------------------------------- */
const char* Log_RollbackResultStrings [] =
{
	"undoOk",
    "undoNoOpenSubtrans",
    "undoReadError",
    "undoWrongEntry",
    "undoExecuteError",
    "undoWriteError",
    "undoLogFull"
};

/* -------------------------------------------------------------------------------- */
inline SAPDB_UInt GetMinimalLengthOfActionToCopy (Log_ActionType type)
{
	// PTS 1131107 UH 2004-08-24 added
    switch (type)
    {
        case Log_NewObject:
        case Log_InsertObject:
        case Log_UpdateObject:
        case Log_DeleteObject:
            return Log_ActionObject::GetMinimalLengthToCopyEntry();
            break;
        case Log_PartialRollback:
            return Log_ActionPartialRollback::GetMinimalLengthToCopyEntry();
            break;
        case Log_SavepointEntry:
        case Log_FinishOpenTrans:
            return Log_ActionSavepoint::GetMinimalLengthToCopyEntry();
            break;
        case Log_MultipleActions:
            return Log_ActionMultiple::GetMinimalLengthToCopyEntry();
            break;
        default:
            return 0;
    }
    return 0;
}
/* -------------------------------------------------------------------------------- */
Data_SplitSpaceWriter Log_Transaction::GetWriterForLocalRedoEntries(SAPDB_Byte *pActionHead,
                                                                    SAPDB_UInt sizeToReserve)
{
	// PTS 1131107 UH 2004-08-24 new
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::GetWriterForLocalRedoEntries", LogTrans_Trace, 5);
    if (! m_LocalRedoEntries.Reserve(pActionHead, sizeToReserve) )
        RTE_Crash( Log_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED,
                   "m_LocalRedoEntries.Reserve()") );
    return Data_SplitSpaceWriter(m_LocalRedoEntries.GetBuffer());
}

/* -------------------------------------------------------------------------------- */
bool Log_Transaction::RestoreLocalRedoEntries (Log_IOSequenceNo iosequence)
{
	// PTS 1131107 UH 2004-08-24 new
    SAPDBTRACE_METHOD_DEBUG ("Log_Transaction::RestoreLocalRedoEntries", LogTrans_Trace, 5);

    Log_AfterImage                image;
    SAPDB_UInt                    actionLength;
    const SAPDB_Byte             *pActionSpace;
    Log_ActionMultiple::Iterator  actioniter  = m_LocalRedoEntries.GetFirstAction();
    Data_SplitSpaceWriter::Result writeResult = Data_SplitSpaceWriter::ok;
    bool                          isOK        = true;

    #ifdef SAPDB_SLOW
    m_LocalRedoEntries.WriteToTrace("Log_Transaction::RestoreLocalRedoEntries()");
    SAPDB_UInt actionno = 1;
    #endif
    
    while ( actioniter.GetAction(image, actionLength, pActionSpace) )
    {
        #ifdef SAPDB_SLOW
        Kernel_VTrace() << "MultipleActions: internal #" << actionno++;
        image.WriteToTrace("IMAGE");
        Kernel_VTrace() << "GetLastCopiedRedoEntrySequence() = " << GetLastCopiedRedoEntrySequence();
        #endif
        if ( actionLength > LocalRedoBufferSize )
        {
            Kernel_VTrace() << "actionLength is invalid" << actionLength;
            return false;
        }
        
        if ( (m_Context.LastRedoEntrySequence.IsInvalid()
              ||
              image.GetSequence() >= m_Context.LastRedoEntrySequence)
             &&
             (GetLastCopiedRedoEntrySequence().IsInvalid()
              ||
              image.GetSequence() > GetLastCopiedRedoEntrySequence()) )
        {
            #ifdef SAPDB_SLOW
            Kernel_VTrace() << "IS COPIED";
            #endif
            Data_SplitSpaceWriter writer = ReserveSpaceForRedoEntryCopy
                                ( actionLength + image.GetPersistentLength(),
                                  GetMinimalLengthOfActionToCopy(image.GetActionType())
                                  + image.GetPersistentLength(),
                                  image.GetSequence(),
                                  iosequence );
            image.SetTransNo(GetRedoTransNo());
            image.WritePersistentFormat(writer, isOK);
            if ( ! isOK )
                return false;
                
            writer.Write (pActionSpace, actionLength, writeResult);
            
            if ( writeResult != Data_SplitSpaceWriter::ok )
            {
                ReleaseSpaceAfterRedoEntryCopy(false);
                return false;
            }
            ReleaseSpaceAfterRedoEntryCopy(true);
        }
        else
        {
            #ifdef SAPDB_SLOW
            Kernel_VTrace() << "IS NOT COPIED";
            #endif
        }
        actioniter.Next();
    }
    m_LocalRedoEntries.Reset();
    return true;
}

// -----------------------------------------------------------------------------
void Log_Transaction::DetermineLocalRedoBufferSize()
{
	// PTS 1131107 UH 2004-08-24
    const SAPDB_UTF8 *         paramName    = UTF8("LOCAL_REDO_LOG_BUFFER_SIZE");
    RTEConf_Parameter::Integer size = 0;
    SAPDBErr_MessageList       error;

    if ( RTEConf_ParameterAccess::Instance() == 0 )
    {
        RTE_Message (Log_Exception(__CONTEXT__,LOG_LOCAL_REDO_BUFFER_SIZE_SET, "0"));
        return;
    }

    if ( ! RTEConf_ParameterAccess::Instance()->GetInteger(paramName, size, error) )
    {
        RTE_Message (error);
        RTE_Message (Log_Exception(__CONTEXT__,LOG_LOCAL_REDO_BUFFER_SIZE_SET, "0"));
        return;
    }
    
    if ( size > SAPDB_MAX_UINT4 )
    {
        RTE_Message(Log_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED,"size <= SAPDB_MAX_UINT4"));
        RTE_Message(Log_Exception(__CONTEXT__,LOG_LOCAL_REDO_BUFFER_SIZE_SET, "0"));
        return;
    }

    LocalRedoBufferSize = static_cast<SAPDB_UInt>(size);
    
	RTE_Message(Log_Exception(__CONTEXT__,LOG_LOCAL_REDO_BUFFER_SIZE_SET,
                              SAPDB_ToString(LocalRedoBufferSize)));
}

/*===========================================================================*
 *  END OF CODE                                                              *
 *===========================================================================*/
