/*!
  @file     IOMan_Manager.hpp
  @author   TorstenS
  @ingroup  IOManagement
  @brief    This module is used to handle all volumes of the kernel.
            The IOMan_Manager class offers the possibility to manage 
            data and log volumes. This contains the facility to create,
            open, close, read and write from and to volumes.

\if EMIT_LICENCE
\endif
\if EMIT_LICENCE


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


\endif
*/



#ifndef IOMAN_MANAGER_HPP
#define IOMAN_MANAGER_HPP



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

#include "gsp00.h"   // PASCAL: SP_basic_constants_and_types
#include "ggg00.h"   // PASCAL: GG_basic_constants_and_tyype

// Interfaces
#include "IOManager/IOMan_IConverterIO.hpp"
#include "IOManager/IOMan_IDataInfo.hpp"
#include "IOManager/IOMan_IDataIO.hpp"
#include "IOManager/IOMan_IDataManager.hpp"
#include "IOManager/IOMan_IDiagnose.hpp"
#include "IOManager/IOMan_ILogInfo.hpp"
#include "IOManager/IOMan_ILogManager.hpp"
#include "IOManager/IOMan_ILogIO.hpp"
#include "IOManager/IOMan_IMigration.hpp"

#include "Converter/Converter_Page.hpp"
#include "DataAccess/Data_BasePage.hpp"
#include "DataAccess/Data_Types.hpp"
#include "IOManager/IOMan_BlockAddress.hpp"
#include "IOManager/IOMan_ClusterAddress.hpp"
#include "IOManager/IOMan_DataArea.hpp"
#include "IOManager/IOMan_ConverterPages.hpp"
#include "IOManager/IOMan_DataPages.hpp"
#include "IOManager/IOMan_LogArea.hpp"
#include "IOManager/IOMan_LogPages.hpp"
#include "IOManager/IOMan_PageFrameAllocator.hpp"
#include "IOManager/IOMan_ReservedBlockAddress.hpp"
#include "IOManager/IOMan_Types.hpp"
#include "KernelCommon/Kernel_Common.hpp"
#include "KernelCommon/Kernel_RestartPage.hpp"
#include "Logging/Log_ClusterAddress.hpp"
#include "Logging/Log_InfoPage.hpp"
#include "Logging/Log_Page.hpp"
#include "RunTime/MemoryManagement/RTEMem_AllocatorWrapper.hpp"
#include "SAPDBCommon/MemoryManagement/SAPDBMem_IRawAllocator.hpp"


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


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


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

/* -----------------------------------------------------------------------*/
/*!
   @class   IOMan_Manager
   @brief   This class is used to handle all volumes of the kernel.
 */
/* -----------------------------------------------------------------------*/

