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

  module      : RTEMem_AllocatorRegister.hpp

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

  responsible : JoergM

  special area: RTE
  description : Allocator registration 
  
                This class implements a singleton, that allows to register allocators.
                This allows to collect the memory usage information for all registered
                allocators.

  last changed: 2001-01-10  11:04
  see also    : <class>RTE_ItemRegister</class>
  first created:2000-03-09  18:21

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



    ========== 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_ALLOCATORREGISTER_HPP
#define RTEMEM_ALLOCATORREGISTER_HPP

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

#include "SAPDBCommon/MemoryManagement/SAPDBMem_IAllocatorInfo.hpp"
#include "RunTime/RTE_ItemRegister.hpp"

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

/*! 
  Class: RTEMem_AllocatorRegister

  Description: The allocator register singleton
  
  The allocator register allows individual allocators to Register()/Deregister()
  themselfs. To be able to register, these allocator must be derived from
  SAPDBMem_IRawAllocator and contain Register() call in their ctor and a Deregister()
  call in their dtor. The Register() call is supplied with an variable of
  type RTEMem_AllocatorInfo which must be member variable of the allocator.
  To be used with RTEMem_AllocatorRegister, the class SAPDBMem_IRawAllocator got 
  an extra GetIdentifier() member function added. The registration takes place 
  automatically during construction, no extra call is needed.

  To obtain the register information a list of all currently registered allocator
  can be retrieved. To do this first the register must be locked via a Lock() call. 
  A loop over all registered allocators is done using the Next() function, which returns
  a pointer to an RTEMem_AllocatorInfo. If no more elements are returned, a NULL pointer
  is returned. An Unlock() call is needed to complete the register access.
  
  The Register() and Deregister() functions use the same internal Spinlock Lock() and 
  Unlock() use on enter and leave. After unlock is called any pointer retunred by a previous
  Next() call is no longer garantuid to point to an existing object!!!!

  Since the Deregister() function is called in every dtor of a class derived from
  RTEMem_IRawAllocator, the allocator instances will never be detructed while 
  registered in the RTEMem_AllocatorRegister.

  Example:

  \#include "Runtime/MemoryManagement/RTEMem_AllocatorRegister.hpp"

  void SaveAllocatorInfo()
  {
      RTEMem_AllocatorRegister & register = RTEMem_AllocatorRegister::Instance() ;

      RTEMem_AllocatorInfo     * info ;

      register.Lock();

      while ( 0 != (info = register.Next()) )
      {
          SAPDB_ULong usedCount;
          SAPDB_ULong allocCount;

          info->GetItem().CalcStatistics(usedCount, allocCount);
          InsertIntoAllocatorSystemTable( info->GetIdentifier(), 
                                          usedCount,
                                          allocCount,
                                          info->GetBaseIdentifier() );
      }

      register.Unlock();
  }

 */
class RTEMem_AllocatorRegister : public RTE_ItemRegister<SAPDBMem_IAllocatorInfo>
{
public:
    static const SAPDB_Int4 m_MaxIdentfierLength;

    struct StatisticInfo
    {
        SAPDB_ULong          UsedBytes;
        SAPDB_ULong          MaxUsedBytes;
        SAPDB_ULong          AllocatedBytes;
        SAPDB_ULong          CountAlloc;
        SAPDB_ULong          CountDealloc;
        SAPDB_ULong          BaseCountAlloc;
        SAPDB_ULong          BaseCountDealloc;
        SAPDB_ULong          CountFailedAlloc; ///< number of failed allocate calls
        SAPDB_ULong          CountFoundError;
        SAPDB_UTF8           AllocatorName[40+4];
        SAPDB_UTF8           AllocatorBaseName[40+4];
    };

    /*!
        Function: Instance

        description: Return reference to single instance of RTEMem_AllocatorRegister

        The InitializeInstance function must have been called before.

        Return value: Reference to singleton instance
     */
    static RTEMem_AllocatorRegister & Instance( );

    /*!
       Function: GetStatisticInfo
       Description: Get a snapshot of all statistic informations
       Arguments: pInfoArray[out] Pointer to array of StatisticInfo

       Return value: True if info array fill, false if not not enough memory
     */
    SAPDB_Bool GetStatisticInfo(StatisticInfo * &pInfoArray, SAPDB_Int4 &itemCount);

    /*!
       Function: FreeStatisticInfo
       Description: Free the snapshot of all statistic informations collected by GetStatisticInfo

       Arguments: pInfoArray[in] Pointer to array of StatisticInfo
     */
    void FreeStatisticInfo(StatisticInfo *pInfoArray);

private:
    RTEMem_AllocatorRegister(SAPDB_Bool makeBackupCopy):RTE_ItemRegister<SAPDBMem_IAllocatorInfo>(makeBackupCopy) {}

    /*!
       Function: FillStatisticInfo
       Description: Fill the statistic informations
       
       Called by GetStatisticInfo, to call at least memory allocation outside of locked registration code

       Arguments: pInfoArray[in] Pointer to array of StatisticInfo
     */
    SAPDB_Bool FillStatisticInfo(StatisticInfo * &pInfoArray, SAPDB_Int4 maxCount, SAPDB_Int4 &itemCount);

    static RTEMem_AllocatorRegister *m_Instance;
};
typedef RTEMem_AllocatorRegister::Info RTEMem_AllocatorInfo;
typedef SAPDB_UTF8 RTEMem_AllocatorIdentifier;
/*!
  EndClass: RTEMem_AllocatorRegister
 */
#endif  /* RTEMEM_ALLOCATORREGISTER_HPP */
