提交 ddc80157 编写于 作者: 丁劲犇's avatar 丁劲犇 😸

1.Add linear hash alg from C code- an dynamic hash method, can effectively...

1.Add linear hash alg from C code- an dynamic hash method, can effectively hash clients socket and their messages
2.generate several namespaces, avoiding name-conflicts
上级 3b486e3e
......@@ -17,13 +17,19 @@ SOURCES += main.cpp\
network/zp_tcpserver.cpp \
network/zp_nettransthread.cpp \
network/zp_netlistenthread.cpp \
network/zp_net_threadpool.cpp
network/zp_net_threadpool.cpp \
pipeline/zp_pipeline.cpp \
dynhash/dynhash.cpp \
smartlink/st_client_table.cpp
HEADERS += zpmainframe.h \
network/zp_tcpserver.h \
network/zp_nettransthread.h \
network/zp_netlistenthread.h \
network/zp_net_threadpool.h
network/zp_net_threadpool.h \
pipeline/zp_pipeline.h \
dynhash/dynhash.h \
smartlink/st_client_table.h
FORMS += zpmainframe.ui
......
#include <stdlib.h>
#include <stdio.h>
#include "dynhash.h"
namespace ZPHashTable{
///开始键值对、桶的定义和操作
/**------------------------------------------------------------*/
//Paires
typedef struct tag_cdyn_pair
{
struct tag_cdyn_pair * next;
//struct tag_cdyn_pair * prev;//双向链表是占用存储的,没有必要
unsigned int key;
void * value;
} CDNPAIR;
//Buckets
typedef struct tag_cdyn_bucket
{
#ifdef DEBUG
int nItems;//占用内存,耗费时钟,调试用
#endif
CDNPAIR * FirstPair;
} CDNBCT;
CDNBCT * bucket_malloc()
{
CDNBCT * bct = (CDNBCT *)malloc(sizeof (CDNBCT));
if (bct)
{
#ifdef DEBUG
bct->nItems = 0;
#endif
bct->FirstPair = 0;
}
return bct;
}
// insert an item into bucket, a bi-direction link list.
int bucket_set(CDNBCT * bucket, unsigned int key,void * value)
{
int res = 0;
CDNPAIR * pairCur = bucket->FirstPair;
while (pairCur)
{
if (pairCur->key == key)
break;
pairCur = pairCur->next;
}
//Not found
if (!pairCur)
{
CDNPAIR * newPair = (CDNPAIR * )malloc(sizeof(CDNPAIR));
if (newPair)
{
newPair->key = key;
newPair->value = value;
newPair->next = bucket->FirstPair;
//newPair->prev = 0;
//if (bucket->FirstPair)
// bucket->FirstPair->prev = newPair;
bucket->FirstPair = newPair;
#ifdef DEBUG
bucket->nItems++;
#endif
res = -1;
}
}
else
pairCur->value = value;
return res;
}
// get an item
void * bucket_get(CDNBCT * bucket, unsigned int key,int * bfound)
{
CDNPAIR * pairCur = bucket->FirstPair;
while (pairCur)
{
if (pairCur->key == key)
break;
pairCur = pairCur->next;
}
//Not found
if (!pairCur)
{
* bfound = 0;
return 0;
}
else
{
* bfound = -1;
return pairCur->value;
}
}
// find.
int bucket_contains(CDNBCT * bucket, unsigned int key)
{
CDNPAIR * pairCur = bucket->FirstPair;
while (pairCur)
{
if (pairCur->key == key)
break;
pairCur = pairCur->next;
}
//Not found
if (!pairCur)
return 0;
else
return -1;
}
int bucket_remove( CDNBCT * bucket, unsigned int key)
{
int res = 0;
CDNPAIR * pairCur = bucket->FirstPair;
CDNPAIR * pairLast = 0;
while (pairCur)
{
if (pairCur->key == key)
break;
pairLast = pairCur;
pairCur = pairCur->next;
}
//Not found
if (!pairCur)
return res;
res = -1;
/* 双向链表浪费空间
if (pairCur->prev)
{
pairCur->prev->next = pairCur->next;
if (pairCur->next)
pairCur->next->prev = pairCur->prev;
}
if (pairCur->next)
{
pairCur->next->prev = pairCur->prev;
if (pairCur->prev)
pairCur->prev->next = pairCur->next;
}
*/
if (pairLast)
pairLast->next = pairCur->next;
else
bucket->FirstPair = pairCur->next;
//if (bucket->FirstPair == pairCur)
// bucket->FirstPair = bucket->FirstPair->next;
free (pairCur);
#ifdef DEBUG
bucket->nItems--;
#endif
return res;
}
void bucket_free( CDNBCT * bucket)
{
CDNPAIR * pairCur = bucket->FirstPair;
while (pairCur)
{
CDNPAIR * delptr = pairCur;
pairCur = pairCur->next;
free(delptr);
}
free(bucket);
}
///开始哈希表内部定义和操作
/**------------------------------------------------------------*/
//Hash Tables
typedef struct tag_cdyn_hash_table{
unsigned int totalElmts; //current size of the table
unsigned int level; //current hash level
int p; //current split point
float splitFactorMax; //when mean payload larger than this, split will happen
float splitFactorMin; //when mean payload lower than this, merge will happen
//items hold buckets and key-value pairs;
int dirsz;
CDNBCT * * directory;
} INTCDYNHASHTB;
///计算地址
unsigned int address(INTCDYNHASHTB * pTable, unsigned int v)
{
//all those addresses after p are obtained using h % 2 ^ level
//and all those before p are obtained usng h % 2 ^ (level+1)
unsigned int h = v % (2 << ((pTable->level) -1));
if(h < pTable->p){
h = v % (2 << (pTable->level));
}
return h;
}
///查找元素
int findElmt(INTCDYNHASHTB * ptable, unsigned int key, void ** val)
{
int bFound = 0;
CDNBCT * bucket = ptable->directory[address(ptable,key)];
* val = bucket_get(bucket, key, &bFound);
return bFound;
}
///核心算法,分裂表
void split_bucket(INTCDYNHASHTB * ptable)
{
unsigned int cur_loc = ptable->p;
int new_sz = 0, i = 0;
CDNBCT ** newPt = 0;
CDNPAIR * pairCur = 0;
CDNBCT * oldBucketPtr = 0, * newBucketPtr = 0;
ptable->p++;
if(ptable->p >= (ptable->dirsz >> 1)){
ptable->level++;
ptable->p = 0;
new_sz = ptable->dirsz << 1;
//insert new buckets addresses
//ptable->dirsz = nInitBuckets;
//ptable->directory = (CDNBCT ** )malloc(sizeof (CDNBCT *) * nInitBuckets);
newPt = (CDNBCT ** )malloc(sizeof (CDNBCT *) * new_sz);
for (i=0;i<new_sz;i++)
{
if (i<ptable->dirsz)
newPt[i] = ptable->directory[i];
else
newPt[i] = bucket_malloc();
}
free (ptable->directory);
ptable->directory = newPt;
ptable->dirsz = new_sz;
}
oldBucketPtr = ptable->directory[cur_loc];
newBucketPtr = bucket_malloc();
ptable->directory[cur_loc] = newBucketPtr;
//Re-hash
pairCur = oldBucketPtr->FirstPair;
while (pairCur)
{
unsigned int loc = address(ptable,pairCur->key);
if(loc == cur_loc)
bucket_set(newBucketPtr,pairCur->key,pairCur->value);
else
bucket_set(ptable->directory[loc],pairCur->key,pairCur->value);
pairCur = pairCur->next;
}
bucket_free(oldBucketPtr);
}
///核心算法,收缩表
void merge_bucket(INTCDYNHASHTB * ptable)
{
//merge the directories located at p and p+directory.size()/2
int new_sz = 0 , i = 0;
CDNBCT ** newPt = 0;
CDNBCT * innerBucketPtr = 0, * outerBucketPtr = 0;
unsigned int next_loc = 0;
CDNPAIR * pairCur = 0;
ptable->p--;
if(ptable->p < 0){//no bucket has been split in this level
new_sz = ptable->dirsz / 2;
ptable->p = new_sz/2 - 1;
ptable->level--;
newPt = (CDNBCT ** )malloc(sizeof (CDNBCT *) * new_sz);
for (i=0;i<ptable->dirsz;i++)
{
if (i<new_sz)
newPt[i] = ptable->directory[i];
else
bucket_free(ptable->directory[i]);
}
free (ptable->directory);
ptable->directory = newPt;
ptable->dirsz = new_sz;
}
next_loc = ptable->p + ((ptable->dirsz) >> 1);
innerBucketPtr = ptable->directory[ptable->p];
outerBucketPtr = ptable->directory[next_loc];
//Re-hash
pairCur = outerBucketPtr->FirstPair;
while (pairCur)
{
bucket_set(innerBucketPtr,pairCur->key,pairCur->value);
pairCur = pairCur->next;
}
bucket_free(outerBucketPtr);
ptable->directory[next_loc] = bucket_malloc();
}
///开始哈希表外部方法定义和操作
/**------------------------------------------------------------*/
//init a hash table
CDYNHASHTB hash_init(float spFacMax, float spFacMin)
{
int i = 0;
int nInitBuckets = 0;
struct tag_cdyn_hash_table * ptable = (struct tag_cdyn_hash_table *)
malloc(sizeof (struct tag_cdyn_hash_table));
if (ptable)
{
ptable->totalElmts = 0;
ptable->level = 1;
ptable->p = 0;
ptable->splitFactorMax = spFacMax;
ptable->splitFactorMin = spFacMin;
nInitBuckets = (2 << ptable->level);
ptable->dirsz = nInitBuckets;
ptable->directory = (CDNBCT ** )malloc(sizeof (CDNBCT *) * nInitBuckets);
for (i=0;i<nInitBuckets;i++)
ptable->directory[i] = bucket_malloc();
}
return (CDYNHASHTB) ptable;
}
//insert an item [key:value] into table, or change existing value
void hash_set(CDYNHASHTB table, unsigned int key, void * value)
{
int bInserted = 0;
INTCDYNHASHTB * ptable = (INTCDYNHASHTB *)table;
CDNBCT * bucket = ptable->directory[address(ptable,key)];
bInserted = bucket_set(bucket,key,value);
if (bInserted)
{
ptable->totalElmts++;
if((float)(ptable->totalElmts)*2 / ptable->dirsz > ptable->splitFactorMax)
split_bucket(ptable);
}
}
//remove an item [key] from table
void hash_del(CDYNHASHTB table, unsigned int key)
{
int bDeleted = 0;
INTCDYNHASHTB * ptable = (INTCDYNHASHTB *)table;
CDNBCT * bucket = ptable->directory[address(ptable,key)];
bDeleted = bucket_remove(bucket,key);
if (bDeleted)
{
ptable->totalElmts--;
if((float)(ptable->totalElmts)*2 / ptable->dirsz < ptable->splitFactorMin)
merge_bucket(ptable);
}
}
///查找表中的值。送入一个查找结果存储变量bfound,当bfound==0时,表示没找到
void * hash_get(CDYNHASHTB table, unsigned int key, int * bfound)
{
void * elmtPtr;
if(findElmt((INTCDYNHASHTB *)table,key, &elmtPtr)){
*bfound = -1;
return elmtPtr;
}
else {
*bfound = 0;
return 0;
}
}
//test whether table contains key. retrun 0 if key not found, -1 when found
int hash_contains(CDYNHASHTB table, unsigned int key)
{
void* elmtPtr = 0;
return findElmt((INTCDYNHASHTB *)table, key, &elmtPtr);
}
///供调试使用,在stdin里,输出哈希表
void hash_dump(CDYNHASHTB table)
{
int i = 0, n = 0;
CDNPAIR * pairCur = 0;
INTCDYNHASHTB * ptable = (INTCDYNHASHTB *)table;
printf ("\np = %d, level = %d, bucket size = %d, total items = %d"
,ptable->p
,ptable->level
,ptable->dirsz
,ptable->totalElmts
);
for (i=0;i<ptable->dirsz;i++)
{
if (!ptable->directory[i]->FirstPair)
continue;
#ifdef DEBUG
printf ("\nBucket #%d [size:%d]:",i,ptable->directory[i]->nItems);
#else
printf ("\nBucket #%d:",i);
#endif
pairCur = ptable->directory[i]->FirstPair;
n = 0;
while (pairCur)
{
if (n==0)
printf("\n\t");
printf ("(%d:%d) ",pairCur->key,(unsigned int)pairCur->value);
if (++n>=5)
n = 0;
pairCur = pairCur->next;
}
}
printf ("\n");
}
///遍历
typedef struct tag_cdyn_iterator{
INTCDYNHASHTB * ptable;
int nCurrIdx;
CDNPAIR * currItem;
} CDNIT;
///遍历表中的所有元素,开始一次遍历
CDYNHASHIt hash_iterate_begin(CDYNHASHTB table)
{
CDNIT * pIt = (CDNIT *)malloc(sizeof(CDNIT));
if (pIt)
{
pIt->ptable = (INTCDYNHASHTB * )table;
pIt->nCurrIdx = 0;
pIt->currItem = pIt->ptable->directory[0]->FirstPair;
//find first element
while (!pIt->currItem && pIt->nCurrIdx <pIt->ptable->dirsz )
{
pIt->nCurrIdx++;
if (pIt->nCurrIdx<pIt->ptable->dirsz)
pIt->currItem = pIt->ptable->directory[pIt->nCurrIdx]->FirstPair;
}
}
return (CDYNHASHIt) pIt;
}
///重置迭代器
void hash_iterate_reset(CDYNHASHIt iter)
{
CDNIT * pIt = (CDNIT *)iter;
pIt->nCurrIdx = 0;
pIt->currItem = pIt->ptable->directory[0]->FirstPair;
//find first element
while (!pIt->currItem && pIt->nCurrIdx <pIt->ptable->dirsz )
{
pIt->nCurrIdx++;
if (pIt->nCurrIdx<pIt->ptable->dirsz)
pIt->currItem = pIt->ptable->directory[pIt->nCurrIdx]->FirstPair;
}
}
///遍历表中的所有元素,继续遍历,运行后,返回值为非0表示成功取得了一组数据,为0表示到头了。
int hash_iterate_next(CDYNHASHIt iter, unsigned int * pkey, void ** pvalue)
{
int res = 0;
CDNIT * pIt = (CDNIT *)iter;
if (pIt->currItem)
{
*pkey = pIt->currItem->key;
*pvalue = pIt->currItem->value;
res = -1;
//step
pIt->currItem = pIt->currItem->next;
if (!pIt->currItem)
{
pIt->nCurrIdx++;
//find next element
while (pIt->nCurrIdx < pIt->ptable->dirsz)
{
if (pIt->ptable->directory[pIt->nCurrIdx]->FirstPair)
{
pIt->currItem = pIt->ptable->directory[pIt->nCurrIdx]->FirstPair;
break;
}
pIt->nCurrIdx++;
}
}
}
return res;
}
///遍历表中的所有元素,关闭遍历,并释放内存
void hash_iterate_end(CDYNHASHIt iter)
{
CDNIT * pIt = (CDNIT *)iter;
free (pIt);
}
///删除表,清理所有内存
void hash_fini(CDYNHASHTB table)
{
INTCDYNHASHTB * ptable = (INTCDYNHASHTB *)table;
int i = 0;
for (i=0;i<ptable->dirsz;i++)
bucket_free(ptable->directory[i]);
free(ptable->directory);
free (ptable);
}
}
#if !defined (hash_V100_H_INCLUDE)
#define hash_V100_H_INCLUDE
/*!
this structure hold an linear dynamic hash table.
the key type is an unsigned integer, value type is an void *
hash table can hold variant value types , using void *.
*/
namespace ZPHashTable{
typedef void * CDYNHASHTB;
typedef void * CDYNHASHIt;
/*!
新建一个哈希表 spFacMax 是触发分裂的门限(可以取>=2), spFacMin是触发合并的门限可以取>=1。
返回一个句柄,所有的操作均针对这个句柄操作。
*/
CDYNHASHTB hash_init(float spFacMax, float spFacMin);
///插入或者修改一个值,
void hash_set(CDYNHASHTB table, unsigned int key, void * value);
///删除 key
void hash_del(CDYNHASHTB table, unsigned int key);
///查找表中的值。送入一个查找结果存储变量bfound,当bfound==0时,表示没找到
void * hash_get(CDYNHASHTB table, unsigned int key, int * bfound);
///看看表中是否含有键 key, 返回-1表示含有,0表示木有
int hash_contains(CDYNHASHTB table, unsigned int key);
///供调试使用,在stdin里,输出哈希表
void hash_dump(CDYNHASHTB table);
///遍历表中的所有元素,开始一次遍历
CDYNHASHIt hash_iterate_begin(CDYNHASHTB table);
///重置迭代器
void hash_iterate_reset(CDYNHASHIt iter);
///遍历表中的所有元素,继续遍历,运行后,返回值为非0表示成功取得了一组数据,为0表示到头了。
int hash_iterate_next(CDYNHASHIt iter, unsigned int * pkey, void ** pvalue);
///遍历表中的所有元素,关闭遍历,并释放内存
void hash_iterate_end(CDYNHASHIt iter);
///删除表,清理所有内存
void hash_fini(CDYNHASHTB table);
}
#endif
#include "zp_net_threadpool.h"
namespace ZPNetwork{
zp_net_ThreadPool::zp_net_ThreadPool(int nPayLoad,QObject *parent) :
QObject(parent)
{
......@@ -241,3 +241,4 @@ bool zp_net_ThreadPool::CanExit()
//m_mutex_listen.unlock();
return res;
}
}
......@@ -9,6 +9,9 @@
#include <QThread>
#include "zp_netlistenthread.h"
#include "zp_nettransthread.h"
namespace ZPNetwork{
class zp_net_ThreadPool : public QObject
{
Q_OBJECT
......@@ -92,5 +95,5 @@ public slots:
void BroadcastData(QObject * objFromClient,const QByteArray & dtarray);
};
}
#endif // ZP_NET_THREADPOOL_H
#include "zp_netlistenthread.h"
namespace ZPNetwork{
zp_netListenThread::zp_netListenThread(const QString & id, QHostAddress address ,quint16 port,QObject *parent)
:QObject(parent)
,m_tcpServer(0)
......@@ -46,3 +46,4 @@ void zp_netListenThread::stopListen(const QString & id)
}
}
}
}
......@@ -7,6 +7,7 @@
#include <QObject>
#include <QHostAddress>
#include "zp_tcpserver.h"
namespace ZPNetwork{
class zp_netListenThread : public QObject
{
Q_OBJECT
......@@ -17,7 +18,7 @@ protected:
quint16 m_port;
public:
explicit zp_netListenThread(const QString & id, QHostAddress address ,quint16 port,QObject *parent = 0);
signals:
void evt_Message(const QString &);
void evt_ListenClosed(const QString &);
......@@ -27,5 +28,5 @@ public slots:
void startListen(const QString & id);
void stopListen(const QString & id);
};
}
#endif // ZP_NETLISTENTHREAD_H
......@@ -4,6 +4,7 @@
#include <assert.h>
#include <QDebug>
#include <QCoreApplication>
namespace ZPNetwork{
zp_netTransThread::zp_netTransThread(int nPayLoad,QObject *parent) :
QObject(parent)
{
......@@ -239,3 +240,4 @@ bool zp_netTransThread::CanExit()
return false;
return true;
}
}
......@@ -6,6 +6,7 @@
#include <QList>
#include <QAbstractSocket>
#include <QMutex>
namespace ZPNetwork{
class zp_netTransThread : public QObject
{
Q_OBJECT
......@@ -65,5 +66,5 @@ signals:
//一批数据被发送
void evt_Data_transferred(QObject * client,qint64);
};
}
#endif // ZP_NETTRANSTHREAD_H
#include "ZP_TcpServer.h"
#include <assert.h>
namespace ZPNetwork{
ZP_TcpServer::ZP_TcpServer(QObject *parent )
: QTcpServer(parent)
{
......@@ -10,3 +11,4 @@ void ZP_TcpServer::incomingConnection(qintptr socketDescriptor)
{
emit evt_NewClientArrived(socketDescriptor);
}
}
......@@ -2,10 +2,10 @@
#define ZP_TcpServer_H
#include <QTcpServer>
namespace ZPNetwork{
class ZP_TcpServer : public QTcpServer
{
Q_OBJECT
Q_OBJECT
public:
ZP_TcpServer(QObject *parent);
......@@ -14,5 +14,5 @@ protected:
signals:
void evt_NewClientArrived(qintptr socketDescriptor);
};
}
#endif // ZP_TcpServer_H
#include "zp_pipeline.h"
namespace ZPTaskEngine{
zp_pipeline::zp_pipeline(QObject *parent) :
QObject(parent)
{
}
}
#ifndef ZP_PIPELINE_H
#define ZP_PIPELINE_H
#include <QObject>
#include <QVector>
#include <QThread>
namespace ZPTaskEngine{
class zp_pipeline : public QObject
{
Q_OBJECT
public:
explicit zp_pipeline(QObject *parent = 0);
protected:
signals:
public slots:
};
}
#endif // ZP_PIPELINE_H
#include "st_client_table.h"
namespace SmartLink{
st_client_table::st_client_table(QObject *parent) :
QObject(parent)
{
}
}
#ifndef ST_CLIENT_TABLE_H
#define ST_CLIENT_TABLE_H
#include <QObject>
namespace SmartLink{
class st_client_table : public QObject
{
Q_OBJECT
public:
explicit st_client_table(QObject *parent = 0);
signals:
public slots:
};
}
#endif // ST_CLIENT_TABLE_H
#include "zpmainframe.h"
#include "ui_zpmainframe.h"
using namespace ZPNetwork;
ZPMainFrame::ZPMainFrame(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::ZPMainFrame)
......
......@@ -20,7 +20,7 @@ protected:
void timerEvent(QTimerEvent *);
private:
Ui::ZPMainFrame *ui;
zp_net_ThreadPool * m_pool;
ZPNetwork::zp_net_ThreadPool * m_pool;
int m_nTimerId;
public slots:
//These Message is nessery.-------------------------------------
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册