/*!
  @file     IOMan_Manager.cpp
  @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
    ========== 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

\endif
*/



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

#include "hbd73.h"
#include "hkb57.h"
#include "hgg01_3.h"
#include "vsp002.h"
#include "heo58.h"   // vget_uniqe_id
#include "heo56.h"   // RTE   : Vsleep

#include "FreeBlockManagement/FBM_Types.hpp"
#include "FreeBlockManagement/FBM_IManager.hpp"
#include "Converter/Converter_IPageNoMapping.hpp"
#include "Converter/Converter_ICommon.hpp"
#include "Converter/Converter_Types.hpp"
#include "IOManager/IOMan_Exception.hpp"
#include "IOManager/IOMan_Manager.hpp"
#include "IOManager/IOMan_Messages.hpp"
#include "IOManager/IOMan_Migration.hpp"
#include "IOManager/IOMan_Types.hpp"
#include "KernelCommon/Kernel_FileIO.hpp"
#include "KernelCommon/ParameterNames/KernelParam_IOManager.hpp"
#include "KernelCommon/Kernel_IAdminRestartShutdown.hpp"
#include "RunTime/MemoryManagement/RTEMem_Allocator.hpp"
#include "RunTime/RTE_Crash.hpp"
#include "RunTime/RTE_Message.hpp"
#include "RunTime/Configuration/RTEConf_ParameterAccess.hpp"
#include "RunTime/Configuration/RTEConf_ParameterAccessKernelInterface.hpp"
#include "SAPDBCommon/SAPDB_ToString.hpp"
#include "Trace/Trace_DevSpaceIOEntry.hpp"


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

/// count current io for read statistic
#define IOMAN_READ_IO   1

/// minimum number of data pages
#define IOMAN_MIN_REQUIRED_DATA_PAGES   2000

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



/*===========================================================================*
 *  GLOBAL VARIABLES                                                         *
 *===========================================================================*/

IOMan_Manager*  IOMan_Manager::m_Instance = NULL;

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


/*===========================================================================*
 *  STATIC/INLINE FUNCTION PROTOTYPES                                        *
 *===========================================================================*/

/* -----------------------------------------------------------------------*/
/*!
    @brief  This method is used to read the log mode information from
            the configuration file. 
    @return  (SAPDB_Bool) true, if the log is mirrored
 */
/* -----------------------------------------------------------------------*/

static
SAPDB_Bool IsMirroredLogConfigured()
{

    RTEConf_Parameter::String   paramValue;
    SAPDBErr_MessageList        errMsg;

    if( ! RTEConf_ParameterAccess::Instance()->GetString(
                UTF8( KERNELPARAM_LOG_MIRRORED ), paramValue, errMsg ))
        RTE_Crash( errMsg );

    if( 0 == strcmp( "NO", ( SAPDB_Char* ) paramValue ))
        return( SAPDB_FALSE ); // LOG_MIRRORED == NO
    else
        return( SAPDB_TRUE ); // LOG_MIRRORED == YES
};

/* -----------------------------------------------------------------------*/
/*!
    @brief  This method is used to get the database instance type from
            the configuration file. 
    @return  (SAPDB_Bool) true, if instance type is archive
 */
/* -----------------------------------------------------------------------*/

static
SAPDB_Bool IsArchiveInstanceConfigured()
{
    RTEConf_Parameter::String   paramValue;
    SAPDBErr_MessageList        errMsg;

    if( ! RTEConf_ParameterAccess::Instance()->GetString(
                UTF8( "INSTANCE_TYPE" ), paramValue, errMsg ))
        RTE_Crash( errMsg );

    if( 0 == strcmp( "ARCHIVE", ( SAPDB_Char* ) paramValue ))
        return( SAPDB_TRUE ); // INSTANCE_TYPE == ARCHIVE
    else
        return( SAPDB_FALSE ); // INSTANCE_TYPE != ARCHIVE
}

/* -----------------------------------------------------------------------*/
/*!
    @brief  This method is used to get the maximum configured log and
            data volume count from the configuration file. 
    @param  paramName [in] wanted configuration parameter
    @return (SAPDB_UInt) maximum configured data volumes respl.
                         maximum configured log volumes.
 */
/* -----------------------------------------------------------------------*/

static SAPDB_UInt
GetMaxConfiguredVolumes( const RTEConf_Parameter::Name paramName )
{
    RTEConf_Parameter::Integer  paramValue;
    SAPDBErr_MessageList        errMsg;

    if( ! RTEConf_ParameterAccess::Instance()->GetInteger(
                paramName, paramValue, errMsg ))
        RTE_Crash( errMsg );

    return(( SAPDB_UInt) paramValue );
}

/*===========================================================================*
 *  METHODS                                                                  *
 *===========================================================================*/

IOMan_Manager::IOMan_Manager( SAPDBMem_IRawAllocator  &allocator )
        :
        m_Allocator( UTF8( "IOMan_Manager" ), allocator ),
        m_PageAllocator(),
        m_DataArea( m_PageAllocator, m_Allocator ),
        m_LogArea( m_PageAllocator, m_Allocator, IsMirroredLogConfigured() ),
        m_ReservedBlocks(),
        m_IsArchiveInstance( IsArchiveInstanceConfigured() )
{};

/*---------------------------------------------------------------------------*/

bool
IOMan_Manager::CreateInstance( const tsp00_TaskId  taskId )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::CreateInstance", IOMan_Trace, 5 );

    if ( NULL == m_Instance )
    {
        m_Instance = new( RTEMem_Allocator::Instance() )
                     IOMan_Manager( RTEMem_Allocator::Instance() );

        if (NULL == m_Instance ) return( false );

        if (! m_Instance->Initialize( taskId,
                                      GetMaxConfiguredVolumes( UTF8( KERNELPARAM_MAXDATAVOLUMES )),
                                      GetMaxConfiguredVolumes( UTF8( KERNELPARAM_MAXLOGVOLUMES ))))
            return( false );
    }
    return( true );
}

/*---------------------------------------------------------------------------*/

