// DbLock.cpp : _xZkqqHx_iDeDiDjDiDhGiDiKiDiBiDjDiDgFiBfLiDfGiDiHiDjD_xHqqkZx_ _xZkqqHx_iDhEiDeAiDeDiDiL_xHqqkZx_
//

#include "stdafx.h"
#include "DynamicDb.h"
#include "UtilErr.h"			// For FFThrowMiscUnknown.
#include "DbLock.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// FCDbLock

FCDbLock::FCDbLock ()
{
	m_lLockCount = 0;
} // FCDbLock::FCDbLock.

FCDbLock::~FCDbLock ()
{
} // FCDbLock::~FCDbLock.

void FCDbLock::SetTable (const FCTableName& tableName)
{
	m_tableName = tableName;
} // FCDbLock::SetTable.

void FCDbLock::SetTable (	HString hstrTopDirPath,
							DWORD dwTableId0,
							DWORD dwTableId1,
							DWORD dwTableId2,
							DWORD dwTableId3)
{
	DWORDVector vTableIds;
	vTableIds.push_back(dwTableId0);
	do {
		if (dwTableId1 == DWORD(-1)) break;
		vTableIds.push_back(dwTableId1);
		if (dwTableId2 == DWORD(-1)) break;
		vTableIds.push_back(dwTableId2);
		if (dwTableId3 == DWORD(-1)) break;
		vTableIds.push_back(dwTableId3);
	} while (FALSE);
	SetTable(FCTableName(hstrTopDirPath, &vTableIds[0], vTableIds.size()));
} // FCDbLock::SetTable.

void FCDbLock::Clear ()
{
	if (IsLocked())
		FFThrowMiscUnknown();
	m_tableName.Clear();
} // FCDbLock::SetGroup.

/*************************************************************************
 * <_xZkqqHx_iKnGjAjE_xHqqkZx_>	FCDbLock::IsLocked
 *
 * <_xZkqqHx_iLeAjEfM_xHqqkZx_>	
 *
 * <_xZkqqHx_iIpIjAjE_xHqqkZx_>	
 *
 * <_xZkqqHx_jFnEjCgM_xHqqkZx_>	
 *
 * <_xZkqqHx_iPnKiNnH_xHqqkZx_>	
 *
 * <_xZkqqHx_jCiNiInD_xHqqkZx_>	
 *
 * <_xZkqqHx_iJpAjAoA_xHqqkZx_>	
 *
 * <_xZkqqHx_jHjKjHpA_xHqqkZx_>	05.12.28 Fukushiro M. _xZkqqHx_iNoMjAkM_xHqqkZx_
 *************************************************************************/
BOOL FCDbLock::IsLocked () const
{
	return (m_lLockCount != 0);
} // FCDbLock::IsLocked.

long FCDbLock::GetLocalLockCount () const
{
	return m_lLockCount;
} // FCDbLock::GetLocalLockCount.

GUID FCDbLock::GetLockedTableGuid () const
{
	return g_pFileServer->GetLockedTableGuid(m_tableName);
} // FCDbLock::GetLockedTableGuid.

DWORD FCDbLock::GetLockDeleteIdentifier () const
{
	return g_pFileServer->GetLockedDeleteIdentifier(m_tableName);
} // FCDbLock::GetLockDeleteIdentifier.

DWORD FCDbLock::GetLockAppendIdentifier () const
{
	return g_pFileServer->GetLockedAppendIdentifier(m_tableName);
} // FCDbLock::GetLockAppendIdentifier.

FCTableName FCDbLock::GetTableName () const
{
	return m_tableName;
} // FCDbLock::GetTableName.

void FCDbLock::UnlockAll ()
{
	// _xZkqqHx_iDiNiDgCiDeOiCpAiKkOjBfDiCmJiJpAiPjMiClHiCoJiBeC_xHqqkZx_
	while (IsLocked())
		Unlock();
} // FCDbLock::UnlockAll.

void FCDbLock::Set (const FCDbLock& dbLock)
{
	// _xZkqqHx_iCnMiClIiNkBiCmMiDiNiDgCiDeOiCpAiKkOjBfDiCmJiJpAiPjMiClHiCoJiBeC_xHqqkZx_
	UnlockAll();
	// _xZkqqHx_iDgFiBfLiDhFiDiLjGlMiCpAjDkPiClGiCmJiBeC_xHqqkZx_
	SetTable(dbLock.GetTableName());
	// _xZkqqHx_jDkPiClGiDiNiDgCiDeOjAjEiCmJiCmIiCoJiCnMiCmFiDiNiDgCiDeOiCpAiMeKiCoIjFnEiClHiBeC_xHqqkZx_
	while (GetLocalLockCount() != dbLock.GetLocalLockCount())
		TryLock();
} // FCDbLock::Set.

