⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 myfiledb.cpp

📁 Chapter08-Transactions.rar com example
💻 CPP
字号:
// MyFileDB.cpp : Implementation of CTextFileDBApp and DLL registration.

#include "stdafx.h"
#include "TextFileDB.h"
#include "MyFileDB.h"
#include "MyFileDBCompensator.h"

/////////////////////////////////////////////////////////////////////////////
//

inline bool ISNOTNULL(IUnknown* p)
{
	return (NULL != p);
}

inline bool ISNULL(IUnknown* p)
{
	return (NULL == p);
}

STDMETHODIMP CMyFileDB::InterfaceSupportsErrorInfo(REFIID riid)
{
	static const IID* arr[] = 
	{
		&IID_IMyFileDB,
	};

	for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
	{
		if (::InlineIsEqualGUID(*arr[i],riid))
			return S_OK;
	}
	return S_FALSE;
}

CMyFileDB::CMyFileDB()
{
}

CMyFileDB::~CMyFileDB()
{
}

HRESULT CMyFileDB::InitCRM()
{
	if (ISNOTNULL(m_spCrmLC)) {
		m_spCrmLC = NULL;
	}

	HRESULT hr = ::CoCreateInstance(
		__uuidof(CRMClerk),
		NULL,
		CLSCTX_INPROC_SERVER,
		__uuidof(ICrmLogControl),
		(void**) &m_spCrmLC);

	if (FAILED(hr)) {
		return hr;
	}

	// Register the compensator. Try 5 times if recovery is in progress
	for(int i=0; i<5; i++) {
		hr = m_spCrmLC->RegisterCompensator(
			L"TextFileDB.MyFileDBCompensator",
			L"My file db compensator",
			CRMREGFLAG_ALLPHASES);

		if (SUCCEEDED(hr)) {
			return S_OK;
		}

		// deal with recovery in progress
		if (XACT_E_RECOVERYINPROGRESS == hr) {
			Sleep(1000); // sleep for a second
			continue; // and try again
		}
		break;
	}

	m_spCrmLC = NULL;
	return hr;
}

STDMETHODIMP CMyFileDB::Open(BSTR bsFilePath)
{
	HRESULT hr = InitCRM();
	if (FAILED(hr)) {
		return hr;
	}

	// Open the file
	USES_CONVERSION;
	LPCTSTR pszFile = W2T(bsFilePath);
	CMyFile file;
	hr = file.Open(pszFile, CMyFile::READ);
	if (FAILED(hr)) {
		m_spCrmLC->ForceTransactionToAbort();
		return hr;
	}

	// Log info with CRM that the file is being opened
	DBACTIONOPEN openAction;

	BLOB blobArray[2];
	blobArray[0].pBlobData = (BYTE*) &openAction;
	blobArray[0].cbSize = sizeof(DBACTIONOPEN);
	blobArray[1].pBlobData = (BYTE*) bsFilePath;
	blobArray[1].cbSize = ::SysStringByteLen(bsFilePath) + 
		sizeof(OLECHAR); // account for the end of string
	hr = m_spCrmLC->WriteLogRecord(blobArray, 2);
	if (FAILED(hr)) {
		m_spCrmLC->ForceTransactionToAbort();
		return hr;
	}

	// Now load file into memory
	hr = file.Load(m_AccountDB);
	if (FAILED(hr)) {
		m_spCrmLC->ForceTransactionToAbort();
		return hr;
	}

	return S_OK;
}

STDMETHODIMP CMyFileDB::GetBalance(BSTR bsClient, long *plBalance)
{
	*plBalance = 0;

	if (ISNULL(m_spCrmLC)) {
		return Error(OLESTR("File DB not opened"), GUID_NULL, E_FAIL);
	}

	MYACCOUNTDB::iterator i = m_AccountDB.find(bsClient);

	if (i == m_AccountDB.end()) {
		return Error(OLESTR("Account not found"), GUID_NULL, E_INVALIDARG);
	}

	*plBalance = (*i).second;
	return S_OK;

}

STDMETHODIMP CMyFileDB::UpdateBalance(BSTR bsClient, long lNewBalance)
{
	if (ISNULL(m_spCrmLC)) {
		return Error(OLESTR("File DB not opened"), GUID_NULL, E_FAIL);
	}

	MYACCOUNTDB::iterator i = m_AccountDB.find(bsClient);

	if (i == m_AccountDB.end()) {
		m_spCrmLC->ForceTransactionToAbort();
		return Error(OLESTR("Account not found"), GUID_NULL, E_INVALIDARG);
	}

	// Log info with CRM that the account is being updated
	DBACTIONUPDATE updateAction;
	updateAction.lNewBalance = lNewBalance;

	BLOB blobArray[2];
	blobArray[0].pBlobData = (BYTE*) &updateAction;
	blobArray[0].cbSize = sizeof(DBACTIONUPDATE);
	blobArray[1].pBlobData = (BYTE*) bsClient;
	blobArray[1].cbSize = ::SysStringByteLen(bsClient) + 
		sizeof(OLECHAR); // account for end of string
	HRESULT hr = m_spCrmLC->WriteLogRecord(blobArray, 2);
	if (FAILED(hr)) {
		m_spCrmLC->ForceTransactionToAbort();
		return hr;
	}

	// Update the in-memory account database
	(*i).second = lNewBalance;

	return S_OK;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -