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

📄 session_buf.cpp

📁 朋友的作品
💻 CPP
字号:

#include "session_buf.h"
#include <stdio.h>

/**
 * 计算hash值
 * @return hash结果
 */
extern int hash(unsigned key);

CSessionBuf::CSessionBuf()
{
	_buf_head = NULL;
	_buf_hash = NULL;
}

CSessionBuf::~CSessionBuf()
{
	_buf_head = NULL;
	_buf_hash = NULL;
}

void CSessionBuf::Create(char* pBuf, size_t iBufSize
		, size_t indexnum,size_t datanum,size_t datasize,unsigned timeout)
throw (runtime_error)
{
	assert(pBuf);
	assert(datanum>1);
	assert(indexnum>1);
	assert(datasize>0);
	unsigned len = CalBufLen(indexnum,datanum, datasize);
	if(iBufSize<len) {
		char sTmp[128];
		sprintf(sTmp,"CSessionBuf::Create: iBufSize(%u)<len(%u)",iBufSize,len);
		throw runtime_error(sTmp);
	}
	_buf_head = (Buf_Head *)pBuf;
	_buf_head->buf_len = len;
	_buf_head->index_num = indexnum;
	_buf_head->data_num = datanum;
	_buf_head->data_size = datasize;
	_buf_head->timeout = timeout;

	_buf_hash = (Buf_Hash *)(pBuf+Head_Length);

	for(unsigned i=0;i<indexnum;i++) {
		_buf_hash[i].offset = -1;
	}

	_list_arr = (Buf_List *)(pBuf+Head_Length+(indexnum*sizeof(Buf_Hash)));
	for(unsigned i=0;i<datanum;i++) {
		_list_arr[i].key = 0;
		_list_arr[i].previous = -1;
		_list_arr[i].next = -1;
		_list_arr[i].access = 0;
	}

	unsigned headlen = Head_Length+indexnum*sizeof(Buf_Hash)+datanum*sizeof(Buf_List);
	_session_data.Create(pBuf+headlen, len-headlen, datanum, datasize);
}

void CSessionBuf::Attach(char * pBuf, size_t iBufSize
	, size_t indexnum,size_t datanum,size_t datasize,unsigned timeout)
throw (runtime_error)
{
	assert(pBuf);
	assert(iBufSize>Head_Length);
	assert(timeout>0);
	assert(indexnum>1);
	assert(datanum>0);
	assert(datasize>0);

	_buf_head = (Buf_Head *)pBuf;
	if(iBufSize!=_buf_head->buf_len) {
		char sTmp[128];
		sprintf(sTmp,"CSessionBuf::Attach: iBufSize(%u)!=len(%u)",iBufSize,_buf_head->buf_len);
		throw runtime_error(sTmp);
	}
	if(_buf_head->index_num != indexnum) {
		char sTmp[128];
		sprintf(sTmp,"CSessionBuf::Attach: index_num(%u)!=index_num(%u)"
			,_buf_head->index_num,indexnum);
		throw runtime_error(sTmp);
	}
	if(_buf_head->data_num != datanum) {
		char sTmp[128];
		sprintf(sTmp,"CSessionBuf::Attach: datanum(%u)!=datanum(%u)"
			,_buf_head->data_num,datanum);
		throw runtime_error(sTmp);
	}
	if(_buf_head->data_size != datasize) {
		char sTmp[128];
		sprintf(sTmp,"CSessionBuf::Attach: datasize(%u)!=datasize(%u)"
			,_buf_head->data_size,datasize);
		throw runtime_error(sTmp);
	}
	_buf_head->timeout = timeout;

	unsigned len = CalBufLen(_buf_head->index_num,_buf_head->data_num, _buf_head->data_size);
	if(len!=iBufSize) {
		char sTmp[128];
		sprintf(sTmp,"CSessionBuf::Attach: iBufSize(%u)!=callen(%u)",iBufSize,len);
		throw runtime_error(sTmp);
	}

	_buf_hash = (Buf_Hash *)(pBuf+Head_Length);
	_list_arr = (Buf_List *)(pBuf+Head_Length+(_buf_head->index_num*sizeof(Buf_Hash)));

	unsigned headlen = Head_Length+_buf_head->index_num*sizeof(Buf_Hash)+_buf_head->data_num*sizeof(Buf_List);
	_session_data.Attach(pBuf+headlen, _buf_head->buf_len-headlen, datanum, datasize);

}

int CSessionBuf::FindNode(int offset,unsigned key)
{
	assert(offset<(int)_buf_head->data_num);

	assert(_list_arr[offset].previous == -1);
	assert(_list_arr[offset].key > 0);
	if(_list_arr[offset].key == key) return offset;

	int offset2;
	for(;;) {
		offset2 = _list_arr[offset].next;
		assert(offset2<(int)_buf_head->data_num);
		if(offset2 == -1) return -1;
		if(_list_arr[offset2].key == key) return offset2;
		offset = offset2;
	}

	return -1;
}

void CSessionBuf::RemoveNode(unsigned hashindx,int offset)
{
	assert(offset<(int)_buf_head->data_num);
	assert(_list_arr[offset].key > 0);
	int offset_pre = _list_arr[offset].previous;
	int offset_next = _list_arr[offset].next;
	if(offset_pre >= 0) { //
		_list_arr[offset_pre].next = _list_arr[offset].next;
	} else {
		assert(_buf_hash[hashindx].offset == offset);
		_buf_hash[hashindx].offset = _list_arr[offset].next;
	}
	if(offset_next >= 0) { //
		_list_arr[offset_next].previous = _list_arr[offset].previous;
	}
	_list_arr[offset].key = 0;
	_list_arr[offset].previous = -1;
	_list_arr[offset].next = -1;
	_list_arr[offset].access = 0;
}

