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

    module      : Log_InvDescMap.hpp

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

    author      : JuergenA
    responsible : UweH

    special area: Logging
    description : defines a class containing the index descriptions

    last changed: 2001-04-17

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

    copyright:    (c) 2000-2004 SAP AG


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




*****************************************************************************/


#ifndef LOG_INV_DESC_MAP_H
#define LOG_INV_DESC_MAP_H

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

#include "SAPDBCommon/SAPDB_Types.hpp"
#include "SAPDBCommon/MemoryManagement/SAPDBMem_IRawAllocator.hpp"
#include "Logging/Log_IRecordColumnMap.hpp"
#include "Logging/Log_ReadWriteActionImage.hpp"
#include "ggg00.h"

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

typedef SAPDB_UInt1 Log_InvDescId;
typedef SAPDB_Int   Log_InvEntryIndex;

//===================================================================================
/*! class:       Log_InvUtilities

    description: functions for index handling
*/
class Log_InvUtilities
{
protected:
    
    typedef enum
    {
        EveryDesc, UniqueDesc, UniqueDescWithoutLateUnique, LateUnique
    } InvDescIterKind;

    //--------------------------------------------------------------Log_InvUtilities---
    /*! function:    BuildInvFileId
    
        desctiption: builds the tree id of an multipl index
        
        arguments:   InvDescId  [in]
                     PrimFileId [in] file id of the primary table
                     InvFileId  [out] file id of the index
    */
    void BuildInvFileId (
        Log_InvDescId       InvDescId,
        const tgg00_FileId &PrimFileId,
        tgg00_FileId       &InvFileId) const;

    //--------------------------------------------------------------Log_InvUtilities---
    /*! function:     GetInvDescId
    
        return value: the index id of the stack entry

        arguments:    StackEntry [in]
    */
    Log_InvDescId GetInvDescId (const tgg00_StackEntry &StackEntry) const
    {
        return ( StackEntry.ecol_tab()[0] );  
    }  

    //--------------------------------------------------------------Log_InvUtilities---
    /*! function:     IsDescendingInvEntry
    
        return value: true, if the entry is descending
        
        arguments:    StackEntry [in]
    */
    inline bool IsDescendingInvEntry (const tgg00_StackEntry &StackEntry) const;

    //--------------------------------------------------------------Log_InvUtilities---
    /*! function:     IsLateUniqueEntry
    
        return value: true, if the entry is part of an unique index wich has to be checked later
        
        arguments:    StackEntry [in]
    */
    inline bool IsLateUniqueEntry (const tgg00_StackEntry &StackEntry) const;

    //--------------------------------------------------------------Log_InvUtilities---
    /*! function:     IsUniqueEntry
    
        return value: true, if the entry is part of an unique index
        
        arguments:    StackEntry [in]
    */
    inline bool IsUniqueEntry (const tgg00_StackEntry &StackEntry) const;
    
    //--------------------------------------------------------------Log_InvUtilities---
    /*! function:     IsUniqueEntryWithoutLateUnique
    
        return value: true, if the entry is part of an unique index
        
        arguments:    StackEntry [in]
    */
    bool IsUniqueEntryWithoutLateUnique (const tgg00_StackEntry &StackEntry) const
    {
        return ( IsUniqueEntry(StackEntry) && ! IsLateUniqueEntry(StackEntry) );
    }

    //--------------------------------------------------------------Log_InvUtilities---
    /*! function:     NilIndex
    
        return value: nil index
    */
    static Log_InvEntryIndex NilIndex ()
    {
        return (SAPDB_MAX_INT4);
    }
    
    //--------------------------------------------------------------Log_InvUtilities---
    /*! function:     NilInvDescId
    
        return value: nil value of Log_InvDescId 
    */
    static Log_InvDescId NilInvDescId ()
    {
        return (0);
    }

};
/*! endclass: Log_InvUtilities */


//===================================================================================
/*! class:       Log_InvDescMap

    description: a list of description entries
*/

class Log_InvDescMap: private Log_InvUtilities
{

private:

