/*!
 * \file    OMS_Session.hpp
 * \author  IvanS, MarkusSi, PeterG
 * \brief   OMS session
 */
/*

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

#include "Oms/OMS_SessionDef.hpp"
#include "Oms/OMS_Context.hpp"
#include "Oms/OMS_ISessionLockObjects.hpp"
#include "Oms/OMS_ObjectContainer.hpp"
#include "Oms/OMS_VersionDirRegions.hpp"
#include "SAPDBCommon/SAPDB_MemCopyMove.hpp"

class OMS_SessionCriticalSection : public OMS_SinkCriticalSection {
public:
  OMS_SessionCriticalSection(OMS_Session* session,int regionId) : OMS_SinkCriticalSection(session->m_lcSink, regionId) {} 
};

/*----------------------------------------------------------------------*/
/*               Implementation of OMS_Session                      */
/*----------------------------------------------------------------------*/

inline void* OMS_Session::operator new(size_t sz)
{
  return OMS_Globals::m_sharedMemAllocatorInstance.allocate(sz);
}

/*----------------------------------------------------------------------*/
#if defined(OMS_PLACEMENT_DELETE)
inline void OMS_Session::operator delete(void* p)
{
  REINTERPRET_CAST(OMS_Session*, p)->DeleteSession();
}
#endif

/*----------------------------------------------------------------------*/