SAPDB_Bool
IOMan_Manager::Initialize(
    const tsp00_TaskId  taskId,
    const SAPDB_UInt    maxDataVolumes,
    const SAPDB_UInt    maxLogVolumes )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::Initialize", IOMan_Trace, 5 );

    if(! m_DataArea.Initialize( taskId, maxDataVolumes ))
        return( SAPDB_FALSE );

    if(! m_LogArea.Initialize( taskId, maxLogVolumes ))
        return( SAPDB_FALSE );

    return( SAPDB_TRUE );
}

/*---------------------------------------------------------------------------*/

void
IOMan_Manager::CloseAllLogVolumes( const tsp00_TaskId  taskId )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::CloseAllLogVolumes", IOMan_Trace, 5 );

    m_LogArea.CloseAll( taskId );
}

/*---------------------------------------------------------------------------*/

void
IOMan_Manager::CloseAllDataVolumes( const tsp00_TaskId  taskId )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::CloseAllDataVolumes", IOMan_Trace, 5 );

    m_DataArea.CloseAll( taskId );

    FBM_IManager::Instance().Shutdown( taskId );
}

/*---------------------------------------------------------------------------*/

bool
IOMan_Manager::CreateAllLogVolumes( const tsp00_TaskId   taskId )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::CreateAllLogVolumes", IOMan_Trace, 5 );

    tsp00_Line          dbIdentifier;
    const SAPDB_Byte    *pDbIdentifier = reinterpret_cast<SAPDB_Byte*>( &dbIdentifier );

    vget_uniqe_id( dbIdentifier );

    return( m_LogArea.CreateAll( taskId, pDbIdentifier ));
}

/*---------------------------------------------------------------------------*/

bool
IOMan_Manager::CreateAllDataVolumes( const tsp00_TaskId  taskId )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::CreateAllDataVolumes", IOMan_Trace, 5 );

    tsp00_Line          dbIdentifier;
    const SAPDB_Byte    *pDbIdentifier = reinterpret_cast<SAPDB_Byte*>( &dbIdentifier );

    vget_uniqe_id( dbIdentifier );

    // Create, open and format all configured data volumes
    if(! m_DataArea.CreateAll( taskId, pDbIdentifier ))
        return( false );

    // Check data volume size in regard to nonsense configuration
    if( IOMAN_MIN_REQUIRED_DATA_PAGES > m_DataArea.TotalDataPages() )
    {
        IOMan_Exception errMsg( __CONTEXT__, IOMAN_MIN_DATA_PAGES,
                                SAPDB_ToString( IOMAN_MIN_REQUIRED_DATA_PAGES, _T_d ),
                                SAPDB_ToString( m_DataArea.TotalDataPages(), _T_d ));
        RTE_Crash( errMsg );
    }
    return( RestartAndInitializeFBM( taskId ));
}

/*---------------------------------------------------------------------------*/

IOMan_BlockCount
IOMan_Manager::GetDataVolumeSize( const IOMan_DeviceNo devNo ) const
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::GetDataVolumeSize", IOMan_Trace, 5 );

    return( m_DataArea.Get( devNo ).GetCapacity( false ));
}
/*---------------------------------------------------------------------------*/

IOMan_BlockCount
IOMan_Manager::GetDataVolumeUsableSize( const IOMan_DeviceNo devNo ) const
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::GetDataVolumeUsableSize", IOMan_Trace, 5 );

    const IOMan_BlockAddress  block = m_ReservedBlocks.GetRestartPageAddress();

    if(( block.IsValid() ) && ( devNo == block.GetDeviceNo() ))
        return( m_DataArea.Get( devNo ).GetCapacity( true ) -1 );
    else
        return( m_DataArea.Get( devNo ).GetCapacity( true ) );
}

/*---------------------------------------------------------------------------*/

IOMan_BlockCount
IOMan_Manager::GetLogVolumeSize( const IOMan_DeviceNo devNo ) const
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::GetLogVolumeSize", IOMan_Trace, 5 );

    return( m_LogArea.Get( devNo ).GetCapacity( false ));
}

/*---------------------------------------------------------------------------*/

IOMan_BlockCount
IOMan_Manager::GetLogVolumeUsableSize( const IOMan_DeviceNo   devNo ) const
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::GetLogVolumeUsableSize", IOMan_Trace, 5 );

    if( 1 == devNo )  // log info page
        return( m_LogArea.Get( devNo ).GetCapacity( true ) -1);
    else
        return( m_LogArea.Get( devNo ).GetCapacity( true ));
}

/*---------------------------------------------------------------------------*/

bool
IOMan_Manager::OpenAllLogVolumes(
    const tsp00_TaskId taskId,
    const SAPDB_Bool   bOpenForWrite )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::OpenLogArea", IOMan_Trace, 5 );

    if( m_LogArea.OpenAll( taskId, bOpenForWrite )){
        return true;
    }

    m_LogArea.CloseAll( taskId );
    return false;
}

/*---------------------------------------------------------------------------*/

bool
IOMan_Manager::OpenAllDataVolumes( const tsp00_TaskId taskId )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::OpenDataArea", IOMan_Trace, 5 );

    if( m_DataArea.OpenAll( taskId ))
    {
        kb57RestoreRestartRecord( taskId );

        if( RestartAndInitializeFBM( taskId )){
            return true;
        }
    }
    m_DataArea.CloseAll( taskId );
    return false;
}

/*---------------------------------------------------------------------------*/

bool
IOMan_Manager::OpenOneDataVolume(
    const tsp00_TaskId    taskId,
    const IOMan_DeviceNo  devNo )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::OpenOneDataVolume", IOMan_Trace, 5 );

    return( IOMan_Okay == ( m_DataArea.Get( devNo ).Open( taskId )));
}

/*---------------------------------------------------------------------------*/
bool
IOMan_Manager::OpenOneLogVolume(
    const tsp00_TaskId    taskId,
    const IOMan_DeviceNo  devNo )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::OpenOneLogVolume", IOMan_Trace, 5 );

    return( IOMan_Okay == ( m_LogArea.Get( devNo ).Open( taskId, 0, SAPDB_TRUE )));
}

/*---------------------------------------------------------------------------*/

