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

📄 blobcache.h

📁 Visual C++.net编成指南一书的源代码
💻 H
字号:

#pragma once

#include <atlrx.h>
#include <string>
#include <fstream>

namespace VCUE
{
	HRESULT GetLineFromFile(const CStringA& strFile, const unsigned int nLine, std::string& strLine)
	{
		HRESULT hr = E_FAIL;
		std::ifstream fsFile;
		fsFile.open(strFile);
		if (fsFile.is_open())
		{
			hr = S_OK;
			for (unsigned int nCurrentLine = 0; nCurrentLine < nLine; ++nCurrentLine)
			{
				if (fsFile.eof() || !fsFile.good())
					return E_FAIL;

				std::getline(fsFile, strLine);
			}
		}

		return hr;
	}

} // namespace VCUE

const int CACHE_SIZE_LIMIT = 5;


[ request_handler("Default") ]
class CBlobCacheHandler
{
public:
	HTTP_CODE ValidateAndExchange()
	{
		HRESULT hr = E_UNEXPECTED;
		//从isapi扩展中获得服务		
		hr = QueryService(&m_spCache);
		if (FAILED(hr))
			return SendError("未能获得内存缓存");

		hr = QueryService(&m_spCacheControl);
		if (FAILED(hr))
			return SendError("未能获得内存缓存控制");

		hr = QueryService(&m_spCacheStats);
		if (FAILED(hr))
			return SendError("未能获得内存缓存统计对象");

		hr = QueryService(&m_spCacheClient);
		if (FAILED(hr))
			return SendError("未能获得内存缓存客户服务");

		hr = m_spCacheControl->SetMaxAllowedEntries( CACHE_SIZE_LIMIT );
		if (FAILED(hr))
			return SendError("未能设置缓存中的最大入口数目");

		hr = m_HttpResponse.SetContentType("text/html");
		const CHttpRequestParams& formFields = m_HttpRequest.GetFormVars();
		//点击了"Clearcache"提交
		if (formFields.Lookup("Clearcache"))
		{
			hr = m_spCacheControl->ResetCache();
			if (SUCCEEDED(hr))
			{
				strStatus = "成功清除了缓存";
				return HTTP_SUCCESS;
			}
			else
				return SendError("清除缓存失败");
		}
		//点"Clear State"提交
		if (formFields.Lookup("Clearstats"))
		{
			hr = m_spCacheStats->ClearStats();
			if (SUCCEEDED(hr))
			{
				strStatus = "成功清除了统计对象";
				return HTTP_SUCCESS;
			}
			else
				return SendError("清除统计失败");
		}
		//获得输入的查询
		CStringA strKey = formFields.Lookup("keystr");				
		strKey.Trim();
		// 获取字符串长度		
		if (0 == strKey.GetLength())
		{
			strStatus = "没有输入键。请输入1到100之间的数字";
			return HTTP_SUCCESS;
		}

		// 正则表达式验证
		CAtlRegExp<CAtlRECharTraitsA> regularExpression;
		if (REPARSE_ERROR_OK != regularExpression.Parse("^[1-9][0-9]?0?$"))
			return SendError("初始化正则表达式失败");

		CAtlREMatchContext<CAtlRECharTraitsA> matchContext;
		if (!regularExpression.Match(strKey, &matchContext))
		{
			strStatus = "无效的键请输入1到100的数值";
			return HTTP_SUCCESS;
		}
		//从缓冲中获得数据
		HCACHEITEM hEntry = 0;
		//获得入口
		hr=m_spCache->LookupEntry(strKey, &hEntry );
		if (SUCCEEDED(hr))
		{
			DWORD dwSize = 0;
			LPSTR szData = 0;
			//获得数据
			hr=m_spCache->GetData(hEntry, reinterpret_cast<void**>(&szData),&dwSize );
			if (SUCCEEDED(hr))
			{
				// 复制数据
				strData = szData;
				strStatus = "从缓冲中取得了数据";
			}
			else
				return SendError("从缓冲中获取数据失败");
		}
		else//从文件加载数据
		{
			strStatus = "没有在缓存中发现数据";
			CStringA strDataFile;
			if (!m_HttpRequest.GetPhysicalPath(strDataFile))
				return SendError("未能获得物理路径");
			strDataFile += "values.txt";

			std::string strValue;
			hr = VCUE::GetLineFromFile(strDataFile, atoi(strKey), strValue);
			if (FAILED(hr))
				return SendError("未能从文件中读取数据");

			strData = strValue.c_str();			
			//分配内存
			DWORD dwSize = strData.GetLength() + 1;
			LPSTR szValue = static_cast<LPSTR>(::HeapAlloc(::GetProcessHeap(), 0, dwSize));
			if (!CopyCString(strData, szValue, &dwSize))
				return SendError("未能拷贝字符串");

			FILETIME ft = {0};
			//加入到缓冲区
			//m_spCacheClient指定删除缓冲区的操作
			hr = m_spCache->Add(strKey, szValue, dwSize, &ft, 0, 0, m_spCacheClient);
			if (FAILED(hr))
				return SendError("未能将值加入到缓冲区");
		}

		m_spCache->Flush();
		return HTTP_SUCCESS;
	}
 
protected:

