/*!
    @ingroup        Restart
    @file           Rst_RedoTaskLifeCycle.cpp
    @author         JuergenA
    @author         UweH
    @brief          defines classes to start and stop redo tasks
*/
/*

    ========== 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



 */


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

#include "SAPDBCommon/SAPDB_Types.hpp"
#include "SAPDBCommon/Tracing/SAPDBTrace_Usage.hpp" // Routine trace macros
#include "Logging/Log_Types.hpp"
#include "KernelCommon/Kernel_Trace.hpp"
#include "Restart/Rst_RedoTaskLifeCycle.hpp"

#include "ggg00.h"
#include "hgg01.h"
#include "hkb53.h"
#include "hkb90.h"
//---------------------------------------------------------------------------
/*!
	@brief   starts tasks of a given type
	@param   TransContext    the current Transcontext
	@param   MessType        the messagetype of the new task (m_restart or m_restore)
	@param   MaxTasks        the number of tasks which shall be started
	@param   RunningTasks    the number of tasks had been successfully started
 */
static void StartTasks (tgg00_TransContext   &TransContext,
                        tgg00_MessType_Param  MessType,
                        SAPDB_Int             MaxTasks,
                        SAPDB_Int            &RunningTasks)
{
    SAPDBTRACE_ROUTINE_DEBUG ("StartTasks", LogTrans_Trace, 5);
    KERNEL_TRACE_BASIS_ERROR (TransContext.trError_gg00, LogTrans_Trace, 5);
    
    tgg00_MessBlock  SendMblock;
    tgg00_TransChild ChildTrans;
    tgg00_BasisError AuxError = TransContext.trError_gg00;
    
    TransContext.trError_gg00 = e_ok;
    RunningTasks              = 0;
    do
    {
        g01mblock_init (TransContext, MessType, mm_nil, SendMblock);
        
        k53child_trans_build (m_restart, RunningTasks+1, ChildTrans);
        
        k90send (SendMblock, ChildTrans);
        
        if (e_ok != TransContext.trError_gg00) return;
        
        ++RunningTasks;
    }
    while (RunningTasks < MaxTasks);
    
    if (e_ok != AuxError) TransContext.trError_gg00 = AuxError;
}
//---------------------------------------------------------------------------
/*!
    @brief   compares two errorcode and returns the more important one
	@param   firstErr    the first occured error
	@param   secondErr   the second occured error
    @return  the more important error
 */
static tgg00_BasisError CombineReturnCodes(const tgg00_BasisError firstErr,
                                           const tgg00_BasisError secondErr)
{
    if (e_ok == firstErr)
    {
        return secondErr;
    }
    else
    {
        if (e_cancelled == firstErr)
        {
            if (   (secondErr != e_ok) 
                && (secondErr != e_cancelled))
            {
                return secondErr;
            }
            return e_cancelled;
        }
        else
        {
            return firstErr;
        }
    }
}

//---------------------------------------------------------------------------
/*!
    @brief   waits for the return of running tasks
	@param   TransContext    transaction-context
	@param   RunningTasks    number of tasks for which shall be waited.
    Returns also the actual number of still running tasks (in case of an error > 0)
 */
static void StopTasks (tgg00_TransContext &TransContext,
                       SAPDB_Int          &RunningTasks)
{
    SAPDBTRACE_ROUTINE_DEBUG ("StopTasks", LogTrans_Trace, 5);
    KERNEL_TRACE_BASIS_ERROR (TransContext.trError_gg00, LogTrans_Trace, 5);
    
    tgg00_MessBlock  ReceiveMblock;
    tgg00_TransChild ChildTrans;
    tgg00_BasisError AnyChildError = e_ok;
    tgg00_BasisError AuxError      = TransContext.trError_gg00;
    
    TransContext.trError_gg00 = e_ok;
    
    while (RunningTasks > 0)
    {
        g01mblock_init (TransContext, m_nil, mm_nil, ReceiveMblock);
        
        k90rcv_child (ReceiveMblock, ChildTrans);
        
        if (e_ok != TransContext.trError_gg00) return;
        
        AnyChildError = CombineReturnCodes(AnyChildError,
                                           ChildTrans.tcdError_gg00);        
        --RunningTasks;
    }
    
    TransContext.trError_gg00 = CombineReturnCodes(AuxError, AnyChildError);
}
//---------------------------------------------------------------------------
Rst_RedoExecuteTaskLifeCycle::Rst_RedoExecuteTaskLifeCycle (tgg00_TransContext &TransContext):
m_TransContext (TransContext),
m_RunningTasks (0)
{
    SAPDBTRACE_METHOD_DEBUG ("Rst_RedoExecuteTaskLifeCycle::Rst_RedoExecuteTaskLifeCycle", LogTrans_Trace, 5);

    const SAPDB_Int ReservedTasks   = 3;
    SAPDB_Int       MaxExecuteTasks = g01maxservertask() - g01no_of_backup_devs() - ReservedTasks;
    
    if (MaxExecuteTasks < 0) MaxExecuteTasks = 1;
    
    StartTasks (TransContext, m_restart, MaxExecuteTasks, m_RunningTasks);
}
//---------------------------------------------------------------------------
Rst_RedoExecuteTaskLifeCycle::~Rst_RedoExecuteTaskLifeCycle ()
{
    SAPDBTRACE_METHOD_DEBUG ("Rst_RedoExecuteTaskLifeCycle::~Rst_RedoExecuteTaskLifeCycle", LogTrans_Trace, 5);

    StopTasks (m_TransContext, m_RunningTasks);
}
//---------------------------------------------------------------------------
Rst_RedoReadTaskLifeCycle::Rst_RedoReadTaskLifeCycle (tgg00_TransContext &TransContext):
m_TransContext (TransContext),
m_RunningTasks (0)
{
    SAPDBTRACE_METHOD_DEBUG ("Rst_RedoReadTaskLifeCycle::Rst_RedoReadTaskLifeCycle", LogTrans_Trace, 5);

    const SAPDB_Int MaxReadTasks = 1;
    
    StartTasks (TransContext, m_restore, MaxReadTasks, m_RunningTasks);
}
//---------------------------------------------------------------------------
Rst_RedoReadTaskLifeCycle::~Rst_RedoReadTaskLifeCycle ()
{
    SAPDBTRACE_METHOD_DEBUG ("Rst_RedoReadTaskLifeCycle::~Rst_RedoReadTaskLifeCycle", LogTrans_Trace, 5);

    StopTasks (m_TransContext, m_RunningTasks);
}