SAPDB_Bool
IOMan_Manager::AddDataVolume(
    const tsp00_TaskId      taskId,
    const SAPDB_Bool        bIsCold, // obsolete
    tsp00_VFilename         &devName,
    const IOMan_BlockCount  devSize,
    const IOMan_DeviceNo    devNo )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::AddDataVolume", IOMan_Trace, 5 );

    bool        retCode            = SAPDB_TRUE;
    const bool  bDataAreaRestarted = m_DataArea.ConfiguredVolumes() == m_DataArea.UsedVolumes();

    if( ! bDataAreaRestarted )
        retCode = m_DataArea.OpenAll( taskId );

    if( retCode )
        retCode = m_DataArea.AddVolume( taskId, ! bDataAreaRestarted, devName, devSize, devNo );

    if( ! bDataAreaRestarted )
        m_DataArea.CloseAll( taskId );

    return( retCode );
}

/*---------------------------------------------------------------------------*/

SAPDB_Bool
IOMan_Manager::AddLogVolume(
    const tsp00_TaskId          taskId,
    const SAPDB_Bool            bIsCold, // obsolete
    tsp00_VFilename             &devName,
    tsp00_VFilename             &mirrDevName,
    const IOMan_BlockCount      devSize,
    const IOMan_DeviceNo        devNo,
    IOMan_LogPages              &pages,
    IOMan_BlockCount            &newLogSize )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::AddLogVolume", IOMan_Trace, 5 );

    bool        retCode           = SAPDB_TRUE;
    const bool  bLogAreaRestarted = m_LogArea.ConfiguredVolumes() == m_LogArea.UsedVolumes();


    if( ! bLogAreaRestarted )
        retCode = m_LogArea.OpenAll( taskId, SAPDB_TRUE );

    if( retCode )
    {
        retCode = m_LogArea.AddVolume( taskId, devName, mirrDevName,
                                       devSize, devNo, pages );

        if( retCode )
            newLogSize = m_LogArea.TotalUsableLogPages();
    }

    if( ! bLogAreaRestarted )
        m_LogArea.CloseAll( taskId ); // PTS 1112474 TS 2001-11-07

    return( retCode );
}

/*---------------------------------------------------------------------------*/

void
IOMan_Manager::ReadConverterPage(
    const tsp00_TaskId          taskId,
    const IOMan_BlockAddress    &block,
    Converter_Page              &page )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::ReadConverterPage", IOMan_Trace, 5 );

    SAPDBTRACE_WRITELN( IOMan_Trace, 5, "ConverterPage: " << block.GetDeviceNo() <<\
                        "/" << block.GetBlockNo() );

    const SAPDB_Bool bOkay = m_DataArea.Get( block.GetDeviceNo() ).ReadPage( taskId, page, block );

    if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
    {
        tgg00_TransContext auxTrans = BuildAuxTrans( taskId );
        Trace_ReadConverterPageEntry( auxTrans, block );
    }

    if( SAPDB_TRUE == bOkay )
    {
        // Check given block address against the block address
        // within the obtained buffer
        const IOMan_BlockAddress  pageBlock = page.ReadBlockAddress();

        if(
            ( block.GetDeviceNo() == pageBlock.GetDeviceNo() ) &&
            ( block.GetBlockNo() == pageBlock.GetBlockNo() )
        )
        {
            bd73ConverterIOStatistic( IOMAN_READ_IO );
            return;
        }
    }

    // Abnormal termination
    IOMan_Exception errMsg( __CONTEXT__, IOMAN_WRONG_CONV_PAGE,
                            KERNEL_DATA_FILE, SAPDB_ToString( block.GetDeviceNo(), _T_d ),
                            SAPDB_ToString( block.GetBlockNo(), _T_d ));

    Kernel_FileIO   DumpFile( KERNEL_DATA_FILE, KERNEL_BAD_FILE_EXTENSION,
                              SAPDB_ToString( block.GetDeviceNo(), _T_d ),
                              SAPDB_ToString( block.GetBlockNo(), _T_d ));
    DumpFile.Write( page );
    DumpFile.Close();

    RTE_Crash( errMsg );
}

/*---------------------------------------------------------------------------*/

IOMan_ReturnCode
IOMan_Manager::ReadDataPage(
    const tsp00_TaskId  taskId,
    Data_BasePage       &page,
    const Data_PageNo   &pageNo )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::ReadDataPage", IOMan_Trace, 5 );


    IOMan_BlockAddress          block;
    const Converter_ReturnCode  retCode = Converter_IPageNoMapping::Instance().GetPositionForReading(
                                              taskId, pageNo, page.RecoveryMode(), block );

    if( Converter_Ok != retCode )
    {
        if( Converter_PageNoOutOfRange == retCode )
            return( IOMan_PageNoOutOfRange );
        else
            return( IOMan_NoConverterEntry );
    }

    SAPDBERR_ASSERT_STATE( block.IsValid() );

    const SAPDB_Int  cMaxRetries  = 3;
    SAPDB_Int        retryCount   = 0;
    do
    {
        if( ! m_DataArea.Get( block.GetDeviceNo() ).ReadPage( taskId, page, block ))
        {
            RTE_Message( IOMan_Exception( __CONTEXT__, IOMAN_BAD_DATA_PAGE,
                                          SAPDB_ToString( pageNo, _T_d ),                 // requested pageNo
                                          Data_PageRecModeStrings( page.RecoveryMode()),  // requested recMode
                                          SAPDB_ToString( page.PageNo(), _T_d )));        // read pageNo
            return IOMan_BadDataPage;
        }

        if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
        {
            tgg00_TransContext auxTrans = BuildAuxTrans( taskId );
            Trace_ReadDataPageEntry( auxTrans, page.ReadPageType2(), page.PageNo(), block );
        }
        //	Check given	pno	against	the	pno	within the obtained	buffer
        if(	pageNo == page.PageNo()){
            return IOMan_Okay;
        }
        { // page is correct, but it is not the requested one!
            RTE_Message( IOMan_Exception( __CONTEXT__, IOMAN_WRONG_PAGENO,
                                          SAPDB_ToString( block.GetDeviceNo(), _T_d	),
                                          SAPDB_ToString( block.GetBlockNo(), _T_d )));

            RTE_Message( IOMan_Exception( __CONTEXT__, IOMAN_WRONG_PAGENO2,
                                          SAPDB_ToString( pageNo, _T_d ),                 // requested pageNo
                                          Data_PageRecModeStrings( page.RecoveryMode()),  // requested recMode
                                          SAPDB_ToString( page.PageNo(), _T_d )));        // read pageNo

            Kernel_FileIO	dumpFile( KERNEL_DATA_FILE,	KERNEL_BAD_FILE_EXTENSION,
                                    SAPDB_ToString( pageNo, _T_d ));
            dumpFile.Write(	page );
        }
        retryCount+=1;
        vsleep( taskId, 1 );
    }while( retryCount < cMaxRetries );

    return IOMan_BadDataPage;
}

