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

  module      : Log_RawDeviceIterator.hpp

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

  responsible : UweH

  author:       TillL
  
  special area: Logging

  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 Log_RawDeviceIterator_HPP
#define Log_RawDeviceIterator_HPP



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

#include "KernelCommon/Kernel_VTrace.hpp"
#include "Logging/Log_Types.hpp"

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

   class: Log_RawDeviceIterator

   description: iterator of raw log device

*******************************************************************************/
class Log_RawDeviceIterator
{
public:

    /*!-------------------------------------------------------------------------
    declaration : RawDeviceOffset
    description:  offset on a raw log device
    --------------------------------------------------------------------------*/
    typedef Log_RawDeviceOffset                             RawDeviceOffset;
    /*!-------------------------------------------------------------------------
    declaration : DeviceBlockCount
    description:  block count on a raw log device
    --------------------------------------------------------------------------*/
    typedef Log_DeviceBlockCount                            DeviceBlockCount;

    /*!-------------------------------------------------------------------------
    function:     Log_RawDeviceIterator()
    description:  Constructor
    arguments:    begin [in] min. offset on device to be used for cyclic write i/o
                  offs  [in] position on device where to write next block
                  end   [in] max. offset on device to be used for cyclic write i/o
    return value: none
    prototypes:   2
    --------------------------------------------------------------------------*/
    Log_RawDeviceIterator()
    {}

    Log_RawDeviceIterator
        (RawDeviceOffset                begin,
         RawDeviceOffset                offs,
         RawDeviceOffset                end)
        :
         m_Begin  (begin), 
         m_Offset (offs),
         m_End    (end)
    {
        SAPDBERR_ASSERT_ARGUMENT(begin <  end);
        SAPDBERR_ASSERT_ARGUMENT(begin <= offs);
        SAPDBERR_ASSERT_ARGUMENT(offs  <= end);
    }

    /*!-------------------------------------------------------------------------
    function:     operator!=()
    description:  Compares with other iterator
    arguments:    iter [in]    other
    return value: (SAPDB_Bool) true if unequal
    --------------------------------------------------------------------------*/
    SAPDB_Bool operator!=
        (const Log_RawDeviceIterator&   iter) const
    {
        return (m_Offset != iter.m_Offset);
    }

    /*!-------------------------------------------------------------------------
    function:     operator++()
    description:  Prefix increment; advances iterator

    arguments:    none
    return value: (Log_RawDeviceIterator&) this instance
    --------------------------------------------------------------------------*/
    Log_RawDeviceIterator& operator++()
    {
        m_Offset = (m_Offset == m_End) ? (SAPDB_UInt)m_Begin : m_Offset + 1;
        return *this;
    }

    /*!-------------------------------------------------------------------------
    function:     operator--()
    description:  Prefix decrement; steps back iterator

    arguments:    none
    return value: (Log_RawDeviceIterator&) this instance
    --------------------------------------------------------------------------*/
    Log_RawDeviceIterator& operator--()
    {
        m_Offset = (m_Offset == m_Begin) ? (SAPDB_UInt)m_End : m_Offset - 1;
        return *this;
    }

    /*!-------------------------------------------------------------------------
    function:     operator+=()
    description:  Increment; advances iterator by given number of steps

    arguments:    steps  [in]  number of steps
    return value: (Log_RawDeviceIterator&) this instance
    --------------------------------------------------------------------------*/
    Log_RawDeviceIterator& operator+=
        (SAPDB_UInt                     steps)
    {
        m_Offset = Later(steps);
        return *this;
    }

    /*!-------------------------------------------------------------------------
    function:     operator-=()
    description:  Increment; steps back iterator by given number of steps

    arguments:    steps  [in]  number of steps
    return value: (Log_RawDeviceIterator&) this instance
    --------------------------------------------------------------------------*/
    Log_RawDeviceIterator& operator-=
        (SAPDB_UInt                     steps)
    {
        m_Offset = Earlier(steps);
        return *this;
    }

    /*!-------------------------------------------------------------------------
    function:     operator+()
    description:  Returns new iterator positioned given number of steps behind
                  actual iterator

    arguments:    steps  [in]  number of steps
    return value: (Log_RawDeviceIterator) 
    --------------------------------------------------------------------------*/
    Log_RawDeviceIterator operator+
        (DeviceBlockCount               steps)
    {
        return Log_RawDeviceIterator(m_Begin, Later(steps), m_End);
    }

    /*!-------------------------------------------------------------------------
    function:     operator-()
    description:  Returns new iterator positioned given number of steps before
                  actual iterator

    arguments:    steps  [in]  number of steps
    return value: (Log_RawDeviceIterator) 
    --------------------------------------------------------------------------*/
    Log_RawDeviceIterator operator-
        (DeviceBlockCount               steps)
    {
        return Log_RawDeviceIterator(m_Begin, Earlier(steps), m_End);
    }

