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

  module      : OMS_VersionDirRegions.cpp

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

  responsible : MarkusSi

  special area: OMS 
  description : OMS regions for the version directory

  first created: 2003-09-18  

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




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



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


#include "ggg00.h"
#include "Oms/OMS_VersionDirRegions.hpp"
#include "Oms/OMS_Globals.hpp"
#include "Oms/OMS_KernelDefaultInterface.hpp"
#include "Oms/OMS_Trace.hpp"
#include "Oms/OMS_DbpError.hpp"
#include "liveCache/LVC_LockRequest.hpp"
#include "liveCache/LVC_IliveCacheSink.hpp"

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

ExclusiveVersionDirRgn::ExclusiveVersionDirRgn(int lockId, bool useRWLocks) : m_size(1)
{
  //OMS_TRACE(omsTrInterface, co10_GetLcSink(), "Exclusive Region requested: " << lockId);

  m_useRWLocks = useRWLocks;
  m_pLockId[0] = lockId;

  if (useRWLocks){
    // Construct a lock-object and send it to the kernel via kernel-interface
    LVC_LockRequest lock(LVC_LockRequest::RWLOCK_LOCK_EXCLUSIVE, lockId);
    short err = OMS_Globals::GetKernelInterface()->LockRequest(lock);
    if (err != e_ok)
      throw DbpError(DbpError::DB_ERROR, err, "ExclusiveVersionDirRgn::ExclusiveVersionDirRgn-1-", __MY_FILE__, __LINE__);
  }
  else {
    // Enter the critical section via the sink-interface
    OMS_Globals::m_globalsInstance->GetCurrentLcSink()->EnterCriticalSection(lockId);
  }

  //OMS_TRACE(omsTrInterface, co10_GetLcSink(), "Exclusive Region aquired: " << lockId);
}

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

ExclusiveVersionDirRgn::ExclusiveVersionDirRgn(const int *pLockId, int size, bool useRWLocks) : m_size(size)
{
  //OMS_TRACE(omsTrInterface, co10_GetLcSink(), "Exclusive Regions requested: ");
  //for (int j=0; j<m_size; ++j){
  //  OMS_TRACE(omsTrInterface, co10_GetLcSink(), "  " << pLockId[j]);
  //}

  m_useRWLocks = useRWLocks;
  for (int i=0; i<m_size; ++i){
    m_pLockId[i] = pLockId[i];
    if (i>0 && m_pLockId[i] <= m_pLockId[i-1]){
      // The ids must be sorted ascending; otherwise deadlocks might occur
      throw DbpError(DbpError::DB_ERROR, e_invalid_indexorder, "ExclusiveVersionDirRgn::ExclusiveVersionDirRgn-2-", __MY_FILE__, __LINE__);
    }
    if (useRWLocks){
      // Construct a lock-object and send it to the kernel via kernel-interface
      LVC_LockRequest lock(LVC_LockRequest::RWLOCK_LOCK_EXCLUSIVE, m_pLockId[i]);
      short err = OMS_Globals::GetKernelInterface()->LockRequest(lock);
      if (err != e_ok)
        throw DbpError(DbpError::DB_ERROR, err, "ExclusiveVersionDirRgn::ExclusiveVersionDirRgn-3-", __MY_FILE__, __LINE__);
    }
    else {
      // Enter the critical section using the sink interface
      OMS_Globals::m_globalsInstance->GetCurrentLcSink()->EnterCriticalSection(m_pLockId[i]);
    }
  }

  //OMS_TRACE(omsTrInterface, co10_GetLcSink(), "Exclusive Regions aquired: ");
  //for (j=0; j<m_size; ++j){
  //  OMS_TRACE(omsTrInterface, co10_GetLcSink(), "  " << pLockId[j]);
  //}
}

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

ExclusiveVersionDirRgn::~ExclusiveVersionDirRgn()
{
  for (int i=0; i<m_size; ++i){
    if (m_useRWLocks){
      LVC_LockRequest lock(LVC_LockRequest::RWLOCK_UNLOCK_EXCLUSIVE, m_pLockId[i]);
      short err = OMS_Globals::GetKernelInterface()->LockRequest(lock);
      if (err != e_ok)
        throw DbpError(DbpError::DB_ERROR, err, "ExclusiveVersionDirRgn::~ExclusiveVersionDirRgn", __MY_FILE__, __LINE__);
    }
    else {
      OMS_Globals::m_globalsInstance->GetCurrentLcSink()->LeaveCriticalSection(m_pLockId[i]);
    }
  }

  //OMS_TRACE(omsTrInterface, co10_GetLcSink(), "Exclusive Regions freed: ");
  //for (int j=0; j<m_size; ++j){
  //  OMS_TRACE(omsTrInterface, co10_GetLcSink(), "  " << m_pLockId[j]);
  //}
}