/*---------------------------------------------------------------------------*/

bool
IOMan_Manager::ReadDataPageDirect(
    const tsp00_TaskId         taskId,
    Data_BasePage              &page,
    const IOMan_BlockAddress   &block )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::ReadDataPageDirect", IOMan_Trace, 5 );

    SAPDBTRACE_WRITELN( IOMan_Trace, 5, "BlockAddress: " <<
                        block.GetDeviceNo() << "/" << block.GetBlockNo());

    if(! m_DataArea.Get( block.GetDeviceNo() ).ReadPage( taskId, page, block ))
        return( false );

    if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
    {
        tgg00_TransContext auxTrans = BuildAuxTrans( taskId );
        Trace_ReadDataPageEntry( auxTrans, page.ReadPageType2(), page.PageNo(), block );
    }
    return( true );
}

/*---------------------------------------------------------------------------*/

void
IOMan_Manager::ReadLogInfoPage(
    const tsp00_TaskId        taskId,
    Log_InfoPage              &page,
    const Log_ClusterAddress  &address )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::ReadLogInfoPage", IOMan_Trace, 5 );

    SAPDBTRACE_WRITELN( IOMan_Trace, 5,
                        " LogOffset: " << address.GetOffset() <<
                        " BlockCount: " << address.GetBlockCount() );

    SAPDBERR_ASSERT_STATE( 1 == address.GetBlockCount() );
    SAPDBERR_ASSERT_STATE( address.GetOffset().IsValid() );

    IOMan_BlockAddress  block = m_LogArea.GetBlockAddress( address.GetOffset() );

    m_LogArea.Get( block.GetDeviceNo() ).ReadPage( taskId, page, block );

    if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
    {
        tgg00_TransContext auxTrans = BuildAuxTrans( taskId );
        Trace_ReadLogPageEntry( auxTrans, pt2LogInfo_egg00, page.ReadPageId(), block );
    }
}

/*---------------------------------------------------------------------------*/
void IOMan_Manager::ReadLogPageWithoutCheck(
    const tsp00_TaskId        taskId,
    Log_Page                  &page,
    const Log_ClusterAddress  &address )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::ReadLogPageWithoutCheck", IOMan_Trace, 5 );

    SAPDBTRACE_WRITELN( IOMan_Trace, 5,
                        " LogOffset: " << address.GetOffset() <<
                        " BlockCount: " << address.GetBlockCount() );

    SAPDBERR_ASSERT_STATE( 1 == address.GetBlockCount() );
    SAPDBERR_ASSERT_STATE( address.GetOffset().IsValid() );

    const IOMan_BlockAddress  block = m_LogArea.GetBlockAddress( address.GetOffset() );

    if(! m_LogArea.Get( block.GetDeviceNo() ).ReadSimple( taskId,
            tsp00_PageAddr( page.GetFramePtr()), block.GetBlockNo(), true ))
    {
        Kernel_FileIO   dumpFile( m_LogArea.Get( block.GetDeviceNo() ).GetTypeName(),
                                  KERNEL_BAD_FILE_EXTENSION,
                                  SAPDB_ToString( block.GetDeviceNo(), _T_d ),
                                  SAPDB_ToString( block.GetBlockNo(), _T_d ));
        dumpFile.Write( page );
        dumpFile.Close();

        Kernel_IAdminRestartShutdown::Instance().Offline();
    }

    bd73LogIOStatistic( IOMAN_READ_IO );

    if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
    {
        tgg00_TransContext auxTrans = BuildAuxTrans( taskId );
        Trace_ReadLogPageEntry( auxTrans, pt2Nil_egg00, page.ReadLastWriterIOSequenceNo(), block );
    }

}
void
IOMan_Manager::ReadLogPage(
    const tsp00_TaskId       taskId,
    Log_Page                 &page,
    const Log_ClusterAddress &address )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::ReadLogPage", IOMan_Trace, 5 );

    SAPDBTRACE_WRITELN( IOMan_Trace, 5,
                        " LogOffset: " << address.GetOffset() <<
                        " BlockCount: " << address.GetBlockCount() );

    SAPDBERR_ASSERT_STATE( 1 == address.GetBlockCount() );
    SAPDBERR_ASSERT_STATE( address.GetOffset().IsValid() );

    IOMan_BlockAddress  block = m_LogArea.GetBlockAddress( address.GetOffset() );

    m_LogArea.Get( block.GetDeviceNo() ).ReadPage( taskId, page, block );

    bd73LogIOStatistic( IOMAN_READ_IO );

    if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
    {
        tgg00_TransContext auxTrans = BuildAuxTrans( taskId );
        Trace_ReadLogPageEntry( auxTrans, pt2Nil_egg00, page.ReadLastWriterIOSequenceNo(), block );
    }

}

/*---------------------------------------------------------------------------*/

