/*!**************************************************************************

  module      : RTEMem_AWEAllocator.hpp

  -------------------------------------------------------------------------

  responsible : RaymondR

  special area: Address Windowing Extensions (AWE)
  description : AWE provides 32-bit applications to address more than 32-bit regions
                of physical memory.

                AWE is supported on all platforms supported by Windows 2000, including
                the 64-bit version of Windows 2000. 

                Windows 2000 (x86) provides applications with a flat 32-bit virtual 
                address space, which describes 4 GB of virtual memory. This address space 
                is usually splitted into two parts. The first part (2GB of address space) 
                is directly accessible to the application, the other 2GB memory is reserved 
                for the operating system.
                On Windows 2000 Advanced Server x86 systems an 'boot.ini' option (/3GB) 
                is provided, so that the operating system reserves only 1 GB of the address 
                space, and the application can access up to 3 GB.

                AWE solves the problem accessing more than 3GB of memory by allowing 
                applications to directly address huge amounts of physical memory while 
                continuing to use 32-bit pointers (where sufficient physical memory is 
                present). 


  last changed: 2001-11-28  12:34
  see also    : 

  -------------------------------------------------------------------------


    ========== 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 RTEMEM_AWEALLOCATOR_HPP
#define RTEMEM_AWEALLOCATOR_HPP



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

#if defined(__cplusplus)
# if defined (_WIN32) && !defined(_WIN64)
#  include "RunTime/System/RTESys_NTAWE.hpp"  /* nocheck */
# endif
# include "SAPDBCommon/SAPDB_Singleton.hpp"
# include "SAPDBCommon/Tracing/SAPDBTrace_Usage.hpp"
#endif


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


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


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

#if defined(__cplusplus)

/*!---------------------------------------------------------------------------
  Class:        RTEMem_AWEAllocator
  Description:  Address Windowing Extensions

                This class allows the application to handle up to 64 GB of
                physical non-paged memory in a 32-bit virtual address space on 32-bit 
                platforms, with windowed views to this physical memory from within 
                the application’s virtual address space.
*/
class RTEMem_AWEAllocator
{
public:
   /*!---------------------------------------------------------------------------
    Function:       Initialize

    Description:    Initialize the RTEMem_AWEAllocator instance

    Arguments:      DBPageSize               [in] - Database page size in bytes
                    NumberOfMapAreaPages     [in] - Number of mapping pages to reserve, which
                                                    are used to map physical pages into them.
                    NumberOfPhysPages    [in/out] - Number of physical pages to allocate.
                    ReservedPhysMemory       [in] - The size of the reserved physical memory, 
                                                    which is used for applications virtual 
                                                    address space. Zero means, the size of
                                                    the complete virtual address space 
                                                    ( excluding the mapping area) is reserved for
                                                    for application space. If the /3GB option is
                                                    set the application reserves up to 3 GB of 
                                                    physical memory which is accessed via the
                                                    virtual address space

     Return value:  none
   */
   static void Initialize( SAPDB_UInt4 const  DBPageSize,
                           SAPDB_UInt4 const  NumberOfMapAreaPages,
                           SAPDB_UInt4        &NumberOfPhysPages,
                           SAPDB_UInt8        ReservedPhysMemory = 0 );  // Use this parameter for tests on small systems only

  /*!
    Function:       Instance
    Description:    Return reference to single instance of RTEMem_AWEAllocator

                    The Initialize() function must have been called before.
                    This is necessary since the database page size is only 
                    known by the caller of the Initialize() function.
                    If an error occurs a 'SAPDBErr_MessageList' is written to to
                    diagnostic file.

    Arguments:      none
    Return value:   Reference to RTEMem_AWEAllocator instance
   */
   static RTEMem_AWEAllocator & Instance( );

   /*!
    Function:       AWEAvailable
    Description:    Function returns true if AWE memory is available

    Arguments:      none

    Return value:   True if AWE memory is available otherwise false.
   */
   bool      AWEAvailable() const;

   /*! 
    Function:       Allocate
    Description:    Allocates one mapping page and mappes a physical page into it.
                    To map a new physical page into the mapping page call 'Map'.

                    The memory is suitably aligned for all types.

                    The memory is not initialised.  

                    If compiled with -DSAPDB_COMPILE_WITHOUT_EXCEPTION_HANDLING a (void *)0 
                    is returned on failure.

                    If compiled without this switch an SAPDBMem_BadAllocException exception
                    is thrown on failure.

                    If an error occurs a 'SAPDBErr_MessageList' is written to to
                    diagnostic file.
 
    Arguments:      pPhysPageNo [out] - A reserved physical page number;
                                        If NULL no physical page is mapped.
    Return value:   Position where mapping page is allocated
   */
   void* Allocate( SAPDB_UInt4*           pPhysPageNo = NULL );

  /*!
    Function:       Deallocate
    Description:    Frees the memory. 

                    The pointer must have been obtained by a previous call to
                    'allocate'.

                    If an error occurs a 'SAPDBErr_MessageList' is written to to
                    diagnostic file.

    Arguments:      pMappingPageAddr [in] - Pointer to memory to deallocate
    Return value:   none
  */
  void Deallocate( void * pMappingPageAddr );

  /*!
    Function:       Map
    Description:    Map a physical page into a specified mapping page.
                   
                    The pointer must have been obtained by a previous call to
                    'allocate'. The physical page number must have been 
                    obtained by a call to 'allocate' or 'ReservePhysPage'

                    If an error occurs a 'SAPDBErr_MessageList' is written to to
                    diagnostic file and the database system stops.

    Arguments:      pMappingPageAddr [in] - Pointer to mapping page.
                    PhysPageNo [in]       - Physical page number.
    Return value:   none
  */
  void        Map ( void * const          pMappingPageAddr,
                    SAPDB_UInt4 const     PhysPageNo );

  /*!
    Function:       UnMap
    Description:    UnMap a physical page from a specified mapping page.
                   
                    The pointer must have been obtained by a previous call to
                    'allocate' and physical page has to be mapped.

                    If an error occurs a 'SAPDBErr_MessageList' is written to to
                    diagnostic file and the database system stops.

    Arguments:      pMappingPageAddr [in] - Pointer to mapping page.
    Return value:   none
  */
  void        UnMap( void * const           pMappingPageAddr );

  /*!
    Function:       ReservePhysPage
    Description:    Reserve a physical page.
                   
    Arguments:      PhysPageNo [out]      - Reserved physical page. The page can be accessed
                                            by mapping it into a mapping page. 

                    If an error occurs a 'SAPDBErr_MessageList' is written to to
                    diagnostic file and the database system stops.
    Return value:   none
  */
  void        ReservePhysPage ( SAPDB_UInt4           &PhysPageNo );

  /*!
    Function:       ReleasePhysPage
    Description:    Release a physical page.
                   
                    If an error occurs a 'SAPDBErr_MessageList' is written to to
                    diagnostic file and the database system stops.

    Arguments:      PhysPageNo [in] - Physical page to release.
    Return value:   none
  */
  void        ReleasePhysPage ( SAPDB_UInt4 const     PhysPageNo );

  /*!
    Function:       NumOfPhysicalPages
    Description:    Maximum number of physical pages.

    Arguments:      none
    Return value:   Maximum number of physical pages
  */
  SAPDB_UInt4 NumOfPhysicalPages () const;

  /*!
    Function:       NumOfFreePhysicalPages
    Description:    Available number of physical pages.

    Arguments:      none
    Return value:   Available number of physical pages
  */
  SAPDB_UInt4 NumOfFreePhysicalPages () const;

  /*!
    Function:       NumOfMapAreaPages
    Description:    Maximum number of mapping pages.

    Arguments:      none
    Return value:   Maximum number of mapping pages
  */
  SAPDB_UInt4 NumOfMapAreaPages () const;

  /*!
    Function:       NumOfFreeMapAreaPages
    Description:    Available number of mapping pages.

    Arguments:      none
    Return value:   Available number of mapping pages
  */
  SAPDB_UInt4 NumOfFreeMapAreaPages () const;

  /*!
    Function:       DBPageSize
    Description:    Size of a database page.

    Arguments:      none
    Return value:   Size of a database page.
  */
  SAPDB_UInt4 DBPageSize            ()  const;

  /*!
    Function:       NumOfMaps
    Description:    Number of Map calls.

    Arguments:      none
    Return value:   Number of Map calls.
  */
  SAPDB_UInt4 NumOfMaps             ()  const;

  /*!
    Function:       NumOfUnMaps
    Description:    Number of UnMap calls.

    Arguments:      none
    Return value:   Number of UnMap calls.
  */
  SAPDB_UInt4 NumOfUnMaps           ()  const;

  /*!
    Function:       GetFirstMapPageInfo / GetNextMapPageInfo
    Description:    Get info of a physical page.

    Arguments:      Handle [out]          - (GetFirstMapPageInfo)use for iteration
                           [in/out]       - (GetNextMapPageInfo) use for iteration
                    pMappingPageAddr[out] - Address of the map page
                    PhysPageNo[out]       - physical page assign to the map page
                    Reserved[out]         - If page has been reserved
                    MapCount[out]         - Number of map in calls
    Return value:   false - if no info available or wrong page number
                    true  - info available
  */
  bool        GetFirstMapPageInfo  ( SAPDB_UInt4            &Idx,
                                     void *                 &pMappingPageAddr,
                                     SAPDB_UInt4            &PhysPageNo,
                                     bool                   &Reserved,
                                     SAPDB_UInt8            &MapCount )  const;