class IOMan_Manager : public IOMan_IConverterIO,
            public IOMan_IDataInfo,
            public IOMan_IDataIO,
            public IOMan_IDataManager,
            public IOMan_IDiagnose,
            public IOMan_ILogInfo,
            public IOMan_ILogIO,
            public IOMan_ILogManager,
            public IOMan_IMigration
{
    friend class IOMan_IConverterIO;
    friend class IOMan_IDataInfo;
    friend class IOMan_IDataIO;
    friend class IOMan_IDataManager;
    friend class IOMan_IDiagnose;
    friend class IOMan_ILogInfo;
    friend class IOMan_ILogIO;
    friend class IOMan_ILogManager;
    friend class IOMan_IMigration;

public:

    /* -----------------------------------------------------------------------*/
    /*!
       @brief   This method returns the access to the component IOManager.
                It is assumed that the IOManager singleton is available! 
                No CreateInstance call will be done.
       @return  Access to the IOMan_Manager singleton
     */
    /* -----------------------------------------------------------------------*/

    static IOMan_Manager& GetInstance(){ return( *m_Instance ); }

    /* -----------------------------------------------------------------------*/
    /*!
       @brief   This method creates the singleton IOMananger.It is assumed 
                that this method will be callled only one time by the timeout 
                task and therefore no synchonization mechanism is used.
       @param   taskId [in] Identification of the calling task.
       @return  true means instance could be created; else false
     */
    /* -----------------------------------------------------------------------*/

    static bool CreateInstance( const tsp00_TaskId  taskId );

    virtual SAPDB_Bool AddDataVolume(
        const tsp00_TaskId      taskId,
        const SAPDB_Bool        bIsCold,
        tsp00_VFilename         &devName,
        const IOMan_BlockCount  devSize,
        const IOMan_DeviceNo    devNo );

    virtual SAPDB_Bool AddLogVolume(
        const tsp00_TaskId          taskId,
        const SAPDB_Bool            bIsCold,
        tsp00_VFilename             &devName,
        tsp00_VFilename             &mirrDevName,
        const IOMan_BlockCount      devSize,
        const IOMan_DeviceNo        devNo,
        IOMan_LogPages              &pages,
        IOMan_BlockCount            &newLogSize );

    virtual SAPDB_Bool AddDataVolumePossible() const
    {
        return( m_DataArea.ConfiguredVolumes() <  m_DataArea.MaxVolumes());
    }

    virtual void CloseAllLogVolumes( const tsp00_TaskId  taskId );

    virtual void CloseAllDataVolumes( const tsp00_TaskId  taskId );

    virtual SAPDB_Int ConfiguredDataVolumes() const
    {
        return( m_DataArea.ConfiguredVolumes() );
    }

    virtual SAPDB_Int MaxConfigurableDataVolumes() const
    {
        return( m_DataArea.MaxVolumes() );
    }

    virtual SAPDB_Int ConfiguredLogVolumes() const
    {
        return( m_LogArea.ConfiguredVolumes() );
    }

    virtual SAPDB_Int MaxConfigurableLogVolumes() const
    {
        return( m_LogArea.MaxConfigurableVolumes() );
    }

    virtual SAPDB_Bool IsLogMirrored() const
    {
        return( m_LogArea.IsLogMirrored() );
    }

    virtual bool GetDataVolumeNo(
        tsp00_VFilename   &devName,
        IOMan_DeviceNo    &devNo ) const
    {
        return( m_DataArea.GetVolumeNo( devName, devNo ));
    }

    virtual bool GetDataVolumeName(
        IOMan_DeviceNo    devNo,
        tsp00_VFilename   &devName ) const
    {
        return( m_DataArea.Get( devNo ).GetName( devName ));
    }

    virtual SAPDB_Bool GetBadLogVolume(
        const tsp00_TaskId  taskId,
        tsp00_VFilename     &badDevName )
    {
        return( m_LogArea.GetBadLogVolume( taskId, badDevName ));
    }

    virtual bool GetLogVolumeNo(
        tsp00_VFilename     &devName,
        IOMan_DeviceNo      &devNo,
        SAPDB_Bool          &bIsPrimary )
    {
        return( m_LogArea.GetVolumeNo( devName, devNo, bIsPrimary ));
    }

    virtual bool GetLogVolumeName(
        const IOMan_DeviceNo        devNo,
        tsp00_VFilename             &devName ) const
    {
        return( m_LogArea.Get( devNo ).GetName( devName ));
    }

    virtual bool GetMirrLogVolumeName(
        const IOMan_DeviceNo        devNo,
        tsp00_VFilename             &devName ) const
    {
        return( m_LogArea.Get( devNo ).GetName( devName, true ));
    }

    virtual bool CreateAllLogVolumes( const tsp00_TaskId  taskId );

    virtual bool CreateAllDataVolumes( const tsp00_TaskId  taskId );

    virtual IOMan_BlockCount GetDataVolumeSize( const IOMan_DeviceNo devNo ) const;

    virtual IOMan_BlockCount GetDataVolumeUsableSize( const IOMan_DeviceNo devNo ) const;

    virtual IOMan_BlockCount GetLogVolumeSize( const IOMan_DeviceNo devNo ) const;

    virtual IOMan_BlockCount GetLogVolumeUsableSize( const IOMan_DeviceNo devNo ) const;

    virtual bool OpenAllLogVolumes(
        const tsp00_TaskId  taskId,
        const SAPDB_Bool    bOpenForWrite = SAPDB_TRUE );

    virtual bool OpenAllDataVolumes( const tsp00_TaskId   taskId );

    virtual bool OpenOneDataVolume(
        const tsp00_TaskId    taskId,
        const IOMan_DeviceNo  devNo );

    virtual bool OpenOneLogVolume(
        const tsp00_TaskId    taskId,
        const IOMan_DeviceNo  devNo );

    virtual void ReadConverterPage(
        const tsp00_TaskId          taskId,
        const IOMan_BlockAddress    &block,
        Converter_Page              &page );

    virtual IOMan_ReturnCode ReadDataPage(
        const tsp00_TaskId  taskId,
        Data_BasePage       &page,
        const Data_PageNo   &pageNo );

    virtual bool ReadDataPagesForSave(
        const tsp00_TaskId          taskId,
        const SAPDB_Int4            asynIOHandle,
        IOMan_DataPages             &pages,
        const IOMan_ClusterAddress  &cluster );

    virtual bool ReadDataPageDirect(
        const tsp00_TaskId          taskId,
        Data_BasePage               &page,
        const IOMan_BlockAddress    &block );

    virtual void ReadLogInfoPage(
        const tsp00_TaskId        taskId,
        Log_InfoPage              &page,
        const Log_ClusterAddress  &address );

    virtual void ReadLogPage(
        const tsp00_TaskId        taskId,
        Log_Page                  &page,
        const Log_ClusterAddress  &address );

    virtual void ReadLogPageWithoutCheck(
        const tsp00_TaskId        taskId,
        Log_Page                  &page,
        const Log_ClusterAddress  &address );

    virtual void ReadLogPages(
        const tsp00_TaskId          taskId,
        IOMan_LogPages              &pages,
        const Log_ClusterAddress    &address );


    virtual void ReadRestartPage(
        const tsp00_TaskId  taskId,
        Kernel_RestartPage  &page );

    virtual void ReadSnapShotRestartPage(
        const tsp00_TaskId          taskId,
        Kernel_RestartPage          &page,
        const IOMan_BlockAddress    &block );

    virtual SAPDB_Int4 TotalUsableDataPages() const
    {
        return( m_DataArea.TotalUsableDataPages() );
    }

    virtual SAPDB_Int4 TotalDataPages() const
    {
        return( m_DataArea.TotalDataPages() );
    }

    virtual SAPDB_Int4  TotalUsableLogPages() const
    {
        return( m_LogArea.TotalUsableLogPages() );
    }

    virtual SAPDB_Int UsedDataVolumes() const
    {
        return( m_DataArea.UsedVolumes() );
    }

    virtual void WriteConverterPage(
        const tsp00_TaskId  taskId,
        Converter_Page      &page );

    virtual void WriteDataPage(
        const tsp00_TaskId   taskId,
        Data_BasePage       &page );

    virtual void WriteDataPages(
        const tsp00_TaskId          taskId,
        IOMan_DataPages             &pages,
        const IOMan_ClusterAddress  &cluster );

    virtual bool WriteDataPagesForRestore(
        const tsp00_TaskId          taskId,
        const SAPDB_Int4            asynIOHandle,
        IOMan_DataPages             &pages,
        const IOMan_ClusterAddress  &cluster );

    virtual void WriteLogInfoPage(
        const tsp00_TaskId        taskId,
        Log_InfoPage              &page,
        const Log_ClusterAddress  &address );

    virtual void WriteLogPage(
        const tsp00_TaskId        taskId,
        Log_Page                  &page,
        const Log_ClusterAddress  &address );

    virtual void WriteLogPages(
        const tsp00_TaskId        taskId,
        IOMan_LogPages            &pages,
        const Log_ClusterAddress  &address );

    virtual void WriteRestartPage(
        const tsp00_TaskId    taskId,
        Kernel_RestartPage    &page );

    virtual void WriteSnapShotRestartPage(
        const tsp00_TaskId  taskId,
        Kernel_RestartPage  &page,
        IOMan_BlockAddress  &block );

    virtual bool ReadPageDirectFromDataVolume(
        const tsp00_TaskId          taskId,
        const IOMan_BlockAddress    &block,
        const tsp00_PageAddr        pPage );

    virtual bool WritePageDirectToDataVolume(
        const tsp00_TaskId          taskId,
        const IOMan_BlockAddress    &block,
        const tsp00_PageAddr        pPage );

    virtual bool ReadPageDirectFromLogVolume(
        const tsp00_TaskId          taskId,
        const IOMan_BlockAddress    &block,
        const tsp00_PageAddr        pPage,
        const SAPDB_Bool            bFromPrimary );

    virtual bool WritePageDirectToLogVolume(
        const tsp00_TaskId          taskId,
        const IOMan_BlockAddress    &block,
        const tsp00_PageAddr        pPage,
        const SAPDB_Bool            bToPrimary );

    virtual IOMan_ReturnCode MigrateDataBase( const tsp00_TaskId  taskId );


    /* -----------------------------------------------------------------------*/
    /*!
       @brief   This method returns the identifier of the first data volume.
                It's not guaranteed that the returned volume identifier 
                specifies a volume which is online.
       @return  IOMan_DeviceNo
     */
    /* -----------------------------------------------------------------------*/

    IOMan_DeviceNo GetFirstDataVolumeNo() const
    {
        return( m_DataArea.GetFirstDataVolumeNo());
    }

    /* -----------------------------------------------------------------------*/
    /*!
       @brief   This method returns the next identifier of the data volume
                following the given data volume. It's not guaranteed that
                the returned volume identifier specifies a volume which
                is online.
       @param   devNo [in] Logical volume identifier
       @return  IOMan_DeviceNo
     */
    /* -----------------------------------------------------------------------*/

    IOMan_DeviceNo GetNextDataVolumeNo( const IOMan_DeviceNo devNo ) const
    {
        return( m_DataArea.GetNextDataVolumeNo( devNo ));
    }

    /* -----------------------------------------------------------------------*/
    /*!
       @brief   This method checks the validity of the given data volume 
                identifier.
       @param   devNo [in] Logical volume identifier
       @return  SAPDB_Bool
     */
    /* -----------------------------------------------------------------------*/

    SAPDB_Bool IsDataVolumeNoValid( const IOMan_DeviceNo devNo ) const
    {
        return( m_DataArea.IsDataVolumeNoValid( devNo ));
    }

    /* -----------------------------------------------------------------------*/
    /*!
       @brief   This method returns whether the given data volume is in
                state online.
       @param   devNo [in] Logical volume identifier
       @return  SAPDB_Bool
     */
    /* -----------------------------------------------------------------------*/

    SAPDB_Bool IsDataVolumeOnline( const IOMan_DeviceNo devNo ) const
    {
        return( m_DataArea.IsDataVolumeOnline( devNo ));
    }

    /* -----------------------------------------------------------------------*/
    /*!
       @brief   This method returns the identifier of the first log volume.
                It's not guaranteed that the returned volume identifier 
                specifies a volume which is online.
       @return  IOMan_DeviceNo
     */
    /* -----------------------------------------------------------------------*/

    IOMan_DeviceNo GetFirstLogVolumeNo() const
    {
        return( m_LogArea.GetFirstLogVolumeNo());
    }
    /* -----------------------------------------------------------------------*/
    /*!
       @brief   This method returns the next identifier of the log volume
                following the given data volume. It's not guaranteed that
                the returned volume identifier specifies a volume which
                is online.
       @param   devNo [in] Logical volume identifier
       @return  IOMan_DeviceNo
     */
    /* -----------------------------------------------------------------------*/

    IOMan_DeviceNo GetNextLogVolumeNo( const IOMan_DeviceNo devNo ) const
    {
        return( m_LogArea.GetNextLogVolumeNo( devNo ));
    }

    /* -----------------------------------------------------------------------*/
    /*!
       @brief   This method checks the validity of the given log volume 
                identifier.
       @param   devNo [in] Logical volume identifier
       @return  SAPDB_Bool
     */
    /* -----------------------------------------------------------------------*/

    SAPDB_Bool IsLogVolumeNoValid( const IOMan_DeviceNo devNo ) const
    {
        return( m_LogArea.IsLogVolumeNoValid( devNo ));
    }

    /* -----------------------------------------------------------------------*/
    /*!
       @brief   This method returns whether the given log volume is in
                state online.
       @param   devNo [in] Logical volume identifier
       @return  SAPDB_Bool
     */
    /* -----------------------------------------------------------------------*/

    SAPDB_Bool IsLogVolumeOnline( const IOMan_DeviceNo devNo ) const
    {
        return( m_LogArea.IsLogVolumeOnline( devNo ));
    }

    SAPDB_Bool ReIntegrateBadLogVolume(
        const tsp00_TaskId  taskId,
        tsp00_VFilename     &badDevName )
    {
        return( m_LogArea.ReIntegrateBadLogVolume( taskId, badDevName ));
    }

private:

    // Copy and assignment operator are not supported

    IOMan_Manager& operator=( const IOMan_Manager &Manager );

    IOMan_Manager( const IOMan_Manager &Manager );

    IOMan_Manager( SAPDBMem_IRawAllocator  &allocator );

    SAPDB_Bool Initialize(
        const tsp00_TaskId  taskId,
        const SAPDB_UInt    maxDataVolumes,
        const SAPDB_UInt    maxLogVolumes );

    SAPDB_Bool RestartAndInitializeFBM( const tsp00_TaskId   taskId );

    tgg00_TransContext BuildAuxTrans( tsp00_TaskId TaskId ) const;

private:

    /*-------------------------------------------------------------------------
    declaration: m_Instance
    description: Pointer to the IOMananger singleton.
    --------------------------------------------------------------------------*/

    static IOMan_Manager    *m_Instance;

    /*-------------------------------------------------------------------------
    declaration: m_Allocator
    description: Base allocator used for all dependent memory allocation of
                 this class. Note that this member data has to be the first 
                 member data defined in this class, because the sequence
                 of the execution of the initialization lists depends on it!
    --------------------------------------------------------------------------*/

    RTEMem_AllocatorWrapper  m_Allocator;

    /*-------------------------------------------------------------------------
    declaration: m_PageAllocator
    description: Allocator for page frames. The page frame size is definded by
                 the data base configuration file. Note that this member data 
                 has to be the second member data defined in this class, because 
                 the sequence of the execution of the initialization lists 
                 depends on it!
    --------------------------------------------------------------------------*/

    IOMan_PageFrameAllocator    m_PageAllocator;

    /*-------------------------------------------------------------------------
    declaration: m_DataArea
    description: Manager istance for all data volumes.
    --------------------------------------------------------------------------*/

    IOMan_DataArea   m_DataArea;

    /*-------------------------------------------------------------------------
    declaration: m_LogArea
    description: Manager instance for all log volumes
    --------------------------------------------------------------------------*/

    IOMan_LogArea m_LogArea;

    /*-------------------------------------------------------------------------
    declaration: m_ReservedBlocks
    description: Collection of reserved block addresses like restart page
    --------------------------------------------------------------------------*/

    IOMan_ReservedBlockAddress  m_ReservedBlocks;

    /*-------------------------------------------------------------------------
    declaration: m_IsArchiveInstance
    description: Is true if the instance type of the data base is configured
                 to ARCHIVE. (SAP BW with LEGATO storage)
    --------------------------------------------------------------------------*/

    const SAPDB_Bool m_IsArchiveInstance;
};

#endif  /* IOMAN_MANAGER_HPP */
