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

  module      : Log_UndoFile.hpp
  special area: Logging
  responsible : UweH
  created     : 2000-09-25  12:00
  last changed: 2000-10-27  12:00
  copyright:    (c) 2000-2004 SAP AG
  description : defines the classes Log_UndoFile, Log_UndoFileEntry



    ========== licence begin  GPL
    Copyright (c) 2000-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


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


#ifndef Log_UndoFile_H
#define Log_UndoFile_H

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

#include "ggg00.h"

#include "SAPDBCommon/SAPDB_Types.hpp"

#include "DataAccess/Data_PageAccessManager.hpp"
#include "DataAccess/Data_ChainSplitSpaceBackwardRead.hpp"
#include "DataAccess/Data_BaseFile.hpp"

#include "Logging/Log_Exceptions.hpp"
#include "Logging/Log_BeforeImage.hpp"
#include "Logging/Log_IAction.hpp"

class SAPDBMem_IRawAllocator;

/*! --------------------------------------------------------------------------------
class:       Log_UndoPage
description: 
*/

class Log_UndoPage : public Data_PageSplitSpaceBackwardRead
{

public:

    /*! ---------------------------------------------------------------------------
    function:    Verify
    */
    virtual SAPDB_Bool Verify() const
    {
        if ( ! this->IsAssigned() )
            return SAPDB_TRUE;
            
        const SAPDB_Byte* pFrame = this->FramePtr();
        const Data_PageOffset firstFreeOffset = this->FirstFreeOffset(pFrame);
    	if ( firstFreeOffset < this->MinSpaceOffset()
             ||
             firstFreeOffset > this->MaxSpaceOffset() )
        {
            RTE_Message( Log_Exception(__CONTEXT__,
                                     LOG_UNDOPAGE_VERIFY,
                                     SAPDB_ToString(this->PageNo()),
                                     SAPDB_ToString(firstFreeOffset) ) );
            return SAPDB_FALSE;
        }
        else
            return SAPDB_TRUE;
	}

    /*! ---------------------------------------------------------------------------
    function:    ~Log_UndoPage
    */
    ~Log_UndoPage()
    {
        if ( this->Verify() != SAPDB_TRUE )
            RTE_Crash( SAPDBErr_Exception(__CONTEXT__,
                                          SAPDBERR_ASSERT_STATE_FAILED,
                                          "Verify() failed") );
    }
    
    /*! ---------------------------------------------------------------------------
    function:    InitializeFrame
    */
    virtual void InitializeFrame ()
    {
        Data_PageSplitSpace::InitializeFrame();
        NodePtr()->nd_trans_id().gg90SetNil();
        SetLastEntrySequence(Log_EntrySequence());
    }

    /*! --------------------------------------------------------------------------------
    function:     SetTransNo
    descriptions: The TransNo is written to the page header.
    */
    void SetTransNo (const tgg91_TransNo& TransNo)
    {
        SAPDBERR_ASSERT_STATE(IsAssigned());
        NodePtr()->nd_trans_id() = TransNo;
    }

    /*! --------------------------------------------------------------------------------
    function:     GetTransNo
    descriptions: The TransNo is read from the page header.
    */
    tgg91_TransNo GetTransNo ()
    {
        SAPDBERR_ASSERT_STATE(IsAssigned());
        return NodePtr()->nd_trans_id();
    }
    
    /*! --------------------------------------------------------------------------------
    function:     SetPageCount
    descriptions: This saves the give pagecount in the pageheader.
    */
    void SetPageCount (SAPDB_UInt pagecount)
    {
        SAPDBERR_ASSERT_STATE(IsAssigned());
        NodePtr()->ndLeafCount_bd00() = SAPDB_Int4(pagecount);
    }

    /*! --------------------------------------------------------------------------------
    function:     GetPageCount
    descriptions: reads out the saved pagecount
    */
    SAPDB_UInt GetPageCount ()
    {
        SAPDBERR_ASSERT_STATE(IsAssigned());
        return SAPDB_UInt(NodePtr()->ndLeafCount_bd00());
    }
    /*! --------------------------------------------------------------------------------
    function:     SetLastEntrySequence
    descriptions: The entry sequence of the last entry in the page is set in
                  the page header.
    arguments:    entrySequence [in]
    */
    void SetLastEntrySequence (Log_EntrySequence entrySequence)
    {
        SAPDBERR_ASSERT_STATE(IsAssigned());
        NodePtr()->ndInvUsageCnt_bd00() = entrySequence;
    }
    /*! --------------------------------------------------------------------------------
    function:     GetLastEntrySequence
    descriptions: The entry sequence of the last entry is returned.
    returns:      entrySequence
    */
    Log_EntrySequence GetLastEntrySequence () const
    {
        SAPDBERR_ASSERT_STATE(IsAssigned());
        return NodePtr()->ndInvUsageCnt_bd00();
    }
    /*! --------------------------------------------------------------------------------
    function:    SaveLastGarbageCollectorPosition
    */
    // PTS ? UH 2002-03-15 new
    void SaveLastGarbageCollectorPosition (Data_PageNo     pageno,
                                           Data_PageOffset offset)
    {
        SAPDBERR_ASSERT_STATE(IsAssigned());
        NodePtr()->nd_filler4() = offset;
        NodePtr()->ndInvRoot_bd00() = pageno; // PTS 1120695 UH 2003-10-27
    }

