/*!
  @file           Catalog_TableObject.hpp
  @author         ThomasA
  @brief          representation of a table descriptor in 
  @see            example.html ...
  @first created  000-03-09  18:21

\if EMIT_LICENCE

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



\endif
*/


#ifndef CATALOG_TABLEOBJECT_HPP
#define CATALOG_TABLEOBJECT_HPP
#include "SQLManager/Catalog/Catalog_Types.hpp"
#include "RunTime/Synchronisation/RTESync_Spinlock.hpp"

#if defined BIT64
#define CATALOG_ALIGN_MASK 7
#else
#define CATALOG_ALIGN_MASK 3
#endif

class SAPDBMem_IRawAllocator;
class SQLMan_Context;

/*!
  @brief encapsulation of pascal type tak_baserecord
*/

class Catalog_TableObject : public Catalog_TableObjectPascal
{
public :
	/*!
	   @brief creates a copy of this using the given allocator
    */
    void* CreateCopy (SAPDBMem_IRawAllocator& allocator, int offset, SAPDB_UInt4& heapUsage);
	/*!
	   @brief deletes the memory containing the column information of the in the given allocator
    */
	void DestroyColumns(SAPDBMem_IRawAllocator& allocator);
    /*!
	   @brief increments the reference counter of the column buffer
    */
    inline void IncColBufferRefCount();
    /*!
	   @brief decrements the reference counter of the column buffer. If the counter becomes 0
              the column buffer is released using the given allocator
    */
    inline void DecColBufferRefCount(SAPDBMem_IRawAllocator& allocator);
    /*!
      @brief stores the table object persistently 
    */
    void outcopy(SQLMan_Context& context);
    /*!
      @brief transforms the consistent layout into a Catalog_TableObject 
    */
    static Catalog_TableObject* incopy(SQLMan_Context& context, const SQLMan_Surrogate& tableId);
private :
    struct ColumnBuffer
    {
        SAPDB_Int4              m_sharedFlag;
        SAPDB_Int4              m_refCount;
        SQLMan_Identifier       m_tableName;
        unsigned char           m_colBuffer;
        void IncRefCount();
        int  DecRefCount(SAPDBMem_IRawAllocator& allocator);
        ColumnBuffer (const SQLMan_Identifier& tableName);
        void* operator new (size_t size, SAPDBMem_IRawAllocator& allocator, int bufferLen);
    };
    inline static int GetColumnInfoLength (Catalog_ColumnInfo& columnInfo);
    inline static int CalcAlignedLength(int length);

    static RTESync_Spinlock m_refCountSynchronizer;
    friend struct Catalog_TableObject::ColumnBuffer;
};

inline void Catalog_TableObject::IncColBufferRefCount()
{
    REINTERPRET_CAST(ColumnBuffer*, bptr)->IncRefCount();
}

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

inline void Catalog_TableObject::DecColBufferRefCount(SAPDBMem_IRawAllocator& allocator)
{
    if (bptr)
    {
        REINTERPRET_CAST(ColumnBuffer*, bptr)->DecRefCount(allocator);
        bptr = 0;
    }
}

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

inline int Catalog_TableObject::GetColumnInfoLength (Catalog_ColumnInfo& columnInfo)
{
    return sizeof(columnInfo) - sizeof(columnInfo.ccolumnn()) + columnInfo.ccolumnn_len();
}

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

inline int Catalog_TableObject::CalcAlignedLength(int length)
{
    return (length + CATALOG_ALIGN_MASK) & ~(CATALOG_ALIGN_MASK);
}

#endif