/*!
  @file    RTE_IKernelInterface.hpp
  @author  JoergM
  @ingroup Runtime
  @brief   Session-free kernel runtime interface for use in liboms.

\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

*/

#ifndef RTE_IINTERFACE_HPP
#define RTE_IINTERFACE_HPP

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

/*! RTE_IF_TIMESTAMP_FORMAT     "YYYY-MM-DD HH:MM:SS" zero terminated */
#define RTE_IF_TIMESTAMP_FORMAT "%04d-%2d-%2d %2d:%2d:%2d"

#define MEMORYPROTECTION_READWRITE 0
#define MEMORYPROTECTION_NOACCESS  1
#define MEMORYPROTECTION_READONLY  2

#include "RunTime/RTE_ISystem.hpp"

/*===========================================================================*
 *  CLASSES, STRUCTURES, TYPES, UNIONS ...                                   *
 *===========================================================================*/
class SAPDBMem_IRawAllocator;
class RTESync_Spinlock;

/*!
  class:       RTE_IKernelInterface
  Description: The exported kernel runtime interface
  
  This class contains all functions provided to all threads or tasks inside a livecache kernel or liboms
 */
class RTE_IInterface
{
public:
    /*! Character array for RTE_IF_TIMESTAMP_FORMAT "YYYY-MM-DD HH:MM:SS" zero terminated */
    typedef SAPDB_Char Timestamp                   [5   +3 +3 +3 +3 +3  ];

    /*!
      @brief get the RTE allocator to be used for all runtime internal allocations
      @return reference to runtime owned allocator
     */
    virtual SAPDBMem_IRawAllocator &Allocator() = 0;

    /*!
      @brief get optimal spinlock loop count
      @return number of hot spinlock loops
     */
    virtual SAPDB_UInt4 GetLockLoopCount() = 0;

    /*!
      @brief set the task state to yield on spinlock, if not already set

      A task can indicate by this interface, that it is yielding to acquiere the given spinlock.
      This call is part of the interface, to allow liboms to indicate its spinlock yield entry.

      @param pLock [in] pointer to spinlock 
      @param beginToYield [in] flag to indicate yield begins, if false yield ends
      @return none
     */
    virtual void SetTaskStateYielding(RTESync_Spinlock const *pLock, bool beginToYield) = 0;

    /*!
      @brief get local date time
      @param now [out] current time
      @return none
     */
    virtual void GetLocalDateTime(RTE_ISystem::DateTime &now) = 0;

    /*!
      @brief protect given memory area
      @param pwAdr [in] start address (must be system page aligned)
      @param ulSize [in] number of bytes to protect
      @param type [in] protection type MEMORYPROTECTION_READWRITE,MEMORYPROTECTION_READ,MEMORYPROTECTION_NOACCESS
      @return 0 if call succeeded, system specific error code else
     */
    virtual SAPDB_ULong MemProtect( void *pvAdr, SAPDB_ULong ulSize, SAPDB_Int type ) = 0;

    /*!
      @brief give up time slice

      This call allows to dispatch next thread/process. Used if block i.e. by a spinlock.
     */
    virtual void GiveUpTimeSlice() = 0;

    /*!
      @brief yield while potentially inside task code

      NOTE: This call produces extra overhead to detect if runnning inside a task or runtime thread.
      If you already know you are running in a task, you can specify a task id. If you know you are not
      running in a task, better call GiveUpTimeSlice() directly !

      This call allows to dispatch next task/thread/process. Used if block i.e. by a spinlock
      @param taskId [in] taskid currently running in ( optional, but performance relevant...)
      @param allowLoadBalancing [in] select to allow/forbid load balancing if yielding in tasking code
     */
    virtual void TaskYield(RTE_TaskId taskId=0, SAPDB_Bool allowLoadBalancing = false) = 0;

    /*!
      @brief get a procedure address from given shared library handle
     */
    virtual RTE_SharedLibProcAddress GetProcAddress( RTE_SharedLibHandle hLib,
                                                     SAPDB_Char const *szSqlFunction, 
                                                     SAPDB_Char *pErrText,
                                                     SAPDB_UInt4 lenErrTextInBytes) = 0;

    /*!
      @brief get the interface instance 
      @return reference to singleton
     */
    static RTE_IInterface &Instance() 
    { return *Initialize(); }

private:
    /*!
      @brief initialization routine (dummy for kernel and meaningfull code in client instance...)
      @return pointer to singleton
     */
    static RTE_IInterface *Initialize();

    /*!
      This global hook must be used instead of an instance method!
      Reason is i.e. the Msg_List class which is used in liboms and kernel.
      That may create two different variables which both have to be initialized.
      The kernel one is initialized in the RTE_KernelInterfaceInstance ctor. 
      The liboms one is initialized in the OMS_LibOmsInterfaceInstance::AdviseKernelInterface method
      The client one is initialized in the RTE_ClientInterfaceInstance ctor. 
     */
    static RTE_IInterface *it;
    friend class LVCSim_KernelInterface;
    friend class OMS_LibOmsInterfaceInstance;
    friend class OMS_KernelDefaultInterface;
    friend class RTE_KernelInterfaceInstance;
    friend class RTE_ClientInterfaceInstance;
};

/*!
  endclass:       RTE_IInterface
*/

#endif  /* RTE_IINTERFACE_HPP */