    /*! --------------------------------------------------------------------------------
    function:    GetLastGarbageCollectorPosition
    description: 
    */
    // PTS ? UH 2002-03-15 new
    void GetLastGarbageCollectorPosition (Data_PageNo     &pageno,
                                          Data_PageOffset &offset)
    {
        SAPDBERR_ASSERT_STATE(IsAssigned());
        offset = NodePtr()->nd_filler4();
        pageno = NodePtr()->ndInvRoot_bd00(); // PTS 1120695 UH 2003-10-27
    }

};
/*! endclass: Log_UndoPage */

/*---------------------------------------------------------------------------*/
/*! class:       Log_UndoFile
    description: This is the Interface to undo log manager.
*/
class Log_UndoFile : public Data_BaseFile
{

public:
    
    /*! --------------------------------------------------------------------------------
    declaration: Container, Iterator, BeforeImageId
    description: These types are used with this class.
    */
    typedef Data_ChainSplitSpaceBackwardRead<Log_UndoPage>  Container;
    typedef Container::Iterator                             Iterator;
    typedef Data_ChainIterator<Log_UndoPage>                PageIterator;
    typedef Container::RecordSpace                          EntrySpace;

    /*! enddeclaration: */

public:

    /*! --------------------------------------------------------------------------------
    function:    Log_UndoFile
    arguments:   Trans [in/out]
                 Root  [in]
                 Last  [in]
    description: This constructs an undo log handle for the given transaction.
                 If the RootPageNo is valid, an existing file is assumed.
    */
    Log_UndoFile (tgg00_TransContext &Trans,
                  const Data_PageNo   Root,
                  const Data_PageNo   Last);
              
    /*! --------------------------------------------------------------------------------
    function:    Log_UndoFile
    arguments:   Pam   [in/out]
                 Allocator [in]
                 Root  [in]
                 Last  [in]
    description: This constructs an undo log handle for the given transaction.
                 If the RootPageNo is valid, an existing file is assumed.
    */
    Log_UndoFile (Data_PageAccessManager &Pam,
                  SAPDBMem_IRawAllocator &Allocator,
                  const tgg91_TransNo    &TransNo,
                  const Data_PageNo       Root,
                  const Data_PageNo       Last);
              
    /*! --------------------------------------------------------------------------------
    function:    ~Log_UndoFile
    description: The file is dropped.
    */
    ~Log_UndoFile ();

    /*! ---------------------------------------------------------------------------
    function:    Create
    returns:     true, if successfull
    description: A new UndoLogfile is created, the transNo is written into the root.
    */
    virtual bool Create ();

    /*! ---------------------------------------------------------------------------
    function:    Drop
    description: A UndoLogfile is dropped.
    */
    virtual void Drop ();

    /*! ---------------------------------------------------------------------------
    function:    Verify
    returns:     true, if the file is consistent
    */
    virtual bool Verify(bool isCold);

    /*! ---------------------------------------------------------------------------
    function:    WriteToTrace
    description: This traces some basic information about the file to the trace.
    */
    virtual void WriteToTrace (const char * title = 0) const;

    /*! ---------------------------------------------------------------------------
    function:    Invalidate
    returns:     (Data_PageId) root
    description: The file is not dropped, but all resources are released
    */
    void Invalidate ()
    {
        m_Iterator.Invalidate();
        m_Iterator.Delete();
        m_Container.Invalidate();
        m_RootId.Invalidate();
    }

    /*! ---------------------------------------------------------------------------
    function:    CheckSpace
    returns:     bool
    description: true is returned if Reserve() will find enough pages.
                 The task can be supended !
    */
    bool CheckSpace()
    {
		// PTS 1115593 UH 2002-05-07 new
        return m_Container.CheckSpace();
    }

