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

  module      : Kernel_DumpPage.hpp

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

  responsible : TorstenS

  special area: Definition of a kernel dump page
  description : This class is used to store main memory structures on a
                dump page.


  last changed: 2001-06-07  16:22
  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


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


#ifndef KERNEL_DUMPPAGE_HPP
#define KERNEL_DUMPPAGE_HPP



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

#include "KernelCommon/Kernel_Common.hpp"
#include "KernelCommon/Kernel_Page.hpp"
#include "SAPDBCommon/Fields/SAPDBFields_Field.hpp"

/*===========================================================================*
 *  DEFINES                                                                  *
 *===========================================================================*/

#define KERNEL_DUMP_LABEL_LENGTH    8
#define KERNEL_DUMP_FILL_BYTE       0xFE

/*===========================================================================*
 *  MACROS                                                                   *
 *===========================================================================*/


/*===========================================================================*
 *  CLASSES, STRUCTURES, TYPES, UNIONS ...                                   *
 *===========================================================================*/


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

   class: Kernel_DumpPage

   description: This class is used to store main memory structures on a
                dump page.
              
*******************************************************************************/

class Kernel_DumpPage : public Kernel_Page
{
public:

    /* -----------------------------------------------------------------------*/
    /*! declarations: Type definitions                                        */
    /* -----------------------------------------------------------------------*/

    typedef SAPDBFields_Field   Entry;

    /* -----------------------------------------------------------------------*/
    /*! enddeclarations:                                                      */
    /* -----------------------------------------------------------------------*/

    /* -----------------------------------------------------------------------*/
    /*! chapter: Constructors and initialization                              */
    /* -----------------------------------------------------------------------*/

    /*!-------------------------------------------------------------------------
    function:     Kernel_DumpPage()
    description:  This is the default constructor of a dump page..
    arguments:    none
    return value: none
    --------------------------------------------------------------------------*/

    Kernel_DumpPage()
    :m_InsertPosition( 0 )
    {}

    /*!-------------------------------------------------------------------------
    function:     Kernel_DumpPage()
    description:  Construct a dump page with a given page image. 
                  No initialization is done.
    arguments:    Frame [in] dump page
    return value: none
    --------------------------------------------------------------------------*/

    Kernel_DumpPage( const PageFrame &Frame )
    :
    Kernel_Page( Frame ),
    m_InsertPosition( 0 )
    {}

    /*!-------------------------------------------------------------------------
    function:     InitializeFrame()
    description:  Initializes frame contents of a dump page. The dump page
                  consists of a eight byte ordinary page header followed by
                  a eight byte dump label, a dump code and a counter which 
                  specifies who often the dump entry with the same dump 
                  label occurs on the current page.
    arguments:    PageNo    [in] consecutive numbering of the dump pages
                  DumpLabel [in] string identifier for the given dump entry
                  DumpCode  [in] numeric identifier for the given dump entry
    return value: none
    --------------------------------------------------------------------------*/

    void InitializeFrame(
        SAPDB_UInt4     PageNo,
        SAPDB_Char      *DumpLabel,
        SAPDB_UInt2     DumpCode )
    {
        WritePageId( PageNo );
        WritePageType( Kernel_DumpPageType );
        PersistentHeaderPtr()->m_KernelPageHeader.m_ParityOrPageType2 = 0;
        PersistentHeaderPtr()->m_KernelPageHeader.m_Filler            = 0;
        memcpy( PersistentHeaderPtr()->m_DumpLabel, DumpLabel,
                sizeof( PersistentHeaderPtr()->m_DumpLabel ));
        PersistentHeaderPtr()->m_DumpCode = DumpCode;
        PersistentHeaderPtr()->m_Counter = 0;

        m_InsertPosition = GetHeaderSize();
    }

    /*!-------------------------------------------------------------------------
    function:     InitializeFrame()
    description:  Initializes page without writing dump page specific 
                  informations on it. This is necessary for page dumps.
    arguments:    none
    return value: none
    --------------------------------------------------------------------------*/

    void InitializeFrame()
    {
        m_InsertPosition = 0;
    }

    /* -----------------------------------------------------------------------*/
    /*! endchapter: Constructors and initialization                           */
    /* -----------------------------------------------------------------------*/

    /* -----------------------------------------------------------------------*/
    /*! chapter: Input/Output operations                                      */
    /* -----------------------------------------------------------------------*/

    /*!-------------------------------------------------------------------------
    function:     CheckAfterRead()
    description:  Prepares page for input from device
                  - Performs check on the frame contents
    arguments:    none
    return value: true if check successful
    --------------------------------------------------------------------------*/

    virtual SAPDB_Bool CheckAfterRead() const
    {
        return( Kernel_DumpPageType == ReadPageType() );
    }

    /*!-------------------------------------------------------------------------
    function:     PrepareForWrite()
    description:  Prepares page for output to device
                  - Fills the remaining space of the dump page with a special 
                    symbol
                  - Applicable immediately before a page is written to device
    arguments:    none
    return:       true if check successful
    --------------------------------------------------------------------------*/

    virtual SAPDB_Bool PrepareForWrite()
    {
        if( 0 == RemainingSpace() )
            return( true );

        memset( m_Frame.GetPointer( m_InsertPosition, RemainingSpace() ),
                KERNEL_DUMP_FILL_BYTE, RemainingSpace() );

        m_InsertPosition = m_Frame.GetLength();
        return( true );
    }