inline void OMS_Session::ActivateDefaultContext() 
{
  m_context = m_defaultContext;
  this->ChangedConsistentView();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::AddContainerInfo(OMS_ClassIdEntry* containerInfo) 
{
  m_context->m_containerDir.HashInsert (containerInfo);
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::AssertNotReadOnly(const char* callerMsg) 
{
  if (m_read_only)
  {
    this->ThrowDBError (e_oms_read_only, callerMsg, __MY_FILE__, __LINE__);
  }
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::CloseVersion()
{
  this->IncCloseVersion();
  m_context->CloseVersion();
  this->ActivateDefaultContext();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::ClearFreeLists(int caller)
{
  m_defaultContext->m_containerDir.ClearFreeLists(caller);
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::ClearTransVersions()
{
  if (!m_versionsBoundToTrans.empty()) {

    cgg251dclIterator<OMS_Context*,OMS_Session> iter = m_versionsBoundToTrans.begin();

    while (iter) {
      cgg251dclIterator<OMS_Context*,OMS_Session> delIter = iter;
      OMS_Context* pContext = *iter();
      ++iter;

      { // Begin of exclusive critical section.    // PTS 1124533
        ExclusiveVersionDirRgn rgn(OMS_Globals::m_globalsInstance->GetLockIdForVersionDirectory(pContext->GetVersionId()),
                                   OMS_Globals::m_globalsInstance->GetLockMethodForVersionDictionary());

        pContext->CleanContainerDir();
        if (!pContext->IsVersionOpen()) {
          pContext->MarkNotBoundToTrans(false);
          m_versionsBoundToTrans.remove(delIter);
        }
      } // End of exclusive critical section.
    }
  }

  // clear list of created versions in transaction
  if (!m_createdVersionsInTrans.empty()) {
    cgg251dclIterator<OMS_Context*,OMS_Session> iter = m_createdVersionsInTrans.begin();

    while (iter) {
      cgg251dclIterator<OMS_Context*,OMS_Session> delIter = iter;
      ++iter;
      m_createdVersionsInTrans.remove(delIter);
    }
  }
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::CreateDefaultContext() 
{
  m_defaultContext = new OMS_Context(this);
  m_context        = m_defaultContext;
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::CommitSubtrans(int requiredLevel)
{

  if (!this->IsSubtransOpen()) {
	  return;
  }
  if (-1 == requiredLevel) {
    requiredLevel = this->CurrentSubtransLevel();
  }
  this->IncSubtransCommit();
  this->ExecuteSubtransCommit(requiredLevel);
}

/*----------------------------------------------------------------------*/

#if defined(OMSTST)
inline void OMS_Session::CheckCancelCountDown()
{
  if (m_cancelCountDown > 0)
  {
    --m_cancelCountDown;
    if (0 == m_cancelCountDown)
    {
       m_cancelCountDown         = -1;
       m_toCancel                = true;
       m_requiredExceptionThrown = true;
    }
  }
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::CheckExceptionCountDown()
{
  if (m_exceptionCountDown > 0)
  {
    --m_exceptionCountDown;
    if (0 == m_exceptionCountDown)
    {
       m_exceptionCountDown      = -1;
       m_requiredExceptionThrown = true;
       this->ThrowDBError (e_requested_dbperror, "user requested exception", __MY_FILE__, __LINE__);
    }
  }
}
#endif

/*----------------------------------------------------------------------*/

inline OMS_Context* OMS_Session::CurrentContext() const
{
  return m_context;
}

/*----------------------------------------------------------------------*/

inline int OMS_Session::CurrentSubtransLevel() const 
{
  return m_subtrans_lvl;
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::DecSubtransLevel()
{
  --m_subtrans_lvl;
}

/*----------------------------------------------------------------------*/

inline OmsAbstractObject* OMS_Session::DeRef (const OmsObjectId& oid, const ClassIDRef guid, bool forUpd, bool doLock) 
{
  const char* msg = "OMS_Session::DeRef";
   
  OmsObjectContainerPtr found = m_context->GetObj (guid, oid, doLock);
  if (found) {
    if ((doLock) && (!found->LockedFlag()) && (!m_context->IsVersion())) {
      m_context->LockObj(found->m_oid);
    }
    if (forUpd) {
      return this->ForUpdPtr(found);
    }

    return &found->m_pobj;
  }
  else {
    this->ThrowDBError (e_object_not_found, msg, oid, __MY_FILE__, __LINE__);
    return NULL;
  }
}

/*----------------------------------------------------------------------*/

inline OmsAbstractObject* OMS_Session::DeRefViaKey (unsigned char*  key, 
                                                        const ClassIDRef guid, 
                                                        bool            forUpd, 
                                                        bool            doLock, 
                                                        OmsSchemaHandle Schema,
                                                        OmsContainerNo  ContainerNo)
{
  OMS_ClassIdEntry*     clsinfo = this->GetClsInfo (guid, Schema, ContainerNo);
  OmsObjectContainerPtr found = NULL;
  if (clsinfo->UseCachedKeys()) {    // PTS 1117571
    found = m_context->GetObjViaCachedKey(*clsinfo, key, doLock);
  }
  else {
    found   = m_context->GetObjViaKey(*clsinfo, key, doLock);
  }


  if (NULL != found) {
    if (forUpd) {
      return this->ForUpdPtr(found);
    }
    return &found->m_pobj;
  }
  return NULL;
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::DeleteSession()
{
  --m_refCnt;
  if (0 == m_refCnt) {
    this->OMS_Session::~OMS_Session();
    OMS_Globals::m_sharedMemAllocatorInstance.deallocate(this);
  }
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::ExecuteSubtransCommit(int requiredLevel)
{
  tsp00_Int2     DBError;
  OMS_HResult hr;
  m_beforeImages.subtransCommit (requiredLevel); 
  while (this->CurrentSubtransLevel() >= requiredLevel) {
    if (this->CurrentSubtransLevel() > 1) {
      hr = m_lcSink->SubtransCommit( &DBError);
      if ( 0 != DBError ) { 
        this->ThrowReturnCode (DBError, "omsCommitSubtrans", __MY_FILE__, __LINE__);
      }
    }
    this->DecSubtransLevel();
  }
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::deallocate(void* p) 
{
#ifdef USE_SYSTEM_ALLOC_CO13
  delete[] (char*) p;
#else
  m_heap.Deallocate(p);
#endif
}

/*----------------------------------------------------------------------*/

inline bool OMS_Session::ForceReadOnly()
{
  bool ret        = m_read_only;
  m_read_only     = true;
  m_allowReadOnly = false;
  return ret;
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::FreeStackHeap()
{
#ifndef USE_SYSTEM_ALLOC_CO13
  m_stackHeap.Free();
#endif
}

/*----------------------------------------------------------------------*/

inline OmsAbstractObject* OMS_Session::ForUpdPtr(OmsObjectContainerPtr pObj)
{
  const char* msg = "OMS_Session::ForUpdPtr";
  this->AssertNotReadOnly(msg);
  this->InsertBeforeImage (pObj);
  return &pObj->m_pobj;
}

/*----------------------------------------------------------------------*/

inline OMS_GuidEntry* OMS_Session::GetClassInfo(const ClassIDRef guid)
{
  return m_context->GetClassInfo (guid);
}

/*----------------------------------------------------------------------*/

inline OmsCallbackInterface* OMS_Session::GetCallbackInterface() const
{
  return m_callbackInterface;
}

/*----------------------------------------------------------------------*/

inline OmsCallbackInterface* OMS_Session::GetCallbackInterface(const ClassIDRef guid) const
{
  if (m_callbackInterfaceGuid == guid) {
    return m_callbackInterface;
  }
  else {
    return NULL;
  }
}

/*----------------------------------------------------------------------*/

inline OMS_ClassIdEntry* OMS_Session::GetClsInfo(const ClassIDRef guid, OmsSchemaHandle Schema, OmsContainerNo ContainerNo) 
{
  return m_context->m_containerDir.HashFind (guid, Schema, ContainerNo);
}

/*----------------------------------------------------------------------*/

inline OMS_ClassIdEntry* OMS_Session::GetClsInfoForReg(const ClassIDRef guid, OmsSchemaHandle Schema, OmsContainerNo ContainerNo) 
{
  return m_context->m_containerDir.HashFindForReg (guid, Schema, ContainerNo);
}

/*----------------------------------------------------------------------*/

inline OMS_ClassIdEntry* OMS_Session::GetContainerInfo(tsp00_Uint4 containerHandle) 
{
  return m_context->GetContainerInfo(containerHandle);
}

/*----------------------------------------------------------------------*/

inline OmsObjectContainerPtr OMS_Session::GetMemory (OMS_ClassIdEntry& clsid) 
{ 
  OmsObjectContainerPtr p;

  p = clsid.m_freeHead->free;
  if (NULL != p) {
    p->CheckFreeListState();
    clsid.m_freeHead->free = p->GetNextFreeList();
  }
  else {
    if (this->InVersion()) {
      p = (OmsObjectContainerPtr) m_context->allocate(clsid.GetObjectSize());
    }
    else {
      p = (OmsObjectContainerPtr) StackHeapMalloc(clsid.GetObjectSize());
    }
  }
  if (NULL != p) {
    p->InitObjContainer(clsid);
    if (p->VarObjFlag()) // PTS 1111943
    {
      new(&p->m_pobj) OMS_VarObjInfo();
    }
  }
  return p;
}

/*----------------------------------------------------------------------*/

inline OmsObjectContainerPtr OMS_Session::GetMemoryInVersion (OMS_ClassIdEntry& clsid)
{ 
  OmsObjectContainerPtr p;

  tsp00_Int4 size = (clsid.GetObjectSize() + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
  p = clsid.m_freeHeadInVersion->free;
  if (NULL != p) { 
    p->CheckFreeListState();
    clsid.m_freeHeadInVersion->free = p->GetNextFreeList();
  }
  else {
    p = (OmsObjectContainerPtr) m_context->allocate(size + 2 * sizeof(void*));
  }
  if (NULL != p) {
    p->InitObjContainer(clsid);
    p->InitVerNew(size);
  }
  return p;
}

/*----------------------------------------------------------------------*/

inline OmsObjectContainerPtr OMS_Session::GetMemory (OMS_GuidEntry& classInfo)
{

  OmsObjectContainerPtr p;

  p = classInfo.m_freeHead->free;
  if (NULL != p) { 
    p->CheckFreeListState();
    classInfo.m_freeHead->free = p->GetNextFreeList();
  }
  else {
    if (this->InVersion()) {
      p = (OmsObjectContainerPtr) m_context->allocate(classInfo.GetObjectSize());
    }
    else {
      p = (OmsObjectContainerPtr) StackHeapMalloc(classInfo.GetObjectSize());
    }
  }
  if (NULL != p) {
    p->InitObjContainer(classInfo);
    if (p->VarObjFlag()) // PTS 1111943
    {
      new(&p->m_pobj) OMS_VarObjInfo();
    }
  }
  return p;
}

/*----------------------------------------------------------------------*/

inline OMS_ISessionLockObjects* OMS_Session::GetSessionLockObject() const
{
  return m_lockObjects; 
}

/*----------------------------------------------------------------------*/

inline long OMS_Session::GetStoredErrorCode() const  // PTS 1122839
{
  return m_errorCode;
}

/*----------------------------------------------------------------------*/

inline tsp00_TaskId  OMS_Session::GetTaskId() const // PTS 1110315
{
  return m_taskId;
}

/*----------------------------------------------------------------------*/

inline unsigned char* OMS_Session::GetVarObjMemory(size_t sz)
{
  this->MonitorVarObjSize((tsp00_Int4) sz);
  return REINTERPRET_CAST(unsigned char*, m_context->allocate(sz));
}

/*----------------------------------------------------------------------*/

inline tsp00_Int4 OMS_Session::GetVarObjSize(const OmsVarOid& oid) 
{

  const char* msg = "OMS_Context::GetVarObjSize";
  OmsObjectContainerPtr pObj = m_context->FindObjInContext (&oid);
  if (NULL != pObj) {
    if (pObj->DeletedFlag()) {
      ThrowDBError (e_object_not_found, msg, oid, __MY_FILE__, __LINE__);
    }
    OMS_VarObjInfo* pObjInfo;
    pObjInfo = REINTERPRET_CAST (OMS_VarObjInfo*, &pObj->m_pobj);
    return pObjInfo->m_vobjSize;
  }
  tsp00_Int4 objSize = m_context->GetVarObjFromLiveCacheBase(oid, false);
  m_context->LoadVarObject(oid, VarObjNoLock, objSize, m_currVarObjChunk, NULL);
  return objSize;
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncRefCnt()
{
  ++m_refCnt;
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncCacheHit(const OmsObjectId& oid)
{
  if (!InVersion()) 
  {
    m_monitor.IncOmsReadCacheHit();
  }
  else if (CurrentContext()->IsVersionOid(oid)){
    m_monitor.IncOmsReadVersion();
  }
  else {
    m_monitor.IncOmsReadCacheHit();
  }
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncCacheMiss()
{
    m_monitor.IncOmsReadCacheMiss();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncDeref()
{
  --m_rescheduleDistance;
  if (m_rescheduleDistance <= 0) { /* PTS 1107849 */
    m_rescheduleDistance = RESCHEDULE_DISTANCE;
    this->Reschedule();
  }  
  m_monitor.IncDeref();
}

/*----------------------------------------------------------------------*/

inline void  OMS_Session::IncDerefIter_LC()
{ // PTS 1107819 TA 13/09/2000 
  m_monitor.IncDerefIter();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncDereflC()
{
  if (InVersion()) 
  {
    m_monitor.IncLCDerefInVersion();
  } 
  else 
  {
    m_monitor.IncDerefLCBase();
  }
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncDerefKey()
{
  if (InVersion()) 
  {
    m_monitor.IncLCKeyDerefInVersion();
  }
  else {
    m_monitor.IncKeyDeref();
  }
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncOmsTerminate()
{
  m_monitor.IncOmsTerminate();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncStore() 
{
  m_monitor.IncStore();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncStore_lC() 
{
  if (InVersion())
  {
    m_monitor.IncStoreInVersion();
    
  }
  else 
  {
    m_monitor.IncLCStore();
  }
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncReadStreamBuffer()
{
  m_monitor.IncReadSteam();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncRehash()
{
  m_monitor.IncRehash();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncWriteStreamBuffer()
{
  m_monitor.IncWriteSteam();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncReadStreamRow()
{
  m_monitor.IncReadStreamRow();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncWriteStreamRow()
{
  m_monitor.IncWriteStreamRow();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncDelete ()
{
  m_monitor.IncDelete();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncDelete_lC(tsp00_Int4 cntDeleted) 
{
  if (InVersion()) 
  {
    m_monitor.IncDeleteInVersion(cntDeleted);
  }
  else 
  {
    m_monitor.IncLCDelete(cntDeleted);
  }
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncDelete_lC() 
{
  IncDelete_lC(1);
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncLock() 
{
  m_monitor.IncLock();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncLogHop(int cnt) 
{
  m_monitor.IncLogHops(cnt);
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncLogHopIter(int cnt) 
{ // PTS 1107819 TA 13/09/2000
  m_monitor.IncLogHopsIter(cnt);
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncExceptions() 
{
  m_monitor.IncExceptions();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncOutOfDate() 
{
  m_monitor.IncOutOfDate();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncOutOfMemory() 
{
  m_monitor.IncBadAlloc();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncTimeout() 
{
  m_monitor.IncTimeout();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncSubtransCommit() 
{
  m_monitor.IncSubtransCommit();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncSubtransRollback()
{
  m_monitor.IncSubtransRollback();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncLoadVarObj() 
{
  m_monitor.IncLoadVarObject();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncLoadVarObjLC() 
{
  m_monitor.IncLoadVarObjectLC();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncStoreVarObj()
{
  m_monitor.IncStoreVarObject();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncStoreVarObjLC() 
{
  m_monitor.IncLCStoreVarObj();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::MaxHashChainLen (int len)
{ // PTS 1118855
  m_monitor.MaxHashChainLen(len);
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::MonitorSubtransLevel() 
{
  m_monitor.MaxSubtransLevel(m_subtrans_lvl);
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::SetCacheSize(tsp00_Uint4 sz) 
{
  m_monitor_curr->cmiCounters_gg00[cmiCacheSize] = sz;
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncCreateVersion () 
{
  m_monitor.IncCreateVersion();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncOpenVersion () {
  m_monitor.IncOpenVersion();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncCloseVersion () 
{
  m_monitor.IncCloseVersion();
}   

/*----------------------------------------------------------------------*/
        
inline void OMS_Session::IncDropVersion () 
{
  m_monitor.IncDropVersion();
}             

/*----------------------------------------------------------------------*/          

inline void OMS_Session::IncDeleteVarObject ()
{
   m_monitor.IncDeleteVarObject();
}      

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncDeleteVarObjectLC () 
{
   m_monitor.IncLCDeleteVarObj();
}              

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncSubtransLevel () 
{
  ++m_subtrans_lvl;
  this->MonitorSubtransLevel();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncCntWaitOmsLockObj() {
      m_monitor.IncCntWaitOmsLockObj();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::IncWaitOmsLockObjSecs(tsp00_Int4 secs)
{
    m_monitor.IncWaitOmsLockObjSecs(secs);
}
 
/*----------------------------------------------------------------------*/

inline bool OMS_Session::InsertBeforeImage (OmsObjectContainerPtr p)
{
  int subtransLvl = this->CurrentSubtransLevel();
  if (!(p->existBeforeImage (subtransLvl, m_context->IsVersion() || OMS_Globals::m_globalsInstance->InSimulator()))) {
    if ((subtransLvl > m_min_subtrans_lvl) || (this->InVersion())) {
      m_beforeImages.insertBeforeImage (p, subtransLvl);
      return true;
    }
  }
  return false;
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::InsertNewBeforeImage (OmsObjectContainerPtr p, OMS_ClassIdEntry* clsinfo)
{
  int subtransLvl = this->CurrentSubtransLevel();
  if ((subtransLvl > m_min_subtrans_lvl) || (this->InVersion())) {
    m_beforeImages.insertNewBeforeImage (p, clsinfo, subtransLvl);
  }
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::InsertTransVersion(OMS_Context* context, bool create)
{
  if (!this->VersionBoundByMe(context)) {
    m_versionsBoundToTrans.insert(context);
  }
  context->MarkBoundToTrans();
  if (create) {
    m_createdVersionsInTrans.insert(context);
  }
}

/*----------------------------------------------------------------------*/

inline bool OMS_Session::InVersion()
{
  return (m_context != m_defaultContext);
}

/*----------------------------------------------------------------------*/

inline bool OMS_Session::IsDefaultContext( OMS_Context* context)
{
  return (context == m_defaultContext);
}

/*----------------------------------------------------------------------*/

inline bool OMS_Session::IsSubtransOpen()
{
  return (m_subtrans_lvl > 1);
}

/*----------------------------------------------------------------------*/

inline OmsObjectContainerPtr OMS_Session::LoadVarObject (const OmsVarOid& oid, OMS_VarObjLockType lockReq, tsp00_Int4 size, void* buf) 
{
  const char* msg = "OMS_Session::LoadVarObject";
  
  this->IncLoadVarObj();
  OmsObjectContainerPtr p = m_context->FindVarObjInContext(oid, lockReq, size, buf);
  if (NULL != p) {
    return p;
  }
  tsp00_Int4 objSize = m_context->GetVarObjFromLiveCacheBase(oid, false);
  if ((size < objSize) && (buf != NULL)) {
    this->ThrowDBError (e_too_small_packet_size, msg, oid, __MY_FILE__, __LINE__);
  }
  p = m_context->LoadVarObject(oid, lockReq, objSize, m_currVarObjChunk, buf);
  m_currVarObjChunk.Clear();
  return p;
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::LockObj(OmsObjectContainerPtr p)
{
  tgg00_BasisError    DBError;
  OMS_UnknownContainerId FileId;
  OMS_HResult hr = m_lcSink->LockObj (
    (unsigned char*) &m_context->m_consistentView,
    (unsigned char*) &FileId, //TODO so lassen ??
    REINTERPRET_CAST(OmsTypeOid*, &p->m_oid),
    (unsigned char*) &p->m_objseq,
    &DBError);
  m_context->LockResult (DBError, p, p->m_oid, "OMS_Session::LockObj");
  this->IncLock();
}

/*----------------------------------------------------------------------*/

inline bool OMS_Session::TryLockObj(OmsObjectContainerPtr p)
{
  tgg00_BasisError    DBError;
  OMS_UnknownContainerId FileId;
  OMS_HResult hr = m_lcSink->LockObj (
    (unsigned char*) &m_context->m_consistentView,
    (unsigned char*) &FileId, //TODO so lassen ??
    REINTERPRET_CAST(OmsTypeOid*, &p->m_oid),
    (unsigned char*) &p->m_objseq,
    &DBError);
  bool retval = m_context->TryLockResult (DBError, p, p->m_oid, "OMS_Session::TryLockObj");
  this->IncLock();
  return retval;
}

/*----------------------------------------------------------------------*/

inline void* OMS_Session::allocate(size_t sz)
{
#ifdef USE_SYSTEM_ALLOC_CO13
  return new char[sz];
#else
  return m_heap.Allocate((SAPDB_ULong) sz);
#endif
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::MonitorVarObjSize(tsp00_Int4 size)
{
  m_monitor.MonitorVarObjSize(size);
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::MonitorWaitNewConsistentView(tsp00_Int4 runTime)
{
  m_monitor.MonitorNewConsistentView(runTime);
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::OpenVersionProlog(const OmsVersionId &versionId, bool create)   // PTS 1129082
{
  if (create) {
    // no modifications allowed before create
    m_defaultContext->VersionClearObjCache();
  } else {
    // check for empty only if exists in created trans
    cgg251dclIterator<OMS_Context*,OMS_Session> iter = m_createdVersionsInTrans.begin();

    while (iter) {
      OMS_Context* pContext = *iter();
      if (!memcmp(pContext->GetVersionId(), versionId, sizeof(OmsVersionId))) {
        // created in this trans
        m_defaultContext->VersionClearObjCache();
        break;
      }
      ++iter;
    }
  }

  // As the consistent view is closed when opening a version, remove all non-changed objects
  // out of the hash. Otherwise these objects would become visible again (in a different 
  // consistent view) after the version has been closed.
  // Objects which has been changed can remain in the cache, as these objects could not be
  // modified by concurrent transactions, as they are locked.
  OMS_OidHash::OidIter iter = m_defaultContext->m_oidDir.First();
  while (iter) {
    OmsObjectContainer *p = iter();
    ++iter;

    if (!p->DeletedFlag() && !p->StoredFlag() && !p->LockedFlag()){
      m_defaultContext->DeleteObjInContext(p, p->GetContainerInfo (m_defaultContext));
    }
  }
}

/*----------------------------------------------------------------------*/
 
inline void OMS_Session::OpenVersionEpilog()  // PTS 1129082
{
  short   DBError;
  HRESULT hr;

  /* current context is default context, release current consistent view */
  if (m_defaultContext->ExistsConsistentView()) {
    hr = m_lcSink->EndConsistentView((unsigned char*) &m_defaultContext->m_consistentView, &DBError);
    if FAILED (hr) {
      throw DbpError (DbpError::HRESULT_ERROR, hr, __MY_FILE__, __LINE__);
    }
    if ( 0 != DBError ) { 
      throw DbpError (DbpError::DB_ERROR, DBError, "OmsSession::OpenVersionEpilog", __MY_FILE__, __LINE__);
    }
  }
}
 
/*----------------------------------------------------------------------*/

inline void OMS_Session::OpenVersion(OMS_Context* context, bool create) 
{
  m_context = context;
  m_context->OpenVersion(this);
  this->ChangedConsistentView();
  this->InsertTransVersion(context, create);
}

/*----------------------------------------------------------------------*/


inline void OMS_Session::ReleaseObj(const OmsObjectId& oid) 
{
  OmsObjectContainerPtr found = m_context->FindObjInContext(&oid);
  if (found) {
    this->ReleaseObj(found);
  }
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::ReleaseObj(OmsObjectContainerPtr p, bool unchangedOnly)
{
  // Objects are NOT released from the cache if:
  // 1)  the object is 'changed' AND
  // 2a) a version is open OR
  // 2b) a subtransaction is open
  //
  // An object is considered as 'changed' if:
  // * A lock has been aquired on the object AND the object is no var-object OR
  // * the object is marked as to be stored (omsStore) OR
  // * the object is marked as to be deleted OR
  // * a before-image of this object exists (omsForUpd)  // PTS 1128262

  const bool releaseUpdatedObj 
    =  (unchangedOnly ? false
                      : (!m_context->IsVersion() && !IsSubtransOpen()));

  m_monitor.OmsIncOmsRelease(); // PTS 1133312

  if (p->DeletedFlag()) 
  {
    if (releaseUpdatedObj) 
    {
      if (p->IsNewObject())
      {
        // UPdate counter which keeps track of how many objects must be flushed during a commit.
        // This counter is only for analysis purpose.
        OMS_DETAIL_TRACE(omsTrNewObj, m_lcSink, 
          "OMS_Session::ReleaseObj : new deleted obj " << p->m_oid 
          << ", class: " << p->GetContainerInfo(m_context)->GetClassInfoPtr()->GetClassName());
        m_context->DecNewObjectsToFlush();
      }
      m_monitor.OmsIncOmsReleaseExecuted(); // PTS 1133314
      m_context->FlushDelete (p, true);
    }
    return;
  }
  else if (p->StoredFlag()) 
  {
    if (releaseUpdatedObj) 
    {
      if (p->IsNewObject())
      {
        OMS_DETAIL_TRACE(omsTrNewObj, m_lcSink,
          "OMS_Session::ReleaseObj : new stored obj " << p->m_oid 
          << ", class: " << p->GetContainerInfo(m_context)->GetClassInfoPtr()->GetClassName());
        m_context->DecNewObjectsToFlush();
      }
      m_context->FlushObj(p);
    }
    else {
      return;
    }
  }
  else if (p->LockedFlag()) {
    if ((releaseUpdatedObj) && (!p->VarObjFlag())) {
      m_context->FlushLockUpdObj (p);
    }
    else {
      return;
    }
  }
  else if (p->GetBeforeImageMask() != 0){  // PTS 1140951
    if (!releaseUpdatedObj){
      return;
    }
  }
  m_monitor.OmsIncOmsReleaseExecuted(); // PTS 1133312
  m_context->DeleteObjInContext(p, p->GetContainerInfo (m_context));
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::ReleaseObjUnconditional(const OmsObjectId& oid)
{
  OmsObjectContainerPtr found = m_context->FindObjInContext(&oid);
  if (found) {
    m_context->DeleteObjInContext(found, found->GetContainerInfo (m_context));
  }
}
/*----------------------------------------------------------------------*/

#if defined(OMSTST)

inline bool OMS_Session::RequiredExceptionThrown() const
{
  return m_requiredExceptionThrown;
}

#endif

/*----------------------------------------------------------------------*/

/* PTS 1107849 */  
inline void OMS_Session::Reschedule() 
{
  if (m_toCancel) 
  {
    m_toCancel = false;
    ThrowDBError(e_cancelled, "Reschedule", __MY_FILE__, __LINE__);
  }

  m_lcSink->Reschedule();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::RollbackSubtrans(int requiredLvl, bool callFromRollbackTrans)
{
  tgg00_BasisError DBError;
  OMS_HResult    hr;
 
  if (-1 == requiredLvl) {
    requiredLvl = this->CurrentSubtransLevel();
  }
  m_beforeImages.subtransRollback (requiredLvl); 
  while (this->CurrentSubtransLevel() >= requiredLvl) {
    if ((this->CurrentSubtransLevel() > m_min_subtrans_lvl) && (!callFromRollbackTrans)) 
    {
      hr = m_lcSink->SubtransRollback( &DBError);
      if ( e_ok != DBError ) { 
        this->ThrowReturnCode (DBError, "RollbackSubtrans", __MY_FILE__, __LINE__);
      }
    }
    this->DecSubtransLevel();
  }
  m_currVarObjChunk.Clear();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::ResetSubtransLevel () 
{
  m_subtrans_lvl = 1;
}

/*----------------------------------------------------------------------*/
#if defined(OMSTST)

inline void OMS_Session::SetCancelCountDown(int countDown)
{
  if (0 == countDown) 
  {
    countDown = 1;
  }
  else
  {
    if (countDown < 0)
    {
      countDown = -1;
    }
  }
  m_cancelCountDown = countDown;
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::SetExceptionCountDown(int countDown)
{
  if (0 == countDown) 
  {
    countDown = 1;
  }
  else
  {
    if (countDown < 0)
    {
      countDown = -1;
    }
  }
  m_exceptionCountDown = countDown;
}
#endif

/*----------------------------------------------------------------------*/

inline void OMS_Session::SetSessionLockObject(OMS_ISessionLockObjects* pLockObj)
{
  m_lockObjects = pLockObj;
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::Signal(tsp00_TaskId TaskId, tsp00_Bool ok) // PTS 1110315
{
  m_lcSink->Signal(TaskId, ok);
}

/*----------------------------------------------------------------------*/

inline void* OMS_Session::StackHeapMalloc(size_t size)
{
#ifdef USE_SYSTEM_ALLOC_CO13
  return new char[size];
#else
  return m_stackHeap.Malloc(size);
#endif
}

/*----------------------------------------------------------------------*/

inline int OMS_Session::StartSubtrans()
{
  
  const char* msg = "OMS_Session::StartSubtrans";
  tsp00_Int2  DBError;
  if (this->CurrentSubtransLevel() >= OMS_BEFOREIMAGE_MAX_SUBTRANS_LEVEL) {
    this->ThrowDBError (e_too_many_subtrans, msg, __MY_FILE__, __LINE__);      
  }
  OMS_HResult hr = m_lcSink->SubtransStart(&DBError);
  if ( 0 != DBError ) { 
    this->ThrowDBError (DBError, msg, __MY_FILE__, __LINE__);
  }
  this->IncSubtransLevel();
  return this->CurrentSubtransLevel();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::StoreErrorCode(long errorCode)   // PTS 1122839
{
  m_errorCode = errorCode;
}

/*----------------------------------------------------------------------*/

inline void OMS_Session:: StoreVarObject (const OmsVarOid& oid, const void* pVarObj, unsigned long objLength) 
{
  bool                  freeBeforeImage = true;
  OmsObjectContainerPtr found           = this->LoadVarObject (oid, VarObjNoLock, -1, NULL);
  if (NULL == found) {
      this->ThrowDBError (e_object_not_found, "StoreVarObject", oid, __MY_FILE__, __LINE__);
  }
  if (!found->LockedFlag()) {
    if (!IsLocked(oid)) {
      this->ThrowDBError (e_object_not_locked, "StoreVarObject", oid, __MY_FILE__, __LINE__);
    }
  }
  this->IncStoreVarObj(); 
  if (m_currVarObjChunk.m_oid == oid) {
    m_currVarObjChunk.Clear();
  }
  OMS_VarObjInfo* objInfo = REINTERPRET_CAST (OMS_VarObjInfo*, &found->m_pobj);
  if (!(found->existBeforeImage (this->CurrentSubtransLevel(), this->InVersion()))) { 
    this->ForUpdPtr(found); 
    freeBeforeImage = false;
  }
  if ((objInfo->m_vobjSize != objLength) || (!freeBeforeImage)) {
    if (freeBeforeImage) {
      objInfo->freeVarObjData(m_context);
    }
    objInfo->m_pvobj = NULL;
    objInfo->m_pvobj = this->GetVarObjMemory(objLength);
  }
  objInfo->m_vobjSize = objLength;
  SAPDB_MemCopyNoCheck (objInfo->m_pvobj, pVarObj, objLength);
  found->MarkStored();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::TransEndEpilog()
{
  m_lockObjects->TransactionEnd();
}

/*----------------------------------------------------------------------*/

inline void OMS_Session::UnforceReadOnly(bool readOnly)
{
  m_read_only     = readOnly;
  m_allowReadOnly = true;
}

/*----------------------------------------------------------------------*/

inline void  OMS_Session::FreeBeforeImages()
{
  /* free before images */
  m_beforeImages.freeBeforeImages();
  m_subtrans_lvl = 1;
}

/*----------------------------------------------------------------------*/

void inline OMS_Session::ReleaseAllUnchanged()    // PTS 1128262
{
  m_context->ReleaseAllUnchanged();
}
   
#endif  // __OMS_SESSION_HPP
