/*!
    @ingroup        Restart
    @file           Rst_RedoFile.hpp
    @author         UweH
    @brief          defines the classes Rst_RedoFile
*/
/*
    ========== 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 Rst_Redo_H
#define Rst_Redo_H

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

#include "SAPDBCommon/SAPDB_Types.hpp"
#include "DataAccess/Data_ChainSplitSpaceForwardRead.hpp"
#include "DataAccess/Data_BaseFile.hpp"
#include "Logging/Log_AfterImageSpace.hpp"
#include "Logging/Log_Types.hpp"

class tgg91_TransNo;
class Data_PageAccessManager;
class SAPDBMem_IRawAllocator;

/*===========================================================================*
 *  DEFINES                                                                  *
 *===========================================================================*/
/*===========================================================================*
 *  MACROS                                                                   *
 *===========================================================================*/
/*===========================================================================*
 *  EXTERNAL VARIABLES                                                       *
 *===========================================================================*/
/*===========================================================================*
 *  CLASSES, STRUCTURES, TYPES, UNIONS ...                                   *
 *===========================================================================*/

/*!
  @class          Rst_RedoPage
   @brief         defines a page of Redo-Entries 

 */


class Rst_RedoPage : public Data_PageSplitSpaceForwardRead
{

public:

    /*!
     * @brief       this method inializes the neccessary PageFrame 
     */
    virtual void InitializeFrame ()
    {
        Data_PageSplitSpace::InitializeFrame();
        NodePtr()->nd_trans_id().gg90SetNil();
        SetFirstEntrySequence (0);
        SetLastEntrySequence(Log_EntrySequence());
    }

    /*!
       @brief   The TransNo is written to the page header.
       @param        TransNo [in] 
     */
    void SetTransNo (const tgg91_TransNo& TransNo)
    {
        SAPDBERR_ASSERT_STATE(IsAssigned());
        NodePtr()->nd_trans_id() = TransNo;
    }

    /*!
       @brief   The TransNo is read from the page header.
       @returns        TransNo
     */
    tgg91_TransNo GetTransNo () const
    {
        SAPDBERR_ASSERT_STATE(IsAssigned());
        return NodePtr()->nd_trans_id();
    }

    /*!
       @brief   The entry sequence of the first entry in the page is set in
                the page header.
       @param   entrySequence [in] 

     */
    void SetFirstEntrySequence (Log_EntrySequence entrySequence)
    {
        SAPDBERR_ASSERT_STATE(IsAssigned());
        NodePtr()->nd_str_version() = entrySequence;
    }

    /*!
       @brief   The entry sequence of the first entry is returned.
       @returns entry sequence

     */
    Log_EntrySequence GetFirstEntrySequence () const
    {
        SAPDBERR_ASSERT_STATE(IsAssigned());
        return NodePtr()->nd_str_version();
    }

    /*!
       @brief   The entry sequence of the last entry in the page is set in
                the page header.
       @param   entrySequence [in] 

     */
    void SetLastEntrySequence (Log_EntrySequence entrySequence)
    {
        SAPDBERR_ASSERT_STATE(IsAssigned());
        NodePtr()->ndInvUsageCnt_bd00() = entrySequence;
    }

    /*!
       @brief   The entry sequence of the last entry is returned.
       @return  an entrySequence

     */

    Log_EntrySequence GetLastEntrySequence () const
    {
        SAPDBERR_ASSERT_STATE(IsAssigned());
        return NodePtr()->ndInvUsageCnt_bd00();
    }
};


/*---------------------------------------------------------------------------*/
/*!
  @class          Rst_RedoFile
   @brief          This is the Interface to Redo log manager.

 */

class Rst_RedoFile : public Data_BaseFile
{

public:
    
    /// In this container all Redo-Etries of one Transaction are collected
    typedef Data_ChainSplitSpaceForwardRead<Rst_RedoPage>  Container;

    /// iterator upon an RedoFile; used for reading the redo-entries
    typedef Container::Iterator                            Iterator;

    /// iterator representing the PageChain of an RedoFile
    typedef Data_ChainIterator<Rst_RedoPage>               PageIterator;

    typedef Container::RecordSpace                         EntrySpace; ///< This is object which is referenced by the iterator.

public:

    /*!
        @brief This constructs an Redo log handle for the given transaction.
        If the RootPageNo is valid, an existing file is assumed.
    */

    Rst_RedoFile (tgg00_TransContext &Trans,
                  const Data_PageNo   Root,
                  const Data_PageNo   Last);

    /// variant with other pam for verify
    Rst_RedoFile (Data_PageAccessManager &Pam,
                  SAPDBMem_IRawAllocator &Allocator,
                  const tgg91_TransNo    &TransNo,
                  const Data_PageNo       Root,
                  const Data_PageNo       Last);

    /// The file is dropped.
    ~Rst_RedoFile ();

    virtual bool Create ();
    virtual void Drop ();
    /// Releases all memory of this objectinstance, but the File
    /// remains persistent. PTS 1131934 mb 2004-10-14
    void Delete ();
    virtual bool Verify (bool isCold);
    virtual void WriteToTrace (const char * title = 0) const;

    /// returns the saved transno member
    const tgg91_TransNo& GetTransNo ()
    {
        return m_TransNo;
    }

    /// the io sequence is extracted.
    static void GetEntryInfo (Data_SplitSpaceReader &Reader,
                              Log_IOSequenceNo      &IOSequence,
                              Log_EntrySequence     &EntrySequence,
                              bool                  &isOK);
                                    
    /*!
        @brief          Space is reserved. the first part has minimum size of MinimalLength.

        The internal iterator is set to the space.
        You have to use ReleaseSpace() after writing everything into the reserved space.
     */
    Data_SplitSpaceWriter ReserveSpace (Data_SplitRecordLength Length,
                                        Data_RecordLength      MinimalLength,
                                        Log_EntrySequence      EntrySequence,
                                        Log_IOSequenceNo       IOSequence);

    /*!
        @brief The internal iterator is deassigned,
        So all resources are released.
        If isOK is false, all pareserved pages are released unchanged.
     */
    void ReleaseSpace(bool isOK);

    /// Sets the internal iterator to the first record in the file.
    Iterator& GetFirstRedoEntry ()
    {
        SAPDBERR_ASSERT_STATE( IsCreated() );

        m_Container.Begin (m_Iterator, Data_ForUpdate); // not Data_ForRead !!

        return m_Iterator;
    }

	/// determinies the last entry sequence written to this file.
    Log_EntrySequence GetLastEntrySequence ();

	/// determines the last page no.
    Data_PageNo LastPageNo()
    {
        SAPDBERR_ASSERT_STATE( IsCreated() );

        return m_Container.LastPageNo();
    }

	/// this truncates the file, so the last entry has the given sequence no.
    void Truncate (Log_EntrySequence stopSequence);

private:

	/// this holds additional information for entry handling
    typedef struct EntryHead
    {
        /// the sequence-number of this LogEntry in this transaction 
        Log_EntrySequence Sequence;

        /// the global sequence-number of this LogEntry 
        Log_IOSequenceNo  IOSequence;
    } EntryHead;
    
	/// The container for this file.
    Container m_Container;

	/// The iterator for the container.
    Iterator m_Iterator;
    
    /// transno for this file
    const tgg91_TransNo &m_TransNo;
};

#endif  /* Rst_Redo_H */