    SAPDBMem_IRawAllocator *m_pRawAllocator;
    const tgg00_StackEntry *m_pInvDescMap;
    tgg00_StackEntry       *m_pAllocatedInvDescMap;
    SAPDB_Int               m_AllocatedEntries;
    SAPDB_Int               m_ValidEntries;
    SAPDB_Int               m_UniqueEntries;
    SAPDB_Int               m_LateUniqueEntries;
    
    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:    FindNumberOfUniqueEntries
    
        description: initializes or resets the number of [late] unique entries.
    */
    void FindNumberOfUniqueEntries();
        
public:

    inline Log_InvDescMap ();

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:    ~Log_InvDescMap
    
        description: deallocate InvDescMap
    */
    ~Log_InvDescMap ();

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:    AddInv
    
        description: adds all secondary keys of the record to the inv trees

        arguments:   TransContext [in out] 
                     IsUndoOrRedo [in]
                     PrimFileId   [in] file id of the primary table
                     pRec         [in] pointer to the record which is used to build secondary keys
    */
    void AddInv (
        tgg00_TransContext &TransContext,
        bool                IsUndoOrRedo,
        bool                inSavepoint,
        const tgg00_FileId &PrimFileId,
        const tgg00_Rec    *pRec)           const;

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:    Allocate
    
        description: allocates a list of empty index descripion entries
        
        arguments:   Entries       [in]
                     pRawAllocator [in out]
                     IsOk          [out]
    */
    void Allocate (
        SAPDB_Int               Entries,
        SAPDBMem_IRawAllocator *pRawAllocator,
        bool                   &IsOk);

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:    Assign
    
        description: assigns the pointer of an existing stack entry list to pInvDescList 
        
        arguments:   pExistingInvDescMap  [in] the pointer must be aligned to stack entries
                     Entries              [in]
                     LookForUniqueEntries [in] if true, the list is scanned to mark unique entries
    */
    void Assign (
        const void *pExistingInvDescMap,
        SAPDB_Int   Entries,
        bool        LookForUniqueEntries);
    
    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:    BuildStackDesc
    
        description: builds a StackDesc for a further call of b03create_index
      
        arguments:   StackDesc [out]
    */
    void BuildStackDesc (tgg00_StackDesc &StackDesc) const;
    
    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:    CheckUniqueIndex
    
        description: unique check of all secondary keys execept those marked to be checked later
      
        arguments:   TransContext   [in out] 
                     PrimFileId     [in] file id of the primary table
                     pRec           [in] pointer to the record which is used to build secondary keys
    */
    void CheckUniqueIndex (
        tgg00_TransContext  &TransContext,
        const tgg00_FileId  &PrimFileId,
        const tgg00_Rec     *pRec)        const;
    
    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:     ContainsUniqueIndex
    
        return value: true, if the InvDescMap contains an unique index
    */
    bool ContainsUniqueIndex () const
    {
        return (m_UniqueEntries > 0);
    }

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:     ContainsLateUniqueCheck
    
        return value: true, if the InvDescMap contains an index wich has to be checked later
    */
    bool ContainsLateUniqueCheck () const
    {
        return (m_LateUniqueEntries > 0);
    }

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:    DelInv
    
        description: deletes all secondary keys of the record from the inv trees

        arguments:   TransContext [in out] 
                     IsUndoOrRedo [in]
                     PrimFileId   [in] file id of the primary table
                     pRec         [in] pointer to the record which is used to build secondary keys
    */
    void DelInv (
        tgg00_TransContext &TransContext,
        bool                IsUndoOrRedo,
        bool                inSavepoint,
        const tgg00_FileId &PrimFileId,
        const tgg00_Rec    *pRec)          const;

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:    FunctionBasedIndexDescCnt
    
        description: in case of a function based index, the number of entries describing the index is returned;
                     otherwise 0.

        arguments:   Log_InvEntryIndex [in] 
    */
    
    inline int FunctionBasedIndexDescCnt (Log_InvEntryIndex EntryIndex) const; // PTS 1120019

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:    GetFirstKey
    