/////////////////////////////////////////////////////////////////////////////
// FCDbReadLock

FCDbReadLock::FCDbReadLock ()
{
} // FCDbReadLock::FCDbReadLock.

FCDbReadLock::FCDbReadLock (const FCTableName& tableName)
			:	BASE_CLASS()
{
	SetTable(tableName);
} // FCDbReadLock::FCDbReadLock.

FCDbReadLock::FCDbReadLock (HString hstrTopDirPath,
							DWORD dwTableId0,
							DWORD dwTableId1,
							DWORD dwTableId2,
							DWORD dwTableId3)
			:	BASE_CLASS()
{
	SetTable(	hstrTopDirPath,
				dwTableId0,
				dwTableId1,
				dwTableId2,
				dwTableId3);
} // FCDbReadLock::FCDbReadLock.

FCDbReadLock::FCDbReadLock (const FCDbReadLock& readLock)
			:	BASE_CLASS()
{
	operator = (readLock);
} // FCDbReadLock::FCDbReadLock.

FCDbReadLock::~FCDbReadLock ()
{
	Unlock();
} // FCDbReadLock::FCDbReadLock.

BOOL FCDbReadLock::TryLock ()
{
	if (IsLocked())
	{
		m_lLockCount++;
	} else
	{
		if (g_pFileServer->TryReadLockTable(m_tableName) != 0)
			m_lLockCount = 1;
	}
	return IsLocked();
} // FCDbReadLock::TryLock.

void FCDbReadLock::Unlock ()
{
	m_lLockCount--;
	if (!IsLocked())
		g_pFileServer->ReadUnlockTable(m_tableName);
} // FCDbReadLock::Unlock.

void FCDbReadLock::operator = (const FCDbReadLock& readLock)
{
	Set(readLock);
//----- 06.01.13 Fukushiro M. _xZkqqHx_iNoNiPjMiOgO_xHqqkZx_ ()-----
//	// _xZkqqHx_iCnMiClIiNkBiCmMiDiNiDgCiDeOiCpAiKkOjBfDiCmJiJpAiPjMiClHiCoJiBeC_xHqqkZx_
//	UnlockAll();
//	// _xZkqqHx_iDgFiBfLiDhFiDiLjGlMiCpAjDkPiClGiCmJiBeC_xHqqkZx_
//	m_tableName = readLock.m_tableName;
//	m_lLockCount = 0;
//	// _xZkqqHx_jDkPiClGiDiNiDgCiDeOjAjEiCmJiCmIiCoJiCnMiCmFiDiNiDgCiDeOiCpAiMeKiCoIjFnEiClHiBeC_xHqqkZx_
//	while (m_lLockCount != readLock.m_lLockCount)
//		TryLock();
//----- 06.01.13 Fukushiro M. _xZkqqHx_iNoNiPjMiPeJ_xHqqkZx_ ()-----
} // FCDbReadLock::operator.

/////////////////////////////////////////////////////////////////////////////
// FCDbWriteLock

FCDbWriteLock::FCDbWriteLock ()
{
} // FCDbWriteLock::FCDbWriteLock.

FCDbWriteLock::FCDbWriteLock (const FCTableName& tableName)
			:	BASE_CLASS()
{
	SetTable(tableName);
} // FCDbWriteLock::FCDbWriteLock.

FCDbWriteLock::FCDbWriteLock (const FCDbWriteLock& writeLock)
			:	BASE_CLASS()
{
	operator = (writeLock);
} // FCDbWriteLock::FCDbWriteLock.

FCDbWriteLock::FCDbWriteLock (	HString hstrTopDirPath,
								DWORD dwTableId0,
								DWORD dwTableId1,
								DWORD dwTableId2,
								DWORD dwTableId3)
			:	BASE_CLASS()
{
	SetTable(	hstrTopDirPath,
				dwTableId0,
				dwTableId1,
				dwTableId2,
				dwTableId3);
} // FCDbWriteLock::FCDbWriteLock.

FCDbWriteLock::~FCDbWriteLock ()
{
	Unlock();
} // FCDbWriteLock::FCDbWriteLock.

BOOL FCDbWriteLock::CreateLock ()
{
	if (g_pFileServer->CreateWriteLock(m_tableName) != 0)
		m_lLockCount = 1;
	return IsLocked();
} // FCDbWriteLock::CreateLock.

BOOL FCDbWriteLock::TryLock ()
{
	if (IsLocked())
	{
		m_lLockCount++;
	} else
	{
		if (g_pFileServer->TryWriteLockTable(m_tableName) != 0)
			m_lLockCount = 1;
	}
	return IsLocked();
} // FCDbWriteLock::TryLock.

void FCDbWriteLock::Unlock ()
{
	m_lLockCount--;
	if (!IsLocked())
		g_pFileServer->WriteUnlockTable(m_tableName);
} // FCDbWriteLock::Unlock.

void FCDbWriteLock::operator = (const FCDbWriteLock& writeLock)
{
//----- 06.01.13 Fukushiro M. _xZkqqHx_jFmPiNfIjBeP_xHqqkZx_ ()-----
//	// _xZkqqHx_iCnMiClIiNkBiCmMiDiNiDgCiDeOiCpAiKkOjBfDiCmJiJpAiPjMiClHiCoJiBeC_xHqqkZx_
//	UnlockAll();
//	// _xZkqqHx_iDgFiBfLiDhFiDiLjGlMiCpAjDkPiClGiCmJiBeC_xHqqkZx_
//	m_tableName = writeLock.m_tableName;
//	m_lLockCount = 0;
//	// _xZkqqHx_jDkPiClGiDiNiDgCiDeOjAjEiCmJiCmIiCoJiCnMiCmFiDiNiDgCiDeOiCpAiMeKiCoIjFnEiClHiBeC_xHqqkZx_
//	while (m_lLockCount != writeLock.m_lLockCount)
//		TryLock();
//----- 06.01.13 Fukushiro M. _xZkqqHx_jFmPiNfIiMoD_xHqqkZx_ ()-----
	Set(writeLock);
//----- 06.01.13 Fukushiro M. _xZkqqHx_jFmPiNfIiPeJ_xHqqkZx_ ()-----
} // FCDbWriteLock::operator.

/////////////////////////////////////////////////////////////////////////////
// FCDbLock_xZkqqHx_iKnGjIeBiKnGjAjEiBeC_xHqqkZx_

/*************************************************************************
 * <_xZkqqHx_iKnGjAjE_xHqqkZx_>	FFTryLock
 *
 * <_xZkqqHx_iLeAjEfM_xHqqkZx_>	
 *
 * <_xZkqqHx_iIpIjAjE_xHqqkZx_>	
 *
 * <_xZkqqHx_jFnEjCgM_xHqqkZx_>	
 *
 * <_xZkqqHx_iPnKiNnH_xHqqkZx_>	
 *
 * <_xZkqqHx_jCiNiInD_xHqqkZx_>	
 *
 * <_xZkqqHx_iJpAjAoA_xHqqkZx_>	
 *
 * <_xZkqqHx_jHjKjHpA_xHqqkZx_>	05.12.19 Fukushiro M. _xZkqqHx_iNoMjAkM_xHqqkZx_
 *************************************************************************/
BOOL FFTryLock (FCDbReadLock& readLock, const FCTableName& tableName)
{
	readLock.SetTable(tableName);
	if (readLock.TryLock())
		return TRUE;
	readLock.Clear();
	return FALSE;
} // FFTryLock.

/*************************************************************************
 * <_xZkqqHx_iKnGjAjE_xHqqkZx_>	FFTryLock
 *
 * <_xZkqqHx_iLeAjEfM_xHqqkZx_>	
 *
 * <_xZkqqHx_iIpIjAjE_xHqqkZx_>	
 *
 * <_xZkqqHx_jFnEjCgM_xHqqkZx_>	
 *
 * <_xZkqqHx_iPnKiNnH_xHqqkZx_>	
 *
 * <_xZkqqHx_jCiNiInD_xHqqkZx_>	
 *
 * <_xZkqqHx_iJpAjAoA_xHqqkZx_>	
 *
 * <_xZkqqHx_jHjKjHpA_xHqqkZx_>	05.12.19 Fukushiro M. _xZkqqHx_iNoMjAkM_xHqqkZx_
 *************************************************************************/