    /*!-------------------------------------------------------------------------
    function:     Verify()
    description:  Verifies consistency of page contents
    arguments:    none
    return:       true if verify successful
    --------------------------------------------------------------------------*/

    virtual SAPDB_Bool Verify() const
    {
        return( CheckAfterRead() );
    }

    /* -----------------------------------------------------------------------*/
    /*! endchapter: Input/Output operations                                   */
    /* -----------------------------------------------------------------------*/

    /* -----------------------------------------------------------------------*/
    /*! chapter: Update operations                                            */
    /* -----------------------------------------------------------------------*/

    /*!-------------------------------------------------------------------------
    function:     Insert()
    description:  This method appends a dump entry to the current dump page.
                  It is a assumed that the given dump entry belongs to the 
                  dump entries already store within the page.
                  All stored dump entries on this page titled with the same
                  dump label and dump code! After each successful insert the
                  counter for the stored dump entries will be incremented.
                  Note that the writing of dump entries greater than a dump 
                  page less the header size is not supported by this method!
    arguments:    DumpEntry [in] given dump entry
    return value: true means insert was successful; else false
    --------------------------------------------------------------------------*/

    SAPDB_Bool Insert( const Entry  &DumpEntry )
    {
        SAPDBERR_ASSERT_STATE( DumpEntry.IsAssigned() );

        const SAPDB_UInt4 EntrySize = DumpEntry.GetLength();

        if( ! IsSpaceAvailable( EntrySize ))
            return( false );

        memcpy( m_Frame.GetPointer( m_InsertPosition, RemainingSpace() ),
                DumpEntry.GetPointer( 0, EntrySize ), EntrySize );

        m_InsertPosition += DumpEntry.GetLength();

        // Count the number of equal dump entries on this page.
        // This is necessary for the analyzer of the dump.
        PersistentHeaderPtr()->m_Counter = PersistentHeaderPtr()->m_Counter + 1;

        return( true );
    }

    /*!-------------------------------------------------------------------------
    function:     InsertPage()
    description:  This method inserts a given page in the current dump page.
                  It is expected that the current dump page is empty!
    arguments:    Page [in] kernel page handler
    return value: true if insert was successfully; else false
    --------------------------------------------------------------------------*/

    SAPDB_Bool InsertPage( const Kernel_Page  &Page )
    {
        SAPDBERR_ASSERT_STATE( 0 == m_InsertPosition );
        SAPDBERR_ASSERT_STATE( Page.IsAssigned() );
        SAPDBERR_ASSERT_STATE( m_Frame.GetLength() == Page.GetFrame().GetLength() );

        if( ! IsSpaceAvailable( Page.GetFrame().GetLength() ))
            return( false );

        memcpy( GetFramePtr(), Page.GetFrame().GetDataPtr(), m_Frame.GetLength());

        //memcpy( GetFramePtr(), Page.GetFramePtr(), m_Frame.GetLength() ); TODO

        m_InsertPosition = m_Frame.GetLength();

        return( true );
    }

    /*!-------------------------------------------------------------------------
    function:     IsSpaceAvailable()
    description:  This method examines whether the given space for the new dump
                  entry is still available on the dump page.
    arguments:    WantedSpace [in] size in bytes of the requested space.
    return value: true means space is available; else false
    --------------------------------------------------------------------------*/

    SAPDB_Bool IsSpaceAvailable( SAPDB_UInt4 WantedSpace ) const
    {
        return( RemainingSpace() >= WantedSpace );
    }

    /*!-------------------------------------------------------------------------
    function:     IsUsed()
    description:  This method indicates whether a dump page contains dump entries.
    arguments:    none
    return value: true means page contains dump entries; else false
    --------------------------------------------------------------------------*/

    SAPDB_Bool IsUsed() const
    {
        return(( this->IsAssigned() ) && ( m_InsertPosition > 0 ));
    }

    /* -----------------------------------------------------------------------*/
    /*! endchapter: Update operations                                         */
    /* -----------------------------------------------------------------------*/

private:

    struct PersistentHeader
    {
        Kernel_Page::PersistentHeader m_KernelPageHeader;
        SAPDB_Char                    m_DumpLabel[ KERNEL_DUMP_LABEL_LENGTH ];
        SAPDB_UInt2                   m_DumpCode;
        SAPDB_UInt2                   m_Counter;
    };

    PersistentHeader* PersistentHeaderPtr()
    {
        return reinterpret_cast< PersistentHeader* >( m_Frame.GetDataPtr());
    }

    const PersistentHeader* PersistentHeaderPtr() const
    {
        return reinterpret_cast< const PersistentHeader* >( m_Frame.GetDataPtr());
    }

    virtual Kernel_Page::SizeType GetHeaderSize() const
    {
        return( sizeof( PersistentHeader ));
    }

    virtual Kernel_Page::SizeType GetTrailerSize() const
    {
        return( 0 );
    }

    SAPDB_UInt4 RemainingSpace() const
    {
        return( m_Frame.GetLength() - m_InsertPosition );
    }

private:

    /*-------------------------------------------------------------------------
    declaration: m_InsertPosition
    description: Position within the page at which the next dump entry
                 will be materialized. This is the first unused byte!
    --------------------------------------------------------------------------*/

    SAPDB_UInt4 m_InsertPosition;
};

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

   endclass: Kernel_DumpPage

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



#endif  /* KERNEL_DUMPPAGE_HPP */