void
IOMan_Manager::ReadLogPages(
    const tsp00_TaskId          taskId,
    IOMan_LogPages              &pages,
    const Log_ClusterAddress    &address )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::ReadLogPages", IOMan_Trace, 5 );

    SAPDBTRACE_WRITELN( IOMan_Trace, 5,
                        " LogOffset: " << address.GetOffset() <<
                        " BlockCount: " << address.GetBlockCount() );

    SAPDBERR_ASSERT_STATE( pages.GetPageCount() >= address.GetBlockCount() ); // PTS 1126157
    SAPDBERR_ASSERT_STATE( 0 < pages.GetPageCount() );
    SAPDBERR_ASSERT_STATE( address.GetOffset().IsValid() );

    Log_DeviceBlockCount pagesToRead = address.GetBlockCount();
    SAPDB_UInt           startIndex  = 0;
    IOMan_ClusterAddress cluster;

    do
    {
        cluster = m_LogArea.GetClusterAddress( address.GetOffset() + startIndex, pagesToRead );
        m_LogArea.Get( cluster.GetDeviceNo() ).ReadPages( taskId, pages, cluster, startIndex );

        if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
        {
            tgg00_TransContext               auxTrans = BuildAuxTrans( taskId );
            SAPDB_UInt                       traceNo  = ( cluster.GetBlockCount() > 1 )? 1:0;
            IOMan_ClusterAddress::BlockIndex index    = 0;
            IOMan_LogPagesIterator           iter( pages );

            for( iter.Begin( startIndex ); !iter.End() && index < cluster.GetBlockCount();
                    ++iter, ++index, ++traceNo )
            {
                Trace_ReadLogPageEntry( auxTrans, pt2Nil_egg00, ( *iter ).ReadLastWriterIOSequenceNo(),
                                        cluster.GetBlockAddress( index ), traceNo );
            }
        }
        pagesToRead -= cluster.GetBlockCount();
        startIndex  += cluster.GetBlockCount();
        bd73LogIOStatistic( IOMAN_READ_IO );
    }
    while( 0 < pagesToRead );
}

/*---------------------------------------------------------------------------*/

void
IOMan_Manager::ReadRestartPage(
    const tsp00_TaskId   taskId,
    Kernel_RestartPage   &page )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::ReadRestartPage", IOMan_Trace, 5 );


    const IOMan_BlockAddress  block = m_ReservedBlocks.GetRestartPageAddress();

    if(! m_DataArea.Get( block.GetDeviceNo() ).ReadPage( taskId, page, block ))
    {
        IOMan_Exception ErrMsg( __CONTEXT__, IOMAN_BAD_RESTART_PAGE,
                                KERNEL_DATA_FILE, SAPDB_ToString( block.GetDeviceNo(), _T_d ),
                                SAPDB_ToString( block.GetBlockNo(), _T_d ));

        Kernel_FileIO   DumpFile( KERNEL_DATA_FILE, KERNEL_BAD_FILE_EXTENSION,
                                  SAPDB_ToString( block.GetDeviceNo(), _T_d ),
                                  SAPDB_ToString( block.GetBlockNo(), _T_d ));

        DumpFile.Write( page );
        DumpFile.Close();

        RTE_Crash( ErrMsg );
    }

    if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
    {
        tgg00_TransContext auxTrans = BuildAuxTrans( taskId );
        Trace_ReadDataPageEntry( auxTrans, page.ReadPageType2(), page.GetPageID(), block );
    }
}

/*---------------------------------------------------------------------------*/

void
IOMan_Manager::ReadSnapShotRestartPage(
    const tsp00_TaskId          taskId,
    Kernel_RestartPage          &page,
    const IOMan_BlockAddress    &block )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::ReadSnapShotRestartPage", IOMan_Trace, 5 );

    if(! m_DataArea.Get( block.GetDeviceNo() ).ReadPage( taskId, page, block ))
    {
        IOMan_Exception ErrMsg( __CONTEXT__, IOMAN_BAD_RESTART_PAGE,
                                KERNEL_DATA_FILE, SAPDB_ToString( block.GetDeviceNo(), _T_d ),
                                SAPDB_ToString( block.GetBlockNo(), _T_d ));

        Kernel_FileIO   DumpFile( KERNEL_DATA_FILE, KERNEL_BAD_FILE_EXTENSION,
                                  SAPDB_ToString( block.GetDeviceNo(), _T_d ),
                                  SAPDB_ToString( block.GetBlockNo(), _T_d ));

        DumpFile.Write( page );
        DumpFile.Close();

        RTE_Crash( ErrMsg );
    }

    if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
    {
        tgg00_TransContext auxTrans = BuildAuxTrans( taskId );
        Trace_ReadDataPageEntry( auxTrans, page.ReadPageType2(), page.GetPageID(), block );
    }
}

/*---------------------------------------------------------------------------*/

void
IOMan_Manager::WriteConverterPage(
    const tsp00_TaskId  taskId,
    Converter_Page      &page )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::WriteConverterPage", IOMan_Trace, 5 );

    const SAPDB_Bool bReqSequential = SAPDB_FALSE;
    const IOMan_BlockAddress block  = FBM_IManager::Instance().GetFreeBlock( taskId , bReqSequential);

    SAPDBTRACE_WRITELN( IOMan_Trace, 5, "New Address: " << block.GetDeviceNo() << "/" << block.GetBlockNo() );

    page.WriteBlockAddress( block );
    page.WriteVersion(Converter_ICommon::Instance().Version());

    m_DataArea.Get( block.GetDeviceNo() ).WritePage( taskId, page, block );

    bd73ConverterIOStatistic( ! IOMAN_READ_IO );

    if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
    {
        tgg00_TransContext auxTrans = BuildAuxTrans( taskId );
        Trace_WriteConverterPageEntry( auxTrans, block );
    }
}

/*---------------------------------------------------------------------------*/

void
IOMan_Manager::WriteDataPage(
    const tsp00_TaskId   taskId,
    Data_BasePage        &page )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::WriteDataPage", IOMan_Trace, 5 );

    const SAPDB_Bool bReqSequential =
        m_IsArchiveInstance && ( Data_VolumeSequential == page.VolumeMode());

    // Update the corresponding  converter entries, before the
    // converter version on the data pages will be changed because
    // the converter needs the old converter version to make decisions
    // about updating the old blockaddress.

    IOMan_BlockAddress block;

    Converter_IPageNoMapping::Instance().GetPositionForWriting( taskId,
            page.PageNo(), page.RecoveryMode(), page.ConverterVersion(),
            bReqSequential, block );

    // Store current converter version within the page image to note
    // the savepoint version when the page was written the last time
    // onto the data volume.
    page.SetConverterVersion( Converter_ICommon::Instance().Version () );

    m_DataArea.Get( block.GetDeviceNo() ).WritePage( taskId, page, block );

    if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
    {
        tgg00_TransContext auxTrans = BuildAuxTrans( taskId );
        Trace_WriteDataPageEntry( auxTrans, page.ReadPageType2(), page.PageNo(), block );
    }
}