BOOL FFTryLock (FCDbWriteLock& writeLock, const FCTableName& tableName)
{
	writeLock.SetTable(tableName);
	if (writeLock.TryLock())
		return TRUE;
	writeLock.Clear();
	return FALSE;
} // FFTryLock.

/*************************************************************************
 * <_xZkqqHx_iKnGjAjE_xHqqkZx_>	FFTryLock
 *
 * <_xZkqqHx_iLeAjEfM_xHqqkZx_>	
 *
 * <_xZkqqHx_iIpIjAjE_xHqqkZx_>	
 *
 * <_xZkqqHx_jFnEjCgM_xHqqkZx_>	
 *
 * <_xZkqqHx_iPnKiNnH_xHqqkZx_>	
 *
 * <_xZkqqHx_jCiNiInD_xHqqkZx_>	
 *
 * <_xZkqqHx_iJpAjAoA_xHqqkZx_>	
 * <_xZkqqHx_jHjKjHpA_xHqqkZx_>	05.12.19 Fukushiro M. _xZkqqHx_iNoMjAkM_xHqqkZx_
 *************************************************************************/
BOOL FFTryLock (FCDbReadLock& readLock, FCDbWriteLock& writeLock, const FCTableName& tableName)
{
	readLock.SetTable(tableName);
	if (readLock.TryLock())
	{
		writeLock.SetTable(tableName);
		if (writeLock.TryLock())
			return TRUE;
		readLock.Unlock();
	}
	writeLock.Clear();
	readLock.Clear();
	return FALSE;
} // FFTryLock.

/*************************************************************************
 * <_xZkqqHx_iKnGjAjE_xHqqkZx_>	FFCreateLock
 *
 * <_xZkqqHx_iLeAjEfM_xHqqkZx_>	
 *
 * <_xZkqqHx_iIpIjAjE_xHqqkZx_>	
 *
 * <_xZkqqHx_jFnEjCgM_xHqqkZx_>	
 *
 * <_xZkqqHx_iPnKiNnH_xHqqkZx_>	
 *
 * <_xZkqqHx_jCiNiInD_xHqqkZx_>	
 *
 * <_xZkqqHx_iJpAjAoA_xHqqkZx_>	
 *
 * <_xZkqqHx_jHjKjHpA_xHqqkZx_>	05.12.19 Fukushiro M. _xZkqqHx_iNoMjAkM_xHqqkZx_
 *************************************************************************/
BOOL FFCreateLock (FCDbReadLock& readLock, FCDbWriteLock& writeLock, const FCTableName& tableName)
{
	writeLock.SetTable(tableName);
	readLock.SetTable(tableName);
	if (writeLock.CreateLock())
	{
		if (readLock.TryLock())
			return TRUE;
		writeLock.Unlock();
	}
	writeLock.Clear();
	readLock.Clear();
	return FALSE;
} // FFCreateLock.


void FCDbLockBank::Append (const FCDbReadLock& readLock)
{
	m_mpTableToReadLock[readLock.GetTableName()] = readLock;
} // void FCDbLockBank::Append (const FCDbReadLock& readLock);

void FCDbLockBank::Append (const FCDbWriteLock& writeLock)
{
	m_mpTableToWriteLock[writeLock.GetTableName()] = writeLock;
} // void FCDbLockBank::Append (const FCDbWriteLock& writeLock);

void FCDbLockBank::Clear ()
{
	m_mpTableToReadLock.clear();
	m_mpTableToWriteLock.clear();
} // void FCDbLockBank::Clear ();

const FCDbReadLock& FCDbLockBank::GetReadLock (const FCTableName& tableName) const
{
	map<FCTableName, FCDbReadLock>::const_iterator i = m_mpTableToReadLock.find(tableName);
	if (i == m_mpTableToReadLock.end())
		FFThrowMiscUnknown();
	return i->second;
} // const FCDbReadLock& FCDbLockBank::GetReadLock (const FCTableName& tableName) const;

const FCDbWriteLock& FCDbLockBank::GetWriteLock (const FCTableName& tableName) const
{
	map<FCTableName, FCDbWriteLock>::const_iterator i = m_mpTableToWriteLock.find(tableName);
	if (i == m_mpTableToWriteLock.end())
		FFThrowMiscUnknown();
	return i->second;
} // const FCDbWriteLock& FCDbLockBank::GetWriteLock (const FCTableName& tableName) const;