    /*!-------------------------------------------------------------------------
    function:     SetPosition()
    description:  Sets position of iter on raw log device
    arguments:    offs [in] offset to be set
    return value: none
    --------------------------------------------------------------------------*/
    void SetPosition
        (RawDeviceOffset                offs)
    {
        SAPDBERR_ASSERT_ARGUMENT(m_Begin <= offs);
        SAPDBERR_ASSERT_ARGUMENT(offs    <= m_End);
        m_Offset = offs;
    }

    /*!-------------------------------------------------------------------------
    function:     GetPosition()
    description:  Returns actual raw log device position
    arguments:    none
    return value: (RawDeviceOffset)
    --------------------------------------------------------------------------*/
    RawDeviceOffset GetPosition() const
    {
        return m_Offset;
    }

    /*!-------------------------------------------------------------------------
    function:     SetEndOffset()
    description:  Sets end offset of iter on raw log device
    arguments:    end [in] offset to be set
    return value: none
    --------------------------------------------------------------------------*/
    void SetEndOffset
        (RawDeviceOffset                end)
    {
        SAPDBERR_ASSERT_ARGUMENT(m_Offset <= end);
        m_End = end;
    }

    /*!-------------------------------------------------------------------------
    function:     GetEndOffset()
    description:  Returns raw log device end offset
    arguments:    none
    return value: (RawDeviceOffset)
    --------------------------------------------------------------------------*/
    RawDeviceOffset GetEndOffset() const
    {
        return m_End;
    }

    /*!-------------------------------------------------------------------------
    function:     GetBeginOffset()
    description:  Returns raw log device begin offset
    arguments:    none
    return value: (RawDeviceOffset)
    --------------------------------------------------------------------------*/
    RawDeviceOffset GetBeginOffset() const
    {
        return m_Begin;
    }

    /*!-------------------------------------------------------------------------
    function:     GetEndDistance()
    description:  Returns distance from actual iter position to raw device end
    
    arguments:    none
    return value: (DeviceBlockCount) distance in blocks
    --------------------------------------------------------------------------*/
    DeviceBlockCount GetEndDistance() const
    {
        return m_End - m_Offset;
    }

    /*!-------------------------------------------------------------------------
    function:     GetDistanceTo()
    description:  Returns distance from actual iter position to given offset
    arguments:    offset [in]  offset "behind" actual iter position
    return value: (DeviceBlockCount) distance in blocks
    --------------------------------------------------------------------------*/
    DeviceBlockCount GetDistanceTo
        (RawDeviceOffset                offset) const
    {
        #ifdef SAPDB_SLOW
        if ( offset < m_Begin )
        {
            Kernel_VTrace() << "Log_RawDeviceIterator::GetDistanceTo: offset: " << offset
                            << ", m_Begin: " << m_Begin
                            << ", m_End: " << m_End;
            SAPDBERR_ASSERT_ARGUMENT(offset >= m_Begin);
        }
        if ( offset > m_End )
        {
            Kernel_VTrace() << "Log_RawDeviceIterator::GetDistanceTo: offset: " << offset
                            << ", m_Begin: " << m_Begin
                            << ", m_End: " << m_End;
            SAPDBERR_ASSERT_ARGUMENT(offset <= m_End);
        }
        #endif

        return (offset >= m_Offset) ? 
                offset - m_Offset : (m_End - m_Offset + 1) + (offset - m_Begin);
    }

    /*!-------------------------------------------------------------------------
    function:     GetDistanceFrom()
    description:  Returns distance from given offset to actual iter position
    arguments:    offset [in]  offset "before" actual iter position
    return value: (DeviceBlockCount) distance in blocks
    --------------------------------------------------------------------------*/
    DeviceBlockCount GetDistanceFrom
        (RawDeviceOffset                offset) const
    {
        SAPDBERR_ASSERT_ARGUMENT(offset >= m_Begin);
        SAPDBERR_ASSERT_ARGUMENT(offset <= m_End);

        return (offset <= m_Offset) ? 
                m_Offset - offset : (m_End - offset + 1) + (m_Offset - m_Begin);
    }

    /*!-------------------------------------------------------------------------
    function:     GetSize()
    description:  Returns distance from begin offset to end offset
    return value: (DeviceBlockCount) distance in blocks
    --------------------------------------------------------------------------*/
    DeviceBlockCount GetSize () const
    {
        return m_End - m_Begin;
    }


private:

    RawDeviceOffset Later
        (SAPDB_UInt                     steps) const
    {
        SAPDBERR_ASSERT_ARGUMENT(steps <= m_End - m_Begin + 1);

        return (m_Offset > m_End - steps) ? 
                m_Begin + steps - (m_End - m_Offset + 1) : m_Offset + steps;
    }

    RawDeviceOffset Earlier
        (SAPDB_UInt                     steps) const
    {
        SAPDBERR_ASSERT_ARGUMENT(steps <= m_End - m_Begin + 1);

        return (m_Offset < m_Begin + steps) ? 
                m_End - steps + (m_Offset - m_Begin + 1) : m_Offset - steps;
    }

    RawDeviceOffset            m_Begin;
    RawDeviceOffset            m_Offset;
    RawDeviceOffset            m_End;

};
/*!*****************************************************************************

   endclass: Log_RawDeviceIterator

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

#endif  // Log_RawDeviceIterator_HPP