/*---------------------------------------------------------------------------*/

void
IOMan_Manager::WriteDataPages(
    const tsp00_TaskId         taskId,
    IOMan_DataPages            &pages,
    const IOMan_ClusterAddress &cluster )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::WriteDataPages", IOMan_Trace, 5 );

    SAPDBERR_ASSERT_STATE( pages.GetPageCount() <= SAPDB_UInt( cluster.GetBlockCount()) );

    // Update the corresponding  converter entries, before the
    // converter version on the data pages will be changed because
    // the converter needs the old converter version to make decisions
    // about updating the old blockaddres.

    IOMan_ClusterAddress::BlockIndex    index = 0;
    IOMan_DataPagesIterator             iter( pages );

    for( iter.Begin(); !iter.End(); ++iter, ++index )
    {
        Converter_IPageNoMapping::Instance().SetPositionForWriting (
            taskId, ( *iter ).ConverterVersion(), ( *iter ).PageNo(),
            ( *iter ).RecoveryMode(), cluster.GetBlockAddress( index ));

        // Store current converter version within the page image to note
        // the savepoint version when the page was written the last time
        // onto the data volume.

        ( *iter ).SetConverterVersion( Converter_ICommon::Instance().Version () );
    }

    m_DataArea.Get( cluster.GetDeviceNo() ).WritePages( taskId, pages, cluster );

    if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
    {
        SAPDB_UInt  traceNo  = ( pages.GetPageCount() > 1 )? 1:0;
        IOMan_ClusterAddress::BlockIndex  index = 0;

        for (iter.Begin(); !iter.End(); ++iter, ++index, ++traceNo)
        {
            tgg00_TransContext auxTrans = BuildAuxTrans( taskId );
            Trace_WriteDataPageEntry( auxTrans, ( *iter ).ReadPageType2(),
                                      ( *iter ).PageNo(), cluster.GetBlockAddress( index ), traceNo );
        }
    }
}

/*---------------------------------------------------------------------------*/

void
IOMan_Manager::WriteLogInfoPage(
    const tsp00_TaskId        taskId,
    Log_InfoPage              &page,
    const Log_ClusterAddress  &address )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::WriteLogInfoPage", IOMan_Trace, 5 );

    SAPDBTRACE_WRITELN( IOMan_Trace, 5,
                        " LogOffset: " << address.GetOffset() <<
                        " BlockCount: " << address.GetBlockCount() );

    SAPDBERR_ASSERT_STATE( 1 == address.GetBlockCount() );
    SAPDBERR_ASSERT_STATE( address.GetOffset().IsValid() );

    IOMan_BlockAddress  block = m_LogArea.GetBlockAddress( address.GetOffset() );

    m_LogArea.Get( block.GetDeviceNo() ).WritePage( taskId, page, block );

    if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
    {
        tgg00_TransContext auxTrans = BuildAuxTrans( taskId );
        Trace_WriteLogPageEntry( auxTrans, pt2LogInfo_egg00, page.ReadPageId(), block );
    }
}

/*---------------------------------------------------------------------------*/

void
IOMan_Manager::WriteLogPage(
    const tsp00_TaskId        taskId,
    Log_Page                  &page,
    const Log_ClusterAddress  &address )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::WriteLogPage", IOMan_Trace, 5 );

    SAPDBTRACE_WRITELN( IOMan_Trace, 5,
                        " LogOffset: " << address.GetOffset() <<
                        " BlockCount: " << address.GetBlockCount() );

    SAPDBERR_ASSERT_STATE( 1 == address.GetBlockCount() );
    SAPDBERR_ASSERT_STATE( address.GetOffset().IsValid() );

    IOMan_BlockAddress  block = m_LogArea.GetBlockAddress( address.GetOffset() );

    m_LogArea.Get( block.GetDeviceNo() ).WritePage( taskId, page, block );

    if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
    {
        tgg00_TransContext auxTrans = BuildAuxTrans( taskId );
        Trace_WriteLogPageEntry( auxTrans, pt2Nil_egg00, page.ReadLastWriterIOSequenceNo(), block );
    }
}


/*---------------------------------------------------------------------------*/

void
IOMan_Manager::WriteLogPages(
    const tsp00_TaskId        taskId,
    IOMan_LogPages            &pages,
    const Log_ClusterAddress  &address )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::WriteLogPages", IOMan_Trace, 5 );

    SAPDBTRACE_WRITELN( IOMan_Trace, 5,
                        " LogOffset: " << address.GetOffset() <<
                        " BlockCount: " << address.GetBlockCount() );

    SAPDBERR_ASSERT_STATE( pages.GetPageCount() == address.GetBlockCount() );
    SAPDBERR_ASSERT_STATE( 0 < pages.GetPageCount() );
    SAPDBERR_ASSERT_STATE( address.GetOffset().IsValid() );

    Log_DeviceBlockCount pagesToWrite = address.GetBlockCount();
    SAPDB_UInt           startOffset  = 0;
    IOMan_ClusterAddress cluster;

    do
    {
        cluster = m_LogArea.GetClusterAddress( address.GetOffset() + startOffset, pagesToWrite );
        m_LogArea.Get( cluster.GetDeviceNo() ).WritePages( taskId, pages, cluster, startOffset );

        if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
        {
            tgg00_TransContext               auxTrans = BuildAuxTrans( taskId );
            SAPDB_UInt                       traceNo  = ( cluster.GetBlockCount() > 1 )? 1:0;
            IOMan_ClusterAddress::BlockIndex index    = 0;
            IOMan_LogPagesIterator           iter( pages );

            for( iter.Begin( startOffset );
                    !iter.End() && index < cluster.GetBlockCount();
                    ++iter, ++index, ++traceNo )
            {
                Trace_WriteLogPageEntry( auxTrans, pt2Nil_egg00, ( *iter ).ReadLastWriterIOSequenceNo(),
                                         cluster.GetBlockAddress( index ), traceNo );
            }
        }
        pagesToWrite -= cluster.GetBlockCount();
        startOffset  += cluster.GetBlockCount();
        bd73LogIOStatistic( ! IOMAN_READ_IO );
    }
    while( 0 < pagesToWrite );
}