bool CSessionBuf::Get(unsigned key, char * data,size_t datasize,time_t tnow)
{
	assert(datasize<=_buf_head->data_size);
	unsigned idx = hash(key);
	assert(idx<_buf_head->index_num);
	int offset = _buf_hash[idx].offset;
	if(offset < 0) { 
		return false;
	}

	offset = FindNode(offset,key);
	if(offset < 0) {
		return false;
	}
	assert(_session_data.GetData(offset));

	if(tnow - _list_arr[offset].access > (int)_buf_head->timeout) { //超时
		_session_data.FreeData(offset);
		RemoveNode(idx,offset);
		return false;
	}

	memcpy(data,_session_data.GetData(offset),datasize);
	return true;
}

void CSessionBuf::Delete(unsigned key)
{
	unsigned idx = hash(key);
	assert(idx<_buf_head->index_num);
	int offset = _buf_hash[idx].offset;
	if(offset < 0) { 
		return;
	}

	offset = FindNode(offset,key);
	if(offset < 0) {
		return;
	}
	assert(_session_data.GetData(offset));

	_session_data.FreeData(offset);
	RemoveNode(idx,offset);
}

void CSessionBuf::Update(unsigned key, char * data,size_t datasize, time_t tnow)
throw(session_buf_full)
{
	assert(datasize<=_buf_head->data_size);
	unsigned idx = hash(key);
	assert(idx<_buf_head->index_num);
	int offset = _buf_hash[idx].offset;
	if(offset < 0) { 
		Insert(key,data,datasize,tnow);
		return;
	}

	offset = FindNode(offset,key);
	if(offset < 0) {
		Insert(key,data,datasize,tnow);
		return;
	}
	assert(_session_data.GetData(offset));
	_list_arr[offset].access = tnow;
	memcpy(_session_data.GetData(offset),data,datasize);
}

void CSessionBuf::Insert(unsigned key, char * data,size_t datasize, time_t tnow)
throw(session_buf_full)
{
	assert(datasize<=_buf_head->data_size);
	unsigned offset = _session_data.AllocData();
	assert(_list_arr[offset].key == 0);
	assert(_list_arr[offset].previous == -1);
	assert(_list_arr[offset].next == -1);
	assert(_list_arr[offset].access == 0);

	memcpy(_session_data.GetData(offset),data,datasize);

	unsigned idx = hash(key);
	int offset2 = _buf_hash[idx].offset;
	// 检查链上是否有超时的
	for(;;) {
		if(offset2 < 0) break;
		if(tnow - _list_arr[offset2].access > (int)_buf_head->timeout) { //超时
			cout << _list_arr[offset2].key << " session 超时"  << endl;
			_session_data.FreeData(offset2);
			RemoveNode(idx, offset2);
			offset2 = _buf_hash[idx].offset;
		}
		else {
			offset2 = _list_arr[offset2].next;
		}
	}

	offset2 = _buf_hash[idx].offset;
	// 插到链首
	_buf_hash[idx].offset = offset;
	_list_arr[offset].key = key;
	_list_arr[offset].previous = -1;
	_list_arr[offset].next = -1;
	_list_arr[offset].access = tnow;

	if(offset2 > 0) {
		_list_arr[offset].next = offset2;
		_list_arr[offset2].previous = offset;
		return;
	}
}

void CSessionBuf::DumpBuf(const char * pBuf,size_t iBufLen)
{
	if(iBufLen < sizeof(Buf_Head)) {
		cout << "CSessionBuf::DumpBuf: iBufLen is too small " << iBufLen << endl;
		return;
	}
	Buf_Head * pHead = (Buf_Head *)pBuf;
	cout << "CSessionBuf::DumpBuf" << endl;
	cout << "---------Head---------" << endl;	
	cout << "buf_len:" << pHead->buf_len  << "\n"
		<< "index_num:" << pHead->index_num << "\n"
		<< "data_num:" << pHead->data_num << "\n"
		<< "data_size:" << pHead->data_size << "\n"
		<< "timeout:" << pHead->timeout 
		<< endl;

	if(iBufLen < pHead->buf_len) {
		cout << "CSessionBuf::DumpBuf: iBufLen " << iBufLen << "<" << pHead->buf_len << endl;
		return;
	}

	unsigned hash_len = pHead->index_num * sizeof(Buf_Hash);
	cout << "---------Hash---------" << endl;
	cout << "len = " << hash_len << endl;

	unsigned list_len = pHead->data_num * sizeof(Buf_List);
	cout << "---------List---------" << endl;	
	cout << "len = " << list_len << endl;

	if(iBufLen < hash_len+list_len+Head_Length) {
		cout << "CSessionBuf::DumpBuf: iBufLen " << iBufLen << "<" << hash_len+list_len+Head_Length << endl;
		return;
	}

	_session_data.DumpBuf(pBuf+Head_Length+hash_len+list_len
						,iBufLen - Head_Length - hash_len - list_len);
}

⌨️ 快捷键说明

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