    /*! --------------------------------------------------------------------------------
    description: This type defines alle return values from WriteBeforeImage()
    */
    enum WriteBeforeImageResult // PTS 1121659 UH 2003-04-30 new
    {
        writeBeforeImageOk,
        writeBeforeImageError,
        writeBeforeImageNoSpaceAvailable
    };
    /*! --------------------------------------------------------------------------------
    function:    WriteBeforeImage
    arguments:   BeforeImage  [in]
                 Action       [in]
	returns:     WriteBeforeImageResult
    description: The given BeforeImage is written into the undo file.

                 m_LastEntrySequence is incremented and written into the before image.
                 The internal iterator is set to the write position.
                 At the end the resoruce the iterator points to is deassigned.
                 These are the pages of the undo log file.
    */
    WriteBeforeImageResult WriteUndoEntry (Log_BeforeImage   &beforeimage,
                                           const Log_IAction &action,
                                           Data_PageNo       &pageno,
                                           Data_PageOffset   &offset);

    /*! ---------------------------------------------------------------------------
    function:    GetIterator
    returns:     The internal Iterator.
    description: Only the iterator is given. It may be invalid.
    */
    Iterator& GetIterator ()
    {
        return m_Iterator;
    }

    /*! ---------------------------------------------------------------------------
    function:    GetLastUndoEntry
    arguments:   accessmode [in]
                 iter       [in/out]
    description: The internal RecordIterator is set to the last record in the chain.
                 The internal RecordSpace is assigned.
    */
    void GetLastUndoEntry (Data_AccessMode     accessmode,
                           Iterator           &iter);

    /*! ---------------------------------------------------------------------------
    function:    GetUndoEntry
    arguments:   pageno     [in]
                 offset     [in]
                 accessmode [in]
                 maxsize    [in]
                 iter       [out]
    description: This is used by consistent read and DeleteBeforeImage.
                 If the iterator is valid, the split space is completly
                 loaded.
                 If the size at the found position is greater then
                 maxsize the iterator is invalidated.
                 If maxsize is 0 it is ignored.
    */
    void GetUndoEntry (Data_PageNo             pageno,
                       Data_PageOffset         offset,
                       Data_AccessMode         accessmode,
                       Data_SplitRecordLength  maxsize,
                       Iterator               &iter);

    /*! --------------------------------------------------------------------------------
    function:    GetLastEntrySequence
    description: determinies the last entry sequence written to this file.
    returns:     entrysequence
    */
    Log_EntrySequence GetLastEntrySequence ();

    /*! ---------------------------------------------------------------------------
    function:    LastPageNo
    returns:     Data_PageNo
    description: If the container does not know the last page no it is determined.
    */
    Data_PageNo& LastPageNo ()
    {
        return m_Container.LastPageNo();
    }

    /*! ---------------------------------------------------------------------------
    function:    GetTransNo
    returns:     TransNo of the file.
    */
    const tgg91_TransNo& GetTransNo ()
    {
        return m_TransNo;
    }

    /*! ---------------------------------------------------------------------------
    function:    GetPageCount
    returns:     SAPDB_UInt Number of pages in this file.
    */
    SAPDB_UInt GetPageCount ();

    /*! ---------------------------------------------------------------------------
    function:    SavePageCount
    description: the internal pagecount is set in root page
    */
    void SavePageCount ();

    /*! --------------------------------------------------------------------------------
    function:    SaveLastGarbageCollectorPosition
    description: 
    */
    // PTS ? UH 2002-03-15
    void SaveLastGarbageCollectorPosition (Data_PageNo     pageno,
                                           Data_PageOffset offset);

    /*! --------------------------------------------------------------------------------
    function:    GetLastGarbageCollectorPosition
    description: 
    */
    // PTS ? UH 2002-03-15
    void GetLastGarbageCollectorPosition (Data_PageNo     &pageno,
                                          Data_PageOffset &offset);

private:

    /*! --------------------------------------------------------------------------------
    variable:    m_Container
    description: The container for this file.
    */
    Container m_Container;

    /*! --------------------------------------------------------------------------------
    variable:    m_Iterator
    description: The iterator for the container.
    */
    Iterator m_Iterator;

    /*! --------------------------------------------------------------------------------
    variable:    m_TransNo
    description: The transaction which own this file.
    */
    /// transno for this file
    const tgg91_TransNo &m_TransNo;
    
    /*! --------------------------------------------------------------------------------
    variable:    m_PageCount
    description: The number of pages used by this container.
    */
    SAPDB_UInt m_PageCount;
};
/*! endclass: Log_UndoFile */


/*===========================================================================*
 *  DEFINITION OF INLINE METHODS                                              *
 *===========================================================================*/
                                         
#endif  /* Log_UndoFile_H */
