📄 session_buf.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 + -