  bool        GetNextMapPageInfo   ( SAPDB_UInt4            &Idx,
                                     void *                 &pMappingPageAddr,
                                     SAPDB_UInt4            &PhysPageNo,
                                     bool                   &Reserved,
                                     SAPDB_UInt8            &MapCount )  const;

  /*!
    Function:       GetPhysPageInfo
    Description:    Get info of a physical page.

    Arguments:      PhysPageNo [in]      - Physical page to release.
                    Reserved[out]        - If page has been reserved
                    MapCount[out]        - Number of map in calls
    Return value:   false - if no info available or wrong page number
                    true  - info available
  */
  bool        GetPhysPageInfo       ( SAPDB_UInt4  const     PhysPageNo,
                                      bool                   &Reserved,
                                      SAPDB_UInt8            &MapCount )  const; 

  ~RTEMem_AWEAllocator () { m_Instance = NULL; }
private:

    SAPDB_Singleton m_ThisIsASingleton; // prevents copy and assignment

    static RTEMem_AWEAllocator *m_Instance;
  // Using a static reference would mean, that initialization function is called before main
  // This we have to prevent for the same reason we prevent static class instances
  // -> dynamic linked RunTime would not get initialized correctly on some OS...

#if defined (_WIN32) && !defined(_WIN64)
    RTESys_NTAWE       AWE;
#endif
};
#endif  /* __cplusplus */

/*! EndClass: RTEMem_AWEAllocator */

/*===========================================================================*
 *  EXTERN "C" PROTOTYPES                                                    *
 *===========================================================================*/

/*! Chapter: extern "C" Functions */


#if !defined(externC)
# define externC extern "C"
#endif  

/* for function descritpions refer to class RTEMem_AWEAllocator
*/
/*!---------------------------------------------------------------------------
  Declaration:  AWE C-functions
  Description:  C functions used to access AWE functionality in pascal or c modules. 

                For function descritpions refer to class RTEMem_AWEAllocator.

*/
externC void          RTEMem_AWEInitialize             ( SAPDB_UInt4 const     DBPageSize,
                                                         SAPDB_UInt4 const     NumberOfMapAreaPages,
                                                         SAPDB_UInt4*          pNumberOfPhysPages,
                                                         SAPDB_UInt8           ReservedPhysMemory );  
externC bool          RTEMem_AWEAvailable              ();
externC void*         RTEMem_AWEAllocate               ( SAPDB_UInt4*          pPhysPageNo );
externC void          RTEMem_AWEDeallocate             ( void *                pMappingPageAddr );
externC void          RTEMem_AWEMap                    ( void * const          pMappingPageAddr,
                                                         SAPDB_UInt4 const     PhysPageNo );
externC void          RTEMem_AWEUnMap                  ( void * const          pMappingPageAddr );
externC void          RTEMem_AWEReservePhysPage        ( SAPDB_UInt4*          pPhysPageNo );
externC void          RTEMem_AWEReleasePhysPage        ( SAPDB_UInt4 const     PhysPageNo );
externC SAPDB_UInt4   RTEMem_AWENumOfPhysicalPages     ();
externC SAPDB_UInt4   RTEMem_AWENumOfFreePhysicalPages ();
externC SAPDB_UInt4   RTEMem_AWENumOfMapAreaPages      ();
externC SAPDB_UInt4   RTEMem_AWENumOfFreeMapAreaPages  ();
externC SAPDB_UInt4   RTEMem_AWENumOfMaps              ();
externC SAPDB_UInt4   RTEMem_AWENumOfUnMaps            ();
externC bool          RTEMem_AWEGetFirstMapPageInfo    ( SAPDB_UInt4            *pIdx,
                                                         void * * const          ppMappingPageAddr,
                                                         SAPDB_UInt4            *PhysPageNo,
                                                         bool                   *pReserved,
                                                         SAPDB_UInt8            *pMapCount );
externC bool          RTEMem_AWEGetNextMapPageInfo     ( SAPDB_UInt4            *pIdx,
                                                         void * * const          ppMappingPageAddr,
                                                         SAPDB_UInt4            *PhysPageNo,
                                                         bool                   *pReserved,
                                                         SAPDB_UInt8            *pMapCount );
externC bool          RTEMem_AWEGetPhysPageInfo        ( SAPDB_UInt4  const     PhysPageNo,
                                                         bool                   *pReserved,
                                                         SAPDB_UInt8            *pMapCount );
externC void          RTEMem_AWEReleaseInstance        ();

/*! EndDeclaration: AWE C-functions */

/*! EndChapter: extern "C" Functions  */

#endif  /* RTEMEM_AWEALLOCATOR_HPP */