/*===========================================================================*/

SharedVersionDirRgn::SharedVersionDirRgn(int lockId, bool useRWLocks) : m_size(1)
{
  //OMS_TRACE(omsTrInterface, co10_GetLcSink(), "Shared Region requested: " << lockId);

  m_useRWLocks = useRWLocks;
  m_pLockId[0] = lockId;

  if (m_useRWLocks){
    // Construct a lock-object and send it to the kernel via kernel-interface
    LVC_LockRequest lock(LVC_LockRequest::RWLOCK_LOCK_SHARED, lockId);
    short err = OMS_Globals::GetKernelInterface()->LockRequest(lock);
    if (err != e_ok)
      throw DbpError(DbpError::DB_ERROR, err, "SharedVersionDirRgn::SharedVersionDirRgn-1-", __MY_FILE__, __LINE__);
  }
  else {
    // Enter the critical section via the sink-interface
    OMS_Globals::m_globalsInstance->GetCurrentLcSink()->EnterCriticalSection(lockId);
  }

  //OMS_TRACE(omsTrInterface, co10_GetLcSink(), "Shared Region aquired: " << lockId);
}

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

SharedVersionDirRgn::SharedVersionDirRgn(const int *pLockId, int size, bool useRWLocks) : m_size(size)
{
  //OMS_TRACE(omsTrInterface, co10_GetLcSink(), "Shared Regions requested: ");
  //for (int j=0; j<m_size; ++j){
  //  OMS_TRACE(omsTrInterface, co10_GetLcSink(), "  " << pLockId[j]);
  //}

  m_useRWLocks = useRWLocks;
  for (int i=0; i<m_size; ++i){
    m_pLockId[i] = pLockId[i];
    if (i>0 && m_pLockId[i] <= m_pLockId[i-1]){
      // The ids must be sorted ascending; otherwise deadlocks might occur
      throw DbpError(DbpError::DB_ERROR, e_invalid_indexorder, "SharedVersionDirRgn::SharedVersionDirRgn-2-", __MY_FILE__, __LINE__);
    }
    if (m_useRWLocks){
      LVC_LockRequest lock(LVC_LockRequest::RWLOCK_LOCK_SHARED, m_pLockId[i]);
      short err = OMS_Globals::GetKernelInterface()->LockRequest(lock);
      if (err != e_ok)
        throw DbpError(DbpError::DB_ERROR, err, "SharedVersionDirRgn::SharedVersionDirRgn-3-", __MY_FILE__, __LINE__);
    }
    else {
      // Enter the critical section via the sink-interface
      OMS_Globals::m_globalsInstance->GetCurrentLcSink()->EnterCriticalSection(m_pLockId[i]);
    }
  }

  //OMS_TRACE(omsTrInterface, co10_GetLcSink(), "Shared Regions aquired: ");
  //for (j=0; j<m_size; ++j){
  //  OMS_TRACE(omsTrInterface, co10_GetLcSink(), "  " << pLockId[j]);
  //}
}

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

SharedVersionDirRgn::~SharedVersionDirRgn()
{
  for (int i=0; i<m_size; ++i){
    if (m_useRWLocks){
      LVC_LockRequest lock(LVC_LockRequest::RWLOCK_UNLOCK_SHARED, m_pLockId[i]);
      short err = OMS_Globals::GetKernelInterface()->LockRequest(lock);
      if (err != e_ok)
        throw DbpError(DbpError::DB_ERROR, err, "SharedVersionDirRgn::~SharedVersionDirRgn", __MY_FILE__, __LINE__);
    }
    else {
      OMS_Globals::m_globalsInstance->GetCurrentLcSink()->LeaveCriticalSection(m_pLockId[i]);
    }
  }

  //OMS_TRACE(omsTrInterface, co10_GetLcSink(), "Shared Regions freed: ");
  //for (int j=0; j<m_size; ++j){
  //  OMS_TRACE(omsTrInterface, co10_GetLcSink(), "  " << m_pLockId[j]);
  //}
}

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