/*!
  @file         Kernel_Migration.cpp
  @author       UweH
  @ingroup      KernelCommon
  @brief        Implementation of methods of class Kernel_Migration
  @since        2003-06-30
*/
/*!
\if EMIT_LICENCE

  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



\endif
*/
#include "RunTime/RTE_Crash.hpp"
#include "RunTime/RTE_Message.hpp"
#include "SAPDBCommon/SAPDB_ToString.hpp"
#include "SAPDBCommon/ErrorsAndMessages/SAPDBErr_Assertions.hpp"
#include "KernelCommon/Kernel_Types.hpp"
#include "KernelCommon/Kernel_Messages.hpp"
#include "KernelCommon/Kernel_Exception.hpp"
#include "KernelCommon/Kernel_Version.hpp"

#include "KernelCommon/Kernel_Migration.hpp"

#define KERNEL_MIGRATION_MATRIX_FOR_CPP true
#include "KernelCommon/Kernel_MigrationMatrix.hpp"
#undef KERNEL_MIGRATION_MATRIX_FOR_CPP

#include "hgg01.h"    // g01is_livecache

/* --------------------------------------------------------------------------- */
SAPDB_Char* Kernel_Migration::PersistentComponentStrings[] =
{
    (SAPDB_Char*)"data",
    (SAPDB_Char*)"log",
    (SAPDB_Char*)"catalog"
};
/* --------------------------------------------------------------------------- */
Kernel_Migration::ChangeInfo & Kernel_Migration::SearchForChangeInfo (const SAPDB_Char * changeTitle)
{
    for ( SAPDB_UInt change = 0; change < MAX_CHANGE_INFO; ++change )
    {
        if ( m_ChangeInfos[change].IsValid()
             &&
             ! strcmp( m_ChangeInfos[change].changeTitle, changeTitle) )
            return m_ChangeInfos[change];
    }
    return m_ChangeInfos[INVALID_CHANGE_INFO];
}
/* --------------------------------------------------------------------------- */
const Kernel_Migration::ChangeInfo & Kernel_Migration::SearchForChangeInfo (const SAPDB_Char * changeTitle) const
{
    for ( SAPDB_UInt change = 0; change < MAX_CHANGE_INFO; ++change )
    {
        if ( m_ChangeInfos[change].IsValid()
             &&
             ! strcmp( m_ChangeInfos[change].changeTitle, changeTitle) )
            return m_ChangeInfos[change];
    }
    return m_ChangeInfos[INVALID_CHANGE_INFO];
}
/* --------------------------------------------------------------------------- */
bool Kernel_Migration::CheckCompatibility(PersistentComponent   checkComponent,
                                          const Kernel_Version &checkVersion)
{
    if ( Kernel_Version() < checkVersion )
    {
        checkVersion.WriteIncompatibleMessage(PersistentComponentStrings[checkComponent]);
        return false;
    }

    for ( SAPDB_UInt change = 0; change < MAX_CHANGE_INFO; ++change )
    {
        if ( m_ChangeInfos[change].IsValid()
             &&
             m_ChangeInfos[change].component == checkComponent )
        {
            if ( m_ChangeInfos[change].livecacheOnly && g01is_livecache()
                 ||
                 ! m_ChangeInfos[change].livecacheOnly )
            {
                m_ChangeInfos[change].migrationEnabled =
                    checkVersion <= m_ChangeInfos[change].changedInVersion;
                if ( m_ChangeInfos[change].migrationEnabled )
                    RTE_Message ( Kernel_Exception( __CONTEXT__, KERNEL_ENABLE_MIGRATION,
                                                    m_ChangeInfos[change].changeTitle ) );
            }
        }
    }

    return true;
}
/* --------------------------------------------------------------------------- */
void Kernel_Migration::ResetAllEnabledMigrationFlags()
{
    for ( SAPDB_UInt change = 0; change < MAX_CHANGE_INFO; ++change )
        if ( m_ChangeInfos[change].IsValid() )
            m_ChangeInfos[change].migrationEnabled = false;
}
/* --------------------------------------------------------------------------- */
        /// This compares all changes and returns the latest change version.
Kernel_Version Kernel_Migration::GetOldestCompatibleVersion()
{
    Kernel_Version latestVersion(0,0,0,0);
    for ( SAPDB_UInt change = 0; change < MAX_CHANGE_INFO; ++change )
    {
        if ( m_ChangeInfos[change].IsValid()
             &&
             m_ChangeInfos[change].changedInVersion > latestVersion )
        {
            latestVersion = m_ChangeInfos[change].changedInVersion;
        }
    }
    return latestVersion;
}
/* --------------------------------------------------------------------------- */
void Kernel_Migration::Test()
{
    Kernel_Migration testMigration;
//    Kernel_Version   testDataVersion1   (7,4,2,3);
//    Kernel_Version   testDataVersion2   (7,4,3,2);
//    Kernel_Version   testLogVersion     (7,4,4,2);
//    Kernel_Version   testCatalogVersion (7,4,4,2);
    
    // positive test
    
    if ( ! testMigration.CheckCompatibility(log, Kernel_Version(7,3)) )
        RTE_Crash( SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED, "CheckCompatibility: 7.3") );

    if ( ! testMigration.CheckCompatibility(catalog, Kernel_Version(7,3)) )
        RTE_Crash( SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED, "CheckCompatibility: 7.3") );

    if ( ! testMigration.CheckCompatibility(data, Kernel_Version(7,3)) )
        RTE_Crash( SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED, "CheckCompatibility: 7.3") );

    if ( ! testMigration.SearchForChangeInfo ("historyRootIdCheck").IsEnabled() && g01is_livecache() )
        RTE_Crash( SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED, "historyRootIdCheck 7.3") );

    if ( ! testMigration.SearchForChangeInfo ("omsContainerNewLockProtocol").IsEnabled() && g01is_livecache() )
        RTE_Crash( SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED, "omsContainerNewLockProtocol: 7.3") );

    if ( ! testMigration.SearchForChangeInfo ("omsContainerDoubleLinkedFreeList").IsEnabled() && g01is_livecache() )
        RTE_Crash( SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED, "omsContainerDoubleLinkedFreeList: 7.3") );

    // negative test

    Kernel_Migration::ResetAllEnabledMigrationFlags();
    
    if ( testMigration.CheckCompatibility(data, Kernel_Version(8,0)) )
        RTE_Crash( SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED, "CheckCompatibility: 8.0") );

    if ( testMigration.SearchForChangeInfo ("historyRootIdCheck").IsEnabled() && g01is_livecache() )
        RTE_Crash( SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED, "historyRootIdCheck: 8.0") );

    if ( testMigration.SearchForChangeInfo ("omsContainerNewLockProtocol").IsEnabled() && g01is_livecache() )
        RTE_Crash( SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED, "omsContainerNewLockProtocol: 8.0") );

    if ( testMigration.SearchForChangeInfo ("omsContainerDoubleLinkedFreeList").IsEnabled() && g01is_livecache() )
        RTE_Crash( SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED, "omsContainerDoubleLinkedFreeList: 8.0") );

    // more
    
    if ( GetOldestCompatibleVersion() < Kernel_Version(7,4,3,2) )
        RTE_Crash( SAPDBErr_Exception(__CONTEXT__,SAPDBERR_ASSERT_STATE_FAILED, "GetOldestCompatibleVersion()") );
}