	[ tag_name(name="limit") ]
	HTTP_CODE OnLimit(void)
	{
		HRESULT hr = E_UNEXPECTED;

		DWORD dwMaximumAllowedEntries = 0;
		hr = m_spCacheControl->GetMaxAllowedEntries(&dwMaximumAllowedEntries);
		if (FAILED(hr))
			return SendError("未能获得最大的入口数");
		
		DWORD dwMaximumAllowedSize = 0;
		hr = m_spCacheControl->GetMaxAllowedSize(&dwMaximumAllowedSize);
		if (FAILED(hr))
			return SendError("未能获得最大大小");

		m_HttpResponse << "<p>缓冲中允许的最大入口数为: " << dwMaximumAllowedEntries << "</p>";
		m_HttpResponse << "<p>缓存允许的最大大小为:" << dwMaximumAllowedSize << "</p>";
	
		return HTTP_SUCCESS;
	}

	[ tag_name(name="output") ]
	HTTP_CODE OnOutput(void)
	{
		m_HttpResponse << "<tr><td><b>值</b></td><td>\"" << strData << "\"</td></tr>";
		m_HttpResponse << "<tr><td><b>状态</b></td><td>" << strStatus << "</td></tr>";
		return HTTP_SUCCESS;
	}

	[ tag_name(name="stats") ]
	HTTP_CODE OnStats(void)
	{
		HRESULT hr = E_UNEXPECTED;

		DWORD dwHits = 0;
		hr = m_spCacheStats->GetHitCount(&dwHits);
		if (FAILED(hr))
			return SendError("未能获得点击数");

		DWORD dwMisses = 0;
		m_spCacheStats->GetMissCount(&dwMisses);
		if (FAILED(hr))
			return SendError("未能获得未命中数");

		DWORD dwMaximumEntries = 0;
		m_spCacheStats->GetMaxEntryCount(&dwMaximumEntries);
		if (FAILED(hr))
			return SendError("未能获得最大入口项数");

		DWORD dwCurrentEntries = 0;
		m_spCacheStats->GetCurrentEntryCount(&dwCurrentEntries);
		if (FAILED(hr))
			return SendError("未能获得当前入口数");

		DWORD dwMaximumSize = 0;
		m_spCacheStats->GetMaxAllocSize(&dwMaximumSize);
		if (FAILED(hr))
			return SendError("未能获得缓存项的最大大小");

		DWORD dwCurrentSize = 0;
		m_spCacheStats->GetCurrentAllocSize(&dwCurrentSize);
		if (FAILED(hr))
			return SendError("未能获得当前缓存项的大小");

		m_HttpResponse << "<tr><td><b>击中</b></td><td>" << dwHits << "</td></tr>";
		m_HttpResponse << "<tr><td><b>丢失</b></td><td>" << dwMisses << "</td></tr>";
		m_HttpResponse << "<tr><td><b>当前入口</b></td><td>" << dwCurrentEntries << "</td></tr>";
		m_HttpResponse << "<tr><td><b>当前大小</b></td><td>" << dwCurrentSize << "</td></tr>";
		m_HttpResponse << "<tr><td><b>最大入口</b></td><td>" << dwMaximumEntries << "</td></tr>";
		m_HttpResponse << "<tr><td><b>最大大小</b></td><td>" << dwMaximumSize << "</td></tr>";

		return HTTP_SUCCESS;
	}

private:
	// 帮助类
	template <class ComInterface>
	HRESULT QueryService(ComInterface** ppInterface)
	{
		return m_spServiceProvider->QueryService(__uuidof(ComInterface), ppInterface);
	}
	
	// 显示错误消息	
	HTTP_CODE SendError(const CStringA& strError, WORD wHttpStatus = 500)
	{
		// 清除缓冲区中响应		
		m_HttpResponse.ClearResponse();
		// 不缓存		
		m_HttpResponse.SetCacheControl("no-cache");
		m_HttpResponse.SetExpires(0);
		// 设置状态代码		
		m_HttpResponse.SetStatusCode(wHttpStatus);
		// 创建响应		
		m_HttpResponse << "<html><head><title>BlobCache 错误</title></head><body><p>" << strError << "</p></body></html>";
		// 返回HTTP_CODE		
		return AtlsHttpError(wHttpStatus, SUBERR_NO_PROCESS);
	}

	// 数据成员
	CComPtr<IMemoryCache> m_spCache;
	CComPtr<IMemoryCacheControl> m_spCacheControl;
	CComPtr<IMemoryCacheStats> m_spCacheStats;
	CComPtr<IMemoryCacheClient> m_spCacheClient;

	CStringA strData;
	CStringA strStatus;
};

⌨️ 快捷键说明

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