        description: creates the first key contained in the inv description map.
      
                     This function is designed for maps which contains one description only.
        
        arguments:   TransContext [in out] 
                     pRec         [in]
                     InvDescId    [out]
                     SecondaryKey [out]        
    */
    void GetFirstKey (tgg00_TransContext &TransContext,
                      const tgg00_Rec    *pRec,
                      Log_InvDescId      &InvDescId,
                      tgg00_Lkey         &SecondaryKey,
                      bool               &allColumnsAreNull ); // PTS 1121337 UH 2003-03-27)

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:     GetInvDescMap
  
        return value: the pointer to the inv description map
    */
    const tgg00_StackEntry *GetInvDescMap () const
    {
        return (m_pInvDescMap);
    }
    
    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:     GetPersistentLength
    
        return value: the length of all valid stack entries of the inv description map
    */
    SAPDB_UInt GetPersistentLength () const
    {
        return ( m_ValidEntries * sizeof (tgg00_StackEntry) );
    }

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:     GetValidEntries
  
        return value: the number of valid entries of the inv description map
    */
    SAPDB_Int GetValidEntries () const
    {
        return (m_ValidEntries);
    }

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:    Insert
    
        description: the number of defined entries of the InvDescMap

        arguments:   StackEntry [in]
    */
    inline void Insert (const tgg00_StackEntry &StackEntry);

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:     InvDescId
  
        return value: the id of the index description 

        arguments:    EntryIndex [in]
    */
    inline Log_InvDescId InvDescId (Log_InvEntryIndex EntryIndex) const;

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:     IsEmpty
    
        return value: true, if the inv description map is empty
    */
    bool IsEmpty () const
    {
        return (m_ValidEntries <= 0);
    }

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:     IsValidIndex
    
        return value: true, if the EntryIndex refers to a valid InvDescEntry
    */
    bool IsValidIndex (Log_InvEntryIndex EntryIndex) const
    {
        return (EntryIndex < m_ValidEntries);
    }

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:     LateUniqueCheckEntries
    
        return value: number of entries with late unique check
    */
    SAPDB_Int LateUniqueCheckEntries () const
    {
        return (m_LateUniqueEntries);
    }
    
    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:    LockAndCheckUniqueIndex
    
        description: locks all unique secondary keys in exclusive mode and performes an unique check
                     
                     Keys are not checked if they are marked to be checked later

        arguments:   TransContext [in out] 
                     PrimFileId   [in] file id of the primary table
                     pRec         [in] pointer to the record which is used to build secondary keys
                     GrantedMode  [out]
    */
    void LockAndCheckUniqueIndex (
        tgg00_TransContext  &TransContext,
        const tgg00_FileId  &PrimFileId,
        const tgg00_Rec     *pRec,
        tgg00_LockReqMode   &GrantedMode) const;
    
    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:    LockUniqueIndex
    
        description: locks all unique secondary keys in exclusive mode

        arguments:   TransContext [in out] 
                     PrimFileId   [in] internal id of the primary table
                     pRec         [in] pointer to the record which is used to build secondary keys
                     GrantedMode  [out]
    */
    void LockUniqueIndex (
        tgg00_TransContext  &TransContext,
        const tgg00_FileId  &PrimFileId,
        const tgg00_Rec     *pRec,
        tgg00_LockReqMode   &GrantedMode) const;

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:    ReadImagePersistent

        description: reads the stack entries from the specified space

        arguments:   ImageReader [in out]
                     IsOk        [out]
    */
    void ReadImagePersistent (
        Log_ActionImageReader &ImageReader,
        SAPDB_UInt4            PersistentLen,
        bool                  &IsOk);
    
    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:    RemoveRedundantEntries
    
        description: removes those inv desc entries, which are not contained in the record column map
      
        arguments:   RawAllocator    [in out]
                     RecordColumnMap [in]
                     IsOk            [out]
    */
    void RemoveRedundantInvDescEntries (
        SAPDBMem_IRawAllocator     &RawAllocator,
        const Log_IRecordColumnMap &RecordColumnMap,
        bool                       &IsOk);

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:     StackEntry
  
