/*

    ========== licence begin  GPL
    Copyright (c) 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 __OMS_OBJECTCONTAINER_HPP
#define __OMS_OBJECTCONTAINER_HPP

#include "Oms/OMS_ObjectContainerDef.hpp"
#include "Oms/OMS_ClassIdEntry.hpp"
#include "Oms/OMS_GuidEntry.hpp"
#include "Oms/OMS_VarObjInfo.hpp"
#include "SAPDBCommon/SAPDB_MemCopyMove.hpp"

inline tsp00_Int4 OmsObjectContainer::headerSize() 
{
  return (sizeof (OmsObjectContainer) - sizeof (OmsAbstractObject));
}

inline void OmsObjectContainer::InitObjContainer(OMS_GuidEntry& classInfo)
{
  void** pvtptr  = REINTERPRET_CAST(void**, (&m_pobj));
  *pvtptr        = classInfo.GetVirtualTablePtr();
  this->InitState(&classInfo);
  m_verstate = 0;
  m_beforeImages = 0;
  m_hashnext     = NULL;
  m_containerInfo   = NULL;
  m_objseq.gg91SetNilRef(); 
}

inline void OmsObjectContainer::InitObjContainer(OMS_ClassIdEntry& clsinfo) 
{
  void** pvtptr  = REINTERPRET_CAST(void**, (&m_pobj));
  *pvtptr        = clsinfo.GetVirtualTablePtr();
  this->InitState(&clsinfo);
  m_verstate = 0;
  m_beforeImages = 0;
  m_hashnext     = NULL;
  m_containerInfo   = NULL;
  m_objseq.gg91SetNilRef(); 
}

inline void OmsObjectContainer::InitState(OMS_GuidEntry* classInfo) 
{
  m_state = 0;
  if ((NULL != classInfo) && (classInfo->IsVarObject())) {
    this->MarkVarObj();
  }
}

inline void OmsObjectContainer::InitState(OMS_ClassIdEntry* clsinfo) 
{ // TODO ?
  m_state = 0;
  if ((NULL != clsinfo) && (clsinfo->IsVarObject())) {
    this->MarkVarObj();
  }
}

inline tsp00_Uint4 OmsObjectContainer::GetContainerHandle() const 
{
  return m_containerInfo->GetContainerHandle();
}

//inline void OmsObjectContainer::ChainFree(OMS_Context* context)
//{
//  OMS_ClassIdEntry* containerInfo = m_containerInfo;
//  OmsObjectContainerPtr p = REINTERPRET_CAST(OmsObjectContainerPtr, this);
//  containerInfo->chainFree(*context, p, 18);
//}

inline OMS_ClassIdEntry* OmsObjectContainer::GetContainerInfo(OMS_Context* context)
{
  context->CheckIfContainerNotDropped(m_containerInfo);
  return m_containerInfo;
}

inline OMS_ClassIdEntry* OmsObjectContainer::GetContainerInfoNoCheck(OMS_Context* context) 
{
  return m_containerInfo;
}

inline void OmsObjectContainer::Copy (OMS_Context* c, OmsObjectContainerPtr beforeImage, int ObjectSize)
{
  tsp00_Int2 refCnt;
  if (this->VarObjFlag()) {
    _OMSASSERT(c->m_session,
      REINTERPRET_CAST(OMS_VarObjInfo*, &beforeImage->m_pobj)->m_vobjInfo.m_vobjNext == 
      REINTERPRET_CAST(OMS_VarObjInfo*, &this->m_pobj)->m_vobjInfo.m_vobjNext);
    refCnt = REINTERPRET_CAST(OMS_VarObjInfo*, &m_pobj)->m_refCnt;
    REINTERPRET_CAST(OMS_VarObjInfo*, &m_pobj)->freeVarObjData(c);
  }
  SAPDB_MemCopyNoCheck (&m_oid, &beforeImage->m_oid, ObjectSize - sizeof(m_hashnext));
  if (this->VarObjFlag()) {
    REINTERPRET_CAST(OMS_VarObjInfo*, &m_pobj)->m_refCnt = refCnt;
    REINTERPRET_CAST(OMS_VarObjInfo*, &beforeImage->m_pobj)->m_pvobj = NULL;
  }
}

inline int OmsObjectContainer::Compare(OMS_Context* c, OmsObjectContainerPtr beforeImage, int ObjectSize)
{
  if (this->VarObjFlag()) {
    // TODO: compare VarObjs
    return 0;
  } else {
    return memcmp(reinterpret_cast<const void**>(&m_pobj) + 1,
      reinterpret_cast<const void**>(&beforeImage->m_pobj) + 1,
      ObjectSize);
  }
}

//inline OmsObjectContainer* OmsObjectContainer::GetNext()
//{
//  unsigned char pattern1[] = {0xfd, 0xfd, 0xfd, 0xfd};
//  unsigned char pattern2[] = {0xad, 0xad, 0xad, 0xad};
//
//  if (!memcmp(this, &pattern1[0], 4)){
//    // Frame is already released from allocator
//    error("Illegal pattern 'fd' found -1-.", this);
//  }
//  else if (!memcmp(this, &pattern2[0], 4)){
//    // Frame is already appended to the freelist
//    error("Illegal pattern 'ad' found -1-.", this);
//  }
//    
//  return m_hashnext;
//}
//
//inline void OmsObjectContainer::SetNext(OmsObjectContainer *p)
//{
//  m_hashnext = p;
//}

inline OmsObjectContainer** OmsObjectContainer::GetNextAddr()
{
  unsigned char pattern1[] = {0xfd, 0xfd, 0xfd, 0xfd};
  unsigned char pattern2[] = {0xad, 0xad, 0xad, 0xad};

  if (!memcmp(this, &pattern1[0], 4)){
    // Frame is already released from allocator
    error("Illegal pattern 'fd' found -2-.", this);
  }
  else if (!memcmp(this, &pattern2[0], 4)){
    // Frame is already appended to the freelist
    error("Illegal pattern 'ad' found -2-.", this);
  }

  return &m_hashnext;
}



inline void OmsObjectContainer::InitializeForFreeList(int caller)
{
  memset (this, 0xad, 4);

  void** pvtptr     = REINTERPRET_CAST(void**, (&m_pobj));
  *pvtptr           = NULL;
  m_beforeImages    = 0;
#if defined(BIT64)
  filler            = 0;
#endif
  m_containerInfo   = NULL;
  memset(&m_oid,    0, sizeof(OmsObjectId));
  memset(&m_objseq, 0, sizeof(tgg91_PageRef));

  m_state     = caller;
  m_verstate  = 0;
}

inline void OmsObjectContainer::InitializeForAllocator(int caller)
{
  CheckFreeListState();
  m_verstate  = caller;
}

inline void OmsObjectContainer::CheckFreeListState()
{
  unsigned char pattern[] = {0xad, 0xad, 0xad, 0xad};
  if (memcmp(this, pattern, 4)){
    // Error
    error("Next-pointer of frame in freelist has been overwritten.", this);
  }

  char nullPattern[] = {0,0,0,0,0,0,0,0};
  void** pvtptr = reinterpret_cast<void**>(&m_pobj);
  if (*pvtptr != NULL || m_beforeImages != 0 || memcmp(&m_oid, &nullPattern, sizeof(OmsObjectId)) || memcmp(&m_objseq, &nullPattern, sizeof(tgg91_PageRef))
#if defined(BIT64)
      || filler != 0 
#endif
     )
  {
    // Error
    error("Header of frame in freelist has been overwritten.", this);
  }
}

inline OmsObjectContainer*  OmsObjectContainer::GetNextFreeList()
{
  return reinterpret_cast<OmsObjectContainer*>(m_containerInfo);
}

inline void OmsObjectContainer::SetNextFreeList(OmsObjectContainer *p)
{
  *reinterpret_cast<OmsObjectContainer**>(&m_containerInfo) = p;
}

//void OmsObjectContainer::error(char* msg, OmsObjectContainer*p)
//Definition is placed in OMS_Globals.cpp because of dependency problems  

#endif  // __OMS_OBJECTCONTAINER_HPP