/*---------------------------------------------------------------------------*/

void
IOMan_Manager::WriteRestartPage(
    const tsp00_TaskId  taskId,
    Kernel_RestartPage  &page )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::WriteRestartPage", IOMan_Trace, 5 );

    const IOMan_BlockAddress  block = m_ReservedBlocks.GetRestartPageAddress();

    m_DataArea.Get( block.GetDeviceNo() ).WritePage( taskId, page, block );

    if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
    {
        tgg00_TransContext auxTrans = BuildAuxTrans( taskId );
        Trace_WriteDataPageEntry( auxTrans, page.ReadPageType2(), page.GetPageID(), block );
    }
}
/*---------------------------------------------------------------------------*/

void
IOMan_Manager::WriteSnapShotRestartPage(
    const tsp00_TaskId  taskId,
    Kernel_RestartPage  &page,
    IOMan_BlockAddress  &block )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::WriteSnapShotRestartPage", IOMan_Trace, 5 );

    const SAPDB_Bool bReqSequential = SAPDB_FALSE;

    block = FBM_IManager::Instance().GetFreeBlock( taskId , bReqSequential );

    SAPDBTRACE_WRITELN( IOMan_Trace, 5, "New Address: " << block.GetDeviceNo() << "/" << block.GetBlockNo() );

    m_DataArea.Get( block.GetDeviceNo() ).WritePage( taskId, page, block );

    if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
    {
        tgg00_TransContext auxTrans = BuildAuxTrans( taskId );
        Trace_WriteDataPageEntry( auxTrans, page.ReadPageType2(), page.GetPageID(), block );
    }
}

/*---------------------------------------------------------------------------*/

bool
IOMan_Manager::ReadPageDirectFromDataVolume(
    const tsp00_TaskId          taskId,
    const IOMan_BlockAddress    &block,
    const tsp00_PageAddr        pPage )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::ReadPageDirectFromDataVolume", IOMan_Trace, 5 );

    SAPDBTRACE_WRITELN( IOMan_Trace, 5, "BlockAddress: " <<
                        block.GetDeviceNo() << "/" << block.GetBlockNo());

    return( m_DataArea.Get( block.GetDeviceNo() ).ReadSimple(
                taskId, pPage, block.GetBlockNo() ));
}

/*---------------------------------------------------------------------------*/

bool
IOMan_Manager::WritePageDirectToDataVolume(
    const tsp00_TaskId          taskId,
    const IOMan_BlockAddress    &block,
    const tsp00_PageAddr        pPage )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::WritePageDirectToDataVolume", IOMan_Trace, 5 );

    SAPDBTRACE_WRITELN( IOMan_Trace, 5, "BlockAddress: " <<
                        block.GetDeviceNo() << "/" << block.GetBlockNo());

    return( m_DataArea.Get( block.GetDeviceNo() ).WriteSimple(
                taskId, pPage, block.GetBlockNo() ));
}

/*---------------------------------------------------------------------------*/

bool
IOMan_Manager::WritePageDirectToLogVolume(
    const tsp00_TaskId          taskId,
    const IOMan_BlockAddress    &block,
    const tsp00_PageAddr        pPage,
    const SAPDB_Bool            bToPrimary )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::WritePageDirectToLogVolume", IOMan_Trace, 5 );

    SAPDBTRACE_WRITELN( IOMan_Trace, 5, "BlockAddress: " <<
                        block.GetDeviceNo() << "/" << block.GetBlockNo());

    return( m_LogArea.Get( block.GetDeviceNo() ).WriteSimple(
                taskId, pPage, block.GetBlockNo(), bToPrimary ));
}

/*---------------------------------------------------------------------------*/

bool
IOMan_Manager::ReadPageDirectFromLogVolume(
    const tsp00_TaskId          taskId,
    const IOMan_BlockAddress    &block,
    const tsp00_PageAddr        pPage,
    const SAPDB_Bool            bFromPrimary )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::ReadPageDirectFromLogVolume", IOMan_Trace, 5 );

    SAPDBTRACE_WRITELN( IOMan_Trace, 5, "BlockAddress: " <<
                        block.GetDeviceNo() << "/" << block.GetBlockNo());

    return( m_LogArea.Get( block.GetDeviceNo() ).ReadSimple(
                taskId, pPage, block.GetBlockNo(), bFromPrimary ));
}

/*---------------------------------------------------------------------------*/

bool
IOMan_Manager::ReadDataPagesForSave(
    const tsp00_TaskId          taskId,
    const SAPDB_Int4            asynIOHandle,
    IOMan_DataPages             &pages,
    const IOMan_ClusterAddress  &cluster )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::ReadDataPagesForSave", IOMan_Trace, 5 );

    SAPDBERR_ASSERT_STATE( pages.GetPageCount() <= SAPDB_UInt( cluster.GetBlockCount()) );

    //FBM_IManager::Instance().GetNextBlocksForBackUp (Trans.trTaskId_gg00, DevNo,
    //  MaxNumBlocksWanted, SuppliedNumBlocks, BlockNo);      TODO

    bool retCode = m_DataArea.Get( cluster.GetDeviceNo() ).AsynReadWrite(
                       taskId, asynIOHandle, pages, cluster );

    if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
    {
        tgg00_TransContext                  auxTrans = BuildAuxTrans( taskId );
        SAPDB_UInt                          traceNo  = ( pages.GetPageCount() > 1 ) ? 1:0;
        IOMan_DataPagesIterator             iter( pages );
        IOMan_ClusterAddress::BlockIndex    index = 0;

        for( iter.Begin(); !iter.End(); ++iter, ++index, ++traceNo)
            Trace_ReadDataPageEntry( auxTrans, ( *iter ).ReadPageType2(), ( *iter ).PageNo(),
                                     cluster.GetBlockAddress( index ), traceNo );
    }
    return( retCode );
}

