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

    module      : Log_ReadWriteActionImage.cpp

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

    author         :JuergenA
    responsible : UweH

    special area: Logging
    description : defines a class to read/write before and after images of any action

    last changed: 2001-03-28

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

    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 "Logging/Log_ReadWriteActionImage.hpp"

#include "SAPDBCommon/SAPDB_Types.hpp"
#include "SAPDBCommon/MemoryManagement/SAPDBMem_IRawAllocator.hpp"
#include "SAPDBCommon/Tracing/SAPDBTrace_Usage.hpp" // Routine trace macros
#include "DataAccess/Data_ISplitSpace.hpp"
#include "KernelCommon/Kernel_Trace.hpp"
#include "Logging/Log_Types.hpp"
#include "Logging/Log_AfterImage.hpp"
#include "Logging/Log_BeforeImage.hpp"
#include "Logging/Log_Transaction.hpp"

#include "ggg00.h"

#include <memory.h> // memset, memcpy

/*===========================================================================*
*  METHODS of Log_ActionImageReader                                          *
*============================================================================*/

void Log_ActionImageReader::PersistentRead (SAPDB_Byte             *&pImage,
                                            SAPDB_UInt4              ImageLen,
                                            SAPDBMem_IRawAllocator *&pUsedAllocator,
                                            bool                    &IsOk)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_ActionImageReader::PersistentRead", LogAction_Trace, 5);

    KERNEL_TRACE_IS_OK (IsOk, LogAction_Trace, 5);
    
    Data_SplitSpaceReader::Result ReadResult;
    
    bool bAllocatorUsed = false;
    
    this->m_SplitSpaceReader.Read (
        Log_AlignedImageLen (ImageLen),
        pImage,
        this->m_IRawAllocator,
        bAllocatorUsed,
        ReadResult);
    
    pUsedAllocator = ( bAllocatorUsed ) ? &(this->m_IRawAllocator) : NULL;
    
    IsOk = 
        ((Data_SplitSpaceReader::ok                 == ReadResult)
        ||
        ( Data_SplitSpaceReader::moreSpaceAvailable == ReadResult) );
    
    SAPDBTRACE_IF (LogAction_Trace, 6, \
        if ( IsOk ) \
            Kernel_TraceBuffer (pImage, ImageLen); \
        else \
            Kernel_VTrace() << "ReadResult: "   << ReadResult \
                            << ", AlignedLen: " << Log_AlignedImageLen (ImageLen); );
}

//---------------------------------------------------------------------------

void Log_ActionImageReader::CopyImage (SAPDB_Byte  *pImage,
                                       SAPDB_UInt4  ImageLen,
                                       bool        &IsOk)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_ActionImageReader::CopyImage", LogAction_Trace, 5);

    SAPDB_Byte             *pImageForRead;
    SAPDBMem_IRawAllocator *pImageAllocator = NULL;
    
    this->PersistentRead (pImageForRead, ImageLen, pImageAllocator, IsOk);
    
    if (IsOk) memcpy (pImage, pImageForRead, ImageLen);
    
    if (NULL != pImageAllocator)
    {   
        pImageAllocator->Deallocate (pImageForRead);
    }
}

/*===========================================================================*
*  METHODS of Log_ActionImageWriter                                          *
*============================================================================*/

void Log_ActionImageWriter::AlignImage (SAPDB_UInt4  WrittenLength,
                                        bool        &IsOk)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_ActionImageWriter::AlignImage", LogAction_Trace, 5);
    
    KERNEL_TRACE_IS_OK (IsOk, LogAction_Trace, 5);
    
    SAPDB_UInt4 AlignedLen = Log_AlignedImageLen (WrittenLength);
    
    if (AlignedLen > WrittenLength)
    {
        SAPDB_Byte PaddingBytes[7];
        
        memset (PaddingBytes, 0, 7);
        
        this->m_SplitSpaceWriter.Write (PaddingBytes, AlignedLen - WrittenLength, this->m_WriteResult);
        
        IsOk = this->IsResultOk();
        
        SAPDBTRACE_IF (LogAction_Trace, 6,\
            {\
                Kernel_VTrace() << "PaddingBytes: " << AlignedLen - WrittenLength;\
                if ( ! IsOk)\
                    Kernel_VTrace() << "m_WriteResult: " << m_WriteResult;\
            } );
    }
}

//----------------------------------------------------------------------------

void Log_ActionImageWriter::UnalignedPersistentWrite (const void  *pSource,
                                                      SAPDB_UInt4  SourceLen,
                                                      bool        &IsOk)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_ActionImageWriter::UnalignedPersistentWrite", LogAction_Trace, 5);
    
    KERNEL_TRACE_IS_OK (IsOk, LogAction_Trace, 5);
    SAPDBTRACE_IF   (LogAction_Trace, 6, Kernel_TraceBuffer (pSource, SourceLen));
    
    this->m_SplitSpaceWriter.Write (
        REINTERPRET_CAST (const SAPDB_Byte*, pSource),
        SourceLen,
        this->m_WriteResult);
    
    IsOk = this->IsResultOk();
    
    SAPDBTRACE_IF (LogAction_Trace, 6, \
        if ( ! IsOk) \
        { \
            Kernel_VTrace() << "SourceLen: " << SourceLen \
                            << ", m_WriteResult: " << m_WriteResult; \
        } );
}