        return value: the pointer to the stack entry

        arguments:    EntryIndex [in]
    */
    const tgg00_StackEntry &StackEntry (Log_InvEntryIndex EntryIndex) const
    {
        return ( *(m_pInvDescMap+EntryIndex) );
    }

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:     UniqueEntries
    
        return value: number of unique index entries
    */
    SAPDB_Int UniqueEntries () const
    {
        return (m_UniqueEntries);
    }

    //--------------------------------------------------------------Log_InvDescMap---
    /*! function:    WriteImagePersistent

        description: writes the valid stack entries into the before or after image

        arguments:   ImageWriter [in out]
                     IsOk        [out]
    */
    void WriteImagePersistent (
        Log_ActionImageWriter &ImageWriter,
        bool                  &IsOk)       const;
    
};
/*! endclass: Log_InvDescMap */

/*==========================================================================*
*  DEFINITION OF INLINE METHODS                                             *
*===========================================================================*/

inline bool Log_InvUtilities::IsDescendingInvEntry (const tgg00_StackEntry &StackEntry) const
{
    return (        
        (op_order_desc             == StackEntry.eop() ) ||
        (op_unique_desc            == StackEntry.eop() ) ||
        (op_late_desc_unique_check == StackEntry.eop() ) );
}

//---------------------------------------------------------------------------

inline bool Log_InvUtilities::IsLateUniqueEntry (const tgg00_StackEntry &StackEntry) const
{
    return (        
        (op_late_asc_unique_check  == StackEntry.eop() ) ||
        (op_late_desc_unique_check == StackEntry.eop() ) );
}

//---------------------------------------------------------------------------

inline bool Log_InvUtilities::IsUniqueEntry (const tgg00_StackEntry &StackEntry) const
{
    return (
        (op_unique                 == StackEntry.eop() ) ||
        (op_unique_desc            == StackEntry.eop() ) ||
        (op_unique_expr_upd        == StackEntry.eop() ) ||
        (op_desc_unique_expr_upd   == StackEntry.eop() ) ||
        (op_late_asc_unique_check  == StackEntry.eop() ) ||
        (op_late_desc_unique_check == StackEntry.eop() ) );
}

//---------------------------------------------------------------------------

inline Log_InvDescMap::Log_InvDescMap ():
    m_pRawAllocator        (NULL),
    m_pInvDescMap          (NULL),
    m_pAllocatedInvDescMap (NULL),
    m_AllocatedEntries     (0),
    m_ValidEntries         (0),
    m_UniqueEntries        (0),
    m_LateUniqueEntries    (0)
{ }

//---------------------------------------------------------------------------

inline Log_InvDescId Log_InvDescMap::InvDescId (Log_InvEntryIndex EntryIndex) const
{
    if (NilIndex() == EntryIndex )
    {
        return ( NilInvDescId() );
    }

    return ( GetInvDescId( *(m_pInvDescMap+EntryIndex) ) );
}

//---------------------------------------------------------------------------

inline void Log_InvDescMap::Insert (const tgg00_StackEntry &StackEntry)
{
    if  (m_AllocatedEntries > m_ValidEntries)
    {
        *(m_pAllocatedInvDescMap+m_ValidEntries) = StackEntry;
        ++m_ValidEntries;
        
        if ( IsUniqueEntry     (StackEntry) ) ++ m_UniqueEntries;
        if ( IsLateUniqueEntry (StackEntry) ) ++ m_LateUniqueEntries;
    }
}

//---------------------------------------------------------------------------

inline int Log_InvDescMap::FunctionBasedIndexDescCnt (Log_InvEntryIndex EntryIndex) const
{
    if (NilIndex() != EntryIndex )
    {
        if (st_func == (m_pInvDescMap+EntryIndex)->etype())
        {
            return (m_pInvDescMap+EntryIndex)->epos();
        }
    }
    return 0;
}

#endif  /* LOG_INV_DESC_MAP_H */