/*---------------------------------------------------------------------------*/

bool
IOMan_Manager::WriteDataPagesForRestore(
    const tsp00_TaskId          taskId,
    const SAPDB_Int4            asynIOHandle,
    IOMan_DataPages             &pages,
    const IOMan_ClusterAddress  &cluster )
{
    SAPDBTRACE_ROUTINE_DEBUG( "IOMan_Manager::WriteDataPagesForRestore", IOMan_Trace, 5 );

    SAPDBERR_ASSERT_STATE( pages.GetPageCount() <= SAPDB_UInt( cluster.GetBlockCount()) );

    // set the blocks of the given cluster to occupied
    // Converter_IBackUp::Instance().SetBlockAddressOfRestoredPage (
    //                                taskId, BlockAddress, PageNo, AddressingMode); TODO

    bool retCode = m_DataArea.Get( cluster.GetDeviceNo() ).AsynReadWrite(
                       taskId, asynIOHandle, pages, cluster );

    if( g01vtrace.vtrAll_gg00 || g01vtrace.vtrIoTrace_gg00 )
    {
        tgg00_TransContext                  auxTrans = BuildAuxTrans( taskId );
        SAPDB_UInt                          traceNo  = ( pages.GetPageCount() > 1 ) ? 1:0;
        IOMan_DataPagesIterator             iter( pages );
        IOMan_ClusterAddress::BlockIndex    index = 0;

        for( iter.Begin(); !iter.End(); ++iter, ++index, ++traceNo)
            Trace_WriteDataPageEntry( auxTrans, ( *iter ).ReadPageType2(), ( *iter ).PageNo(),
                                      cluster.GetBlockAddress( index ), traceNo );
    }
    return( retCode );
}

/*---------------------------------------------------------------------------*/


IOMan_ReturnCode
IOMan_Manager::MigrateDataBase( const tsp00_TaskId  taskId )
{
    if( IOMan_Migration::IsMigrationNeeded() )
    {
        IOMan_Migration migManager( taskId, m_PageAllocator, m_Allocator );

        if( ! migManager.Initialize( m_DataArea.MaxVolumes() ))
        {
            return( IOMan_NoMoreMemory );
        }
        if( ! migManager.ExecuteMigration( m_DataArea, m_LogArea ))
        {
            // only one error could occur.
            return( IOMan_NotPreparedForMigration );
        }
    }
    return( IOMan_Okay );
}

/*---------------------------------------------------------------------------*/
/*----------------------------- Private Methods -----------------------------*/
/*---------------------------------------------------------------------------*/

SAPDB_Bool
IOMan_Manager::RestartAndInitializeFBM( const tsp00_TaskId   taskId )
{
    if(! FBM_IManager::Instance().Restart( taskId, m_DataArea.MaxVolumes(), m_ReservedBlocks ))
        return( SAPDB_FALSE );

    for( IOMan_DeviceNo devNo = 1; devNo <= m_DataArea.UsedVolumes(); ++devNo )
    {
        if(! FBM_IManager::Instance().AddVolume( taskId, devNo,
                m_DataArea.Get( devNo ).GetCapacity( SAPDB_FALSE ),
                m_DataArea.Get( devNo ).GetAccessMode()))
            return( SAPDB_FALSE );
    }

    // not active
    //    FBM_IManager::Instance().CheckVolumeBalance();

    return( SAPDB_TRUE );
}

/*---------------------------------------------------------------------------*/

tgg00_TransContext
IOMan_Manager::BuildAuxTrans( tsp00_TaskId TaskId ) const
{
    tgg00_TransContext  Trans;

    Trans.trTaskId_gg00 = TaskId;
    Trans.trSessionId_gg00.becomes( cgg_nil_session );
    Trans.trTransId_gg00.becomes( cgg_nil_trans );
    Trans.trWriteTransId_gg00.becomes( cgg_nil_trans );
    Trans.trSubtransId_gg00 = cgg_zero_subtrans;

    return( Trans );
}

/*---------------------------------------------------------------------------*/
/*-------------- Implementation of Interface Instance methods ---------------*/
/*---------------------------------------------------------------------------*/

IOMan_IDataInfo&
IOMan_IDataInfo::GetInstance()
{
    return( IOMan_Manager::GetInstance() );
}

/*---------------------------------------------------------------------------*/

IOMan_IDataIO&
IOMan_IDataIO::GetInstance()
{
    return( IOMan_Manager::GetInstance() );
}

/*---------------------------------------------------------------------------*/

IOMan_IDataManager&
IOMan_IDataManager::GetInstance()
{
    return( IOMan_Manager::GetInstance() );
}

/*---------------------------------------------------------------------------*/

IOMan_IDiagnose&
IOMan_IDiagnose::GetInstance()
{
    return( IOMan_Manager::GetInstance() );
}

/*---------------------------------------------------------------------------*/

IOMan_ILogInfo&
IOMan_ILogInfo::GetInstance()
{
    return( IOMan_Manager::GetInstance() );
}

/*---------------------------------------------------------------------------*/

IOMan_ILogIO&
IOMan_ILogIO::GetInstance()
{
    return( IOMan_Manager::GetInstance() );
}

/*---------------------------------------------------------------------------*/

IOMan_ILogManager&
IOMan_ILogManager::GetInstance()
{
    return( IOMan_Manager::GetInstance() );
}

/*---------------------------------------------------------------------------*/

IOMan_IConverterIO&
IOMan_IConverterIO::GetInstance()
{
    return( IOMan_Manager::GetInstance() );
}

/*---------------------------------------------------------------------------*/

IOMan_IMigration&
IOMan_IMigration::GetInstance()
{
    return( IOMan_Manager::GetInstance() );
}

/*===========================================================================*
 *  END OF CODE                                                              *
 *===========================================================================*/