/*===========================================================================*
*  METHODS of Log_ReadWriteActionImage                                       *
*============================================================================*/

void Log_ReadWriteActionImage::ReadPersistentFormat (Data_SplitSpaceReader  &Reader,
                                                     SAPDBMem_IRawAllocator &Allocator,
                                                     bool                   &IsOk)
{
    SAPDBTRACE_METHOD_DEBUG ("Log_ReadWriteActionImage::ReadPersistentFormat", LogAction_Trace, 5);

    KERNEL_TRACE_IS_OK (IsOk, LogAction_Trace, 5);
    
    Log_ActionImageReader ActionImageWriter (Reader, Allocator);
    
    this->ReadImagePersistent (ActionImageWriter, IsOk);
}

//----------------------------------------------------------------------------

void Log_ReadWriteActionImage::WriteAfterImage (tgg00_TransContext &TransContext) const
{
    SAPDBTRACE_METHOD_DEBUG ("Log_ReadWriteActionImage::WriteAfterImage", LogAction_Trace, 5);
    
    KERNEL_TRACE_BASIS_ERROR (TransContext.trError_gg00, LogAction_Trace, 5);

    if (e_ok != TransContext.trError_gg00) return;
    
    if (Log_NoOp == this->m_ActionType)
    {
        TransContext.trError_gg00 = e_invalid;
        return;
    }
    
    Log_AfterImage AfterImage (this->m_ActionType);
    
    switch (REINTERPRET_CAST(Log_Transaction*,TransContext.trLogContext_gg00)->
        WriteRedoEntry (AfterImage, *this))
    {
        case Log_Transaction::noError:
            break;
        case Log_Transaction::logFull:
            TransContext.trError_gg00 = e_log_full;
            break;
        case Log_Transaction::logError:
            TransContext.trError_gg00 = e_log_error;
            break;
        default:
            RTE_Crash( SAPDBErr_Exception(
                       __CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED,
                       "invalid result of WriteRedoEntry") );
    }
        
}

//----------------------------------------------------------------------------

void Log_ReadWriteActionImage::WriteBeforeImage (tgg00_TransContext &TransContext) const
{
    SAPDBTRACE_METHOD_DEBUG ("Log_ReadWriteActionImage::WriteBeforeImage", LogAction_Trace, 5);
    
    KERNEL_TRACE_BASIS_ERROR (TransContext.trError_gg00, LogAction_Trace, 5);

    if (e_ok != TransContext.trError_gg00) return;
    
    if (Log_NoOp == this->m_ActionType)
    {
        TransContext.trError_gg00 = e_invalid;
        return;
    }
    
    Log_BeforeImage BeforeImage (this->m_ActionType);
    Data_PageNo     unusedPageNo;
    Data_PageOffset unusedOffset;
    
    // PTS 1121659 UH 2003-04-30 begin - more result checking
    Log_Transaction &logtrans = *(reinterpret_cast<Log_Transaction*>(TransContext.trLogContext_gg00));
    switch ( logtrans.WriteUndoEntry (BeforeImage, *this, unusedPageNo, unusedOffset) )
    {
        case Log_UndoFile::writeBeforeImageOk:
            TransContext.trError_gg00 = e_ok;
            break;
        case Log_UndoFile::writeBeforeImageError:
            TransContext.trError_gg00 = e_log_error;
            break;
        case Log_UndoFile::writeBeforeImageNoSpaceAvailable:
            TransContext.trError_gg00 = e_work_rolled_back;
            break;
        default:
            TransContext.trError_gg00 = e_log_error;
            break;
    }
    // PTS 1121659 UH 2003-04-30 end
}

//----------------------------------------------------------------------------

void Log_ReadWriteActionImage::WritePersistentFormat (Data_SplitSpaceWriter &Writer,
                                                      bool                  &IsOk) const
{
    SAPDBTRACE_METHOD_DEBUG ("Log_ReadWriteActionImage::WritePersistentFormat", LogAction_Trace, 5);
    
    KERNEL_TRACE_IS_OK (IsOk, LogAction_Trace, 5);

    Log_ActionImageWriter ActionImageWriter (Writer);
    
    this->WriteImagePersistent (ActionImageWriter, IsOk);

    if ( ! IsOk ) return;
    
    IsOk = ActionImageWriter.IsWrittenCompletely ();
    
    SAPDBTRACE_IF(LogAction_Trace, 6, \
        if ( ! IsOk)
            Kernel_VTrace() << "WriteResult: " << ActionImageWriter.WriteResultValue(); \
            );
}

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