From fbbcfbdec7a944c67e24d16341f310ccc04ca64f Mon Sep 17 00:00:00 2001 From: wyy Date: Mon, 15 Sep 2014 17:52:33 +0800 Subject: [PATCH] update limonp and husky for threadpool using --- conf/server.conf | 2 + server/Husky/EpollServer.hpp | 286 -------------------- server/Husky/HttpReqInfo.hpp | 65 +++-- server/Husky/IRequestHandler.hpp | 18 ++ server/Husky/ThreadPoolServer.hpp | 108 ++++++++ server/Husky/WorkerThread.hpp | 134 +++++++++ server/server.cpp | 35 +-- src/Limonp/ArgvContext.hpp | 84 ++++++ src/Limonp/BlockingQueue.hpp | 128 +++++++++ src/Limonp/BoundedQueue.hpp | 73 +++++ src/Limonp/CastFloat.hpp | 90 +++++++ src/Limonp/CodeConverter.hpp | 8 +- src/Limonp/Condition.hpp | 48 ++++ src/Limonp/Config.hpp | 36 ++- src/Limonp/HandyMacro.hpp | 7 +- src/Limonp/InitOnOff.hpp | 10 +- src/Limonp/LocalVector.hpp | 82 +++--- src/Limonp/Md5.hpp | 432 ++++++++++++++++++++++++++++++ src/Limonp/MutexLock.hpp | 57 ++++ src/Limonp/MysqlClient.hpp | 56 ++-- src/Limonp/Thread.hpp | 50 ++++ src/Limonp/ThreadPool.hpp | 105 ++++++++ test/testdata/server.conf | 2 + 23 files changed, 1501 insertions(+), 415 deletions(-) delete mode 100644 server/Husky/EpollServer.hpp create mode 100644 server/Husky/IRequestHandler.hpp create mode 100644 server/Husky/ThreadPoolServer.hpp create mode 100644 server/Husky/WorkerThread.hpp create mode 100644 src/Limonp/ArgvContext.hpp create mode 100644 src/Limonp/BlockingQueue.hpp create mode 100644 src/Limonp/BoundedQueue.hpp create mode 100644 src/Limonp/CastFloat.hpp create mode 100644 src/Limonp/Condition.hpp create mode 100644 src/Limonp/Md5.hpp create mode 100644 src/Limonp/MutexLock.hpp create mode 100644 src/Limonp/Thread.hpp create mode 100644 src/Limonp/ThreadPool.hpp diff --git a/conf/server.conf b/conf/server.conf index 28ded12..70902f2 100644 --- a/conf/server.conf +++ b/conf/server.conf @@ -3,6 +3,8 @@ #socket listen port port=11200 +thread_number=4 +queue_max_size=4096 #dict path dict_path=/usr/share/CppJieba/dict/jieba.dict.utf8 diff --git a/server/Husky/EpollServer.hpp b/server/Husky/EpollServer.hpp deleted file mode 100644 index cf5f625..0000000 --- a/server/Husky/EpollServer.hpp +++ /dev/null @@ -1,286 +0,0 @@ -#ifndef HUSKY_EPOLLSERVER_H -#define HUSKY_EPOLLSERVER_H - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "HttpReqInfo.hpp" - - - -namespace Husky -{ - using namespace Limonp; - - const char* const HTTP_FORMAT = "HTTP/1.1 200 OK\r\nConnection: close\r\nServer: HuskyServer/1.0.0\r\nContent-Type: text/json; charset=%s\r\nContent-Length: %d\r\n\r\n%s"; - const char* const CHARSET_UTF8 = "UTF-8"; - const char* const CLIENT_IP_K = "CLIENT_IP"; - - const struct linger LNG = {1, 1}; - const struct timeval SOCKET_TIMEOUT = {5, 0}; - - class IRequestHandler - { - public: - virtual ~IRequestHandler(){}; - public: - virtual bool do_GET(const HttpReqInfo& httpReq, string& res) const = 0; - virtual bool do_POST(const HttpReqInfo& httpReq, string& res) const = 0; - }; - - class EpollServer: public InitOnOff - { - private: - static const size_t LISTEN_QUEUE_LEN = 1024; - static const size_t RECV_BUFFER_SIZE = 1024*4; - static const int MAXEPOLLSIZE = 512; - - private: - const IRequestHandler & _reqHandler; - int _host_socket; - int _epoll_fd; - int _epollSize; - unordered_map _sockIpMap; - public: - explicit EpollServer(size_t port, const IRequestHandler & handler): _reqHandler(handler), _host_socket(-1), _epollSize(0) - { - _setInitFlag(_init_epoll(port)); - }; - ~EpollServer(){}; - public: - bool start() - { - sockaddr_in clientaddr; - socklen_t nSize = sizeof(clientaddr); - struct epoll_event events[MAXEPOLLSIZE]; - int nfds, clientSock; - - while(true) - { - if(-1 == (nfds = epoll_wait(_epoll_fd, events, _epollSize, -1))) - { - LogFatal(strerror(errno)); - return false; - } - - //LogDebug("epoll_wait return event sum[%d]", nfds); - - for(int i = 0; i < nfds; i++) - { - if(events[i].data.fd == _host_socket) /*new connect coming.*/ - { - if(-1 == (clientSock = accept(_host_socket, (struct sockaddr*) &clientaddr, &nSize))) - { - LogError(strerror(errno)); - continue; - } - if(!_epoll_add(clientSock, EPOLLIN | EPOLLET)) - { - LogError("_epoll_add(%d, EPOLLIN | EPOLLET)", clientSock); - _closesocket(clientSock); - continue; - } - - /* inet_ntoa is not thread safety at some version */ - //_sockIpMap[clientSock] = inet_ntoa(clientaddr.sin_addr); - - } - else /*client socket data to be received*/ - { - _response(events[i].data.fd); - - /*close socket will case it to be removed from epoll automatically*/ - _closesocket(events[i].data.fd); - } - } - - } - return true; - } - private: - bool _epoll_add(int sockfd, uint32_t events) - { - if (!_setNonBLock(sockfd)) - { - LogError(strerror(errno)); - return false; - } - struct epoll_event ev; - ev.data.fd = sockfd; - ev.events = events; - if(epoll_ctl(_epoll_fd, EPOLL_CTL_ADD, sockfd, &ev) < 0) - { - LogError("insert socket '%d' into epoll failed: %s", sockfd, strerror(errno)); - return false; - } - _epollSize ++; - return true; - } - - bool _setsockopt(int sockfd) const - { - if(-1 == setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (const char*)&LNG, sizeof(LNG))) - { - LogError(strerror(errno)); - return false; - } - if(-1 == setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT))) - { - LogError(strerror(errno)); - return false; - } - if(-1 == setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT))) - { - LogError(strerror(errno)); - return false; - } - return true; - } - - bool _receive(int sockfd, string& strRec) const - { - char recvBuf[RECV_BUFFER_SIZE]; - int nRetCode = -1; - while(true) - { - memset(recvBuf, 0, sizeof(recvBuf)); - nRetCode = recv(sockfd, recvBuf, sizeof(recvBuf) - 1, 0); - if(-1 == nRetCode) - { - LogError(strerror(errno)); - return false; - } - if(0 == nRetCode) - { - LogDebug("client socket orderly shut down"); - return true; - } - strRec += recvBuf; - if(nRetCode != sizeof(recvBuf) - 1) - { - break; - } - } - return true; - } - bool _send(int sockfd, const string& strSnd) const - { - if(-1 == send(sockfd, strSnd.c_str(), strSnd.length(), 0)) - { - LogError(strerror(errno)); - return false; - } - return true; - } - - bool _response(int sockfd) const - { - if(!_setsockopt(sockfd)) - { - return false; - } - string strRec, strSnd, strRetByHandler; - if(!_receive(sockfd, strRec)) - { - return false; - } - - HttpReqInfo httpReq(strRec); - if(!httpReq) - { - LogError("HttpReqInfo invalid."); - return false; - } - if("GET" == httpReq.getMethod() && !_reqHandler.do_GET(httpReq, strRetByHandler)) - { - LogError("do_GET failed."); - return false; - } - if("POST" == httpReq.getMethod() && !_reqHandler.do_POST(httpReq, strRetByHandler)) - { - LogError("do_POST failed."); - return false; - } - string_format(strSnd, HTTP_FORMAT, CHARSET_UTF8, strRetByHandler.length(), strRetByHandler.c_str()); - - if(!_send(sockfd, strSnd)) - { - return false; - } - - LogInfo("response:%s", strRetByHandler.c_str()); - return true; - } - bool _init_epoll(size_t port) - { - _host_socket = socket(AF_INET, SOCK_STREAM, 0); - if(-1 == _host_socket) - { - LogError(strerror(errno)); - return false; - } - - int nRet = 1; - if(-1 == setsockopt(_host_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&nRet, sizeof(nRet))) - { - LogError(strerror(errno)); - return false; - } - - struct sockaddr_in addrSock; - addrSock.sin_family = AF_INET; - addrSock.sin_port = htons(port); - addrSock.sin_addr.s_addr = htonl(INADDR_ANY); - if(-1 == ::bind(_host_socket, (sockaddr*)&addrSock, sizeof(sockaddr))) - { - LogError(strerror(errno)); - _closesocket(_host_socket); - return false; - } - if(-1 == listen(_host_socket, LISTEN_QUEUE_LEN)) - { - LogError(strerror(errno)); - return false; - } - - if(-1 == (_epoll_fd = epoll_create(MAXEPOLLSIZE))) - { - LogError(strerror(errno)); - return false; - } - if(!_epoll_add(_host_socket, EPOLLIN)) - { - LogError("_epoll_add(%d, EPOLLIN) failed.", _host_socket); - return false; - } - LogInfo("create socket listening port[%u], epoll{size:%d} init ok", port, MAXEPOLLSIZE); - return true; - } - void _closesocket(int sockfd) - { - if(-1 == close(sockfd)) - { - LogError(strerror(errno)); - return; - } - _epollSize--; - } - static bool _setNonBLock(int sockfd) - { - return -1 != fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK); - } - }; -} -#endif diff --git a/server/Husky/HttpReqInfo.hpp b/server/Husky/HttpReqInfo.hpp index f5a985d..67adaf4 100644 --- a/server/Husky/HttpReqInfo.hpp +++ b/server/Husky/HttpReqInfo.hpp @@ -5,7 +5,6 @@ #include #include "Limonp/Logger.hpp" #include "Limonp/StringUtil.hpp" -#include "Limonp/InitOnOff.hpp" namespace Husky { @@ -71,16 +70,19 @@ namespace Husky } } - class HttpReqInfo: public InitOnOff + class HttpReqInfo { public: - HttpReqInfo(const string& headerStr) + HttpReqInfo() { - _setInitFlag(_init(headerStr)); + _isHeaderFinished = false; + _isBodyFinished = false; + _contentLength = 0; } - private: - bool _init(const string& headerStr) + public: + bool parseHeaders(const char* buffer, size_t len) { + string headerStr(buffer, len); size_t lpos = 0, rpos = 0; vector buf; rpos = headerStr.find("\n", lpos); @@ -134,19 +136,47 @@ namespace Husky _headerMap[k] = v; lpos = rpos + 1; } - //message header end - - //body begin - _body.assign(headerStr.substr(rpos)); - trim(_body); + rpos ++; + _isHeaderFinished = true; + string content_length; + if(!find("CONTENT-LENGTH", content_length)) + { + _isBodyFinished = true; + return true; + } + _contentLength = atoi(content_length.c_str()); + if(rpos < headerStr.size()) + { + appendBody(headerStr.c_str() + rpos, headerStr.size() - rpos); + } return true; + //message header end + } + void appendBody(const char* buffer, size_t len) + { + if(_isBodyFinished) + { + return; + } + _body.append(buffer, len); + if(_body.size() >= _contentLength) + { + _isBodyFinished = true; + } + else + { + _isBodyFinished = false; + } + } + bool isHeaderFinished() const + { + return _isHeaderFinished; + } + bool isBodyFinished() const + { + return _isBodyFinished; } - public: - //string& operator[] (const string& key) - //{ - // return _headerMap[key]; - //} const string& set(const string& key, const string& value) { return _headerMap[key] = value; @@ -176,6 +206,9 @@ namespace Husky return _body; } private: + bool _isHeaderFinished; + bool _isBodyFinished; + size_t _contentLength; unordered_map _headerMap; unordered_map _methodGetMap; string _body; diff --git a/server/Husky/IRequestHandler.hpp b/server/Husky/IRequestHandler.hpp new file mode 100644 index 0000000..d1d857f --- /dev/null +++ b/server/Husky/IRequestHandler.hpp @@ -0,0 +1,18 @@ +#ifndef HUSKY_IREQUESTHANDLER_HPP +#define HUSKY_IREQUESTHANDLER_HPP + +#include "HttpReqInfo.hpp" + +namespace Husky +{ + class IRequestHandler + { + public: + virtual ~IRequestHandler(){}; + public: + virtual bool do_GET(const HttpReqInfo& httpReq, string& res) const = 0; + virtual bool do_POST(const HttpReqInfo& httpReq, string& res) const = 0; + }; +} + +#endif diff --git a/server/Husky/ThreadPoolServer.hpp b/server/Husky/ThreadPoolServer.hpp new file mode 100644 index 0000000..8d21009 --- /dev/null +++ b/server/Husky/ThreadPoolServer.hpp @@ -0,0 +1,108 @@ +#ifndef HUSKY_EPOLLSERVER_H +#define HUSKY_EPOLLSERVER_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "WorkerThread.hpp" + +namespace Husky +{ + using namespace Limonp; + + class ThreadPoolServer + { + private: + static const size_t LISTEN_QUEUE_LEN = 1024; + + private: + ThreadPool _pool; + const IRequestHandler & _reqHandler; + int _host_socket; + public: + ThreadPoolServer(size_t thread_number, size_t queue_max_size, size_t port, const IRequestHandler & handler): + _pool(thread_number, queue_max_size), _reqHandler(handler), _host_socket(-1) + { + _init_host_socket(port); + }; + ~ThreadPoolServer(){}; + public: + bool start() + { + _pool.start(); + sockaddr_in clientaddr; + socklen_t nSize = sizeof(clientaddr); + int clientSock; + + while(true) + { + if(-1 == (clientSock = accept(_host_socket, (struct sockaddr*) &clientaddr, &nSize))) + { + LogError(strerror(errno)); + break; + //continue; + } + _pool.add(CreateTask(clientSock, _reqHandler)); + //_response(clientSock); + //_closesocket(clientSock); + + } + return true; + } + private: + bool _init_host_socket(size_t port) + { + _host_socket = socket(AF_INET, SOCK_STREAM, 0); + if(-1 == _host_socket) + { + LogFatal(strerror(errno)); + return false; + } + + int nRet = 1; + if(-1 == setsockopt(_host_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&nRet, sizeof(nRet))) + { + LogFatal(strerror(errno)); + return false; + } + + struct sockaddr_in addrSock; + addrSock.sin_family = AF_INET; + addrSock.sin_port = htons(port); + addrSock.sin_addr.s_addr = htonl(INADDR_ANY); + if(-1 == ::bind(_host_socket, (sockaddr*)&addrSock, sizeof(sockaddr))) + { + LogFatal(strerror(errno)); + _closesocket(_host_socket); + return false; + } + if(-1 == listen(_host_socket, LISTEN_QUEUE_LEN)) + { + LogFatal(strerror(errno)); + return false; + } + + LogInfo("create socket listening port[%u] init ok", port); + return true; + } + void _closesocket(int sockfd) + { + if(-1 == close(sockfd)) + { + LogError(strerror(errno)); + return; + } + } + }; +} +#endif diff --git a/server/Husky/WorkerThread.hpp b/server/Husky/WorkerThread.hpp new file mode 100644 index 0000000..a355413 --- /dev/null +++ b/server/Husky/WorkerThread.hpp @@ -0,0 +1,134 @@ +#ifndef HUSKY_WORKER_HPP +#define HUSKY_WORKER_HPP + +#include "Limonp/ThreadPool.hpp" +#include "IRequestHandler.hpp" + +namespace Husky +{ + const char* const HTTP_FORMAT = "HTTP/1.1 200 OK\r\nConnection: close\r\nServer: HuskyServer/1.0.0\r\nContent-Type: text/json; charset=%s\r\nContent-Length: %d\r\n\r\n%s"; + const char* const CHARSET_UTF8 = "UTF-8"; + const char* const CLIENT_IP_K = "CLIENT_IP"; + const size_t RECV_BUFFER_SIZE = 16 * 1024; + + const struct linger LNG = {1, 1}; + const struct timeval SOCKET_TIMEOUT = {16, 0}; + + + class WorkerThread: public ITask + { + public: + WorkerThread(int sockfs, const IRequestHandler& reqHandler): + _sockfd(sockfs), _reqHandler(reqHandler) + { + } + virtual ~WorkerThread() + { + } + private: + int _sockfd; + const IRequestHandler& _reqHandler; + + public: + void run() + { + do + { + if(!_setsockopt(_sockfd)) + { + LogFatal("_setsockopt failed."); + break; + } + string strSnd, strRetByHandler; + HttpReqInfo httpReq; + if(!_receive(_sockfd, httpReq)) + { + LogFatal("_receive failed."); + break; + } + + if("GET" == httpReq.getMethod() && !_reqHandler.do_GET(httpReq, strRetByHandler)) + { + LogError("do_GET failed."); + break; + } + if("POST" == httpReq.getMethod() && !_reqHandler.do_POST(httpReq, strRetByHandler)) + { + LogError("do_POST failed."); + break; + } + string_format(strSnd, HTTP_FORMAT, CHARSET_UTF8, strRetByHandler.length(), strRetByHandler.c_str()); + + if(!_send(_sockfd, strSnd)) + { + LogError("_send failed."); + break; + } + LogInfo("response:%s", strRetByHandler.c_str()); + } while(false); + + + if(-1 == close(_sockfd)) + { + LogError(strerror(errno)); + } + } + private: + bool _receive(int sockfd, HttpReqInfo& httpInfo) const + { + char recvBuf[RECV_BUFFER_SIZE]; + int n; + while((n = recv(sockfd, recvBuf, RECV_BUFFER_SIZE, 0)) > 0) + { + if(!httpInfo.isHeaderFinished()) + { + httpInfo.parseHeaders(recvBuf, n); + continue; + } + httpInfo.appendBody(recvBuf, n); + if(!httpInfo.isBodyFinished()) + { + continue; + } + break; + } + if(n < 0) + { + LogError(strerror(errno)); + return false; + } + return true; + } + bool _send(int sockfd, const string& strSnd) const + { + if(-1 == send(sockfd, strSnd.c_str(), strSnd.length(), 0)) + { + LogError(strerror(errno)); + return false; + } + return true; + } + bool _setsockopt(int sockfd) const + { + if(-1 == setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (const char*)&LNG, sizeof(LNG))) + { + LogError(strerror(errno)); + return false; + } + if(-1 == setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT))) + { + LogError(strerror(errno)); + return false; + } + if(-1 == setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT))) + { + LogError(strerror(errno)); + return false; + } + return true; + } + + }; +} + +#endif diff --git a/server/server.cpp b/server/server.cpp index 92945f6..8db24d7 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -4,7 +4,7 @@ #include #include #include "Limonp/Config.hpp" -#include "Husky/EpollServer.hpp" +#include "Husky/ThreadPoolServer.hpp" #include "MPSegment.hpp" #include "HMMSegment.hpp" #include "MixSegment.hpp" @@ -55,37 +55,28 @@ bool run(int argc, char** argv) { return false; } - size_t port = 0; + int port = 0; + int threadNumber = 0; + int queueMaxSize = 0; string dictPath; string modelPath; string userDictPath; - string val; - if(!conf.get("port", val)) - { - LogFatal("conf get port failed."); - return false; - } - port = atoi(val.c_str()); - - if(!conf.get("dict_path", dictPath)) - { - LogFatal("conf get dict_path failed."); - return false; - } - if(!conf.get("model_path", modelPath)) - { - LogFatal("conf get model_path failed."); - return false; - } - + LIMONP_CHECK(conf.get("port", port)); + LIMONP_CHECK(conf.get("thread_number", threadNumber)); + LIMONP_CHECK(conf.get("queue_max_size", queueMaxSize)); + LIMONP_CHECK(conf.get("dict_path", dictPath)); + LIMONP_CHECK(conf.get("model_path", modelPath)); if(!conf.get("user_dict_path", userDictPath)) //optional { userDictPath = ""; } + LogInfo("config info: %s", conf.getConfigInfo().c_str()); + ReqHandler reqHandler(dictPath, modelPath, userDictPath); - EpollServer sf(port, reqHandler); + ThreadPoolServer sf(threadNumber, queueMaxSize, port, reqHandler); return sf.start(); + } int main(int argc, char* argv[]) diff --git a/src/Limonp/ArgvContext.hpp b/src/Limonp/ArgvContext.hpp new file mode 100644 index 0000000..d26675a --- /dev/null +++ b/src/Limonp/ArgvContext.hpp @@ -0,0 +1,84 @@ +/************************************ + * file enc : ascii + * author : wuyanyi09@gmail.com + ************************************/ + +#ifndef LIMONP_ARGV_FUNCTS_H +#define LIMONP_ARGV_FUNCTS_H + +#include +#include +#include "StringUtil.hpp" + +namespace Limonp +{ + using namespace std; + class ArgvContext + { + public : + ArgvContext(int argc, const char* const * argv) + { + + for(int i = 0; i < argc; i++) + { + if(startsWith(argv[i], "-")) + { + if(i + 1 < argc && !startsWith(argv[i + 1], "-")) + { + mpss_[argv[i]] = argv[i+1]; + i++; + } + else + { + sset_.insert(argv[i]); + } + } + else + { + args_.push_back(argv[i]); + } + } + } + ~ArgvContext(){}; + public: + friend ostream& operator << (ostream& os, const ArgvContext& args); + string operator [](size_t i) const + { + if(i < args_.size()) + { + return args_[i]; + } + return ""; + } + string operator [](const string& key) const + { + map::const_iterator it = mpss_.find(key); + if(it != mpss_.end()) + { + return it->second; + } + return ""; + } + public: + bool hasKey(const string& key) const + { + if(mpss_.find(key) != mpss_.end() || sset_.find(key) != sset_.end()) + { + return true; + } + return false; + } + private: + vector args_; + map mpss_; + set sset_; + + }; + + inline ostream& operator << (ostream& os, const ArgvContext& args) + { + return os< +#include "BoundedQueue.hpp" +#include "Condition.hpp" + +namespace Limonp +{ + template + class BlockingQueue: NonCopyable + { + public: + BlockingQueue() + : mutex_(), notEmpty_(mutex_), queue_() + { + } + + void push(const T& x) + { + MutexLockGuard lock(mutex_); + queue_.push(x); + notEmpty_.notify(); // wait morphing saves us + } + + T pop() + { + MutexLockGuard lock(mutex_); + // always use a while-loop, due to spurious wakeup + while (queue_.empty()) + { + notEmpty_.wait(); + } + assert(!queue_.empty()); + T front(queue_.front()); + queue_.pop(); + return front; + } + + size_t size() const + { + MutexLockGuard lock(mutex_); + return queue_.size(); + } + bool empty() const + { + return size() == 0; + } + + private: + mutable MutexLock mutex_; + Condition notEmpty_; + std::queue queue_; + }; + + template + class BoundedBlockingQueue : NonCopyable + { + public: + explicit BoundedBlockingQueue(size_t maxSize) + : mutex_(), + notEmpty_(mutex_), + notFull_(mutex_), + queue_(maxSize) + {} + + void push(const T& x) + { + MutexLockGuard lock(mutex_); + while (queue_.full()) + { + notFull_.wait(); + } + assert(!queue_.full()); + queue_.push(x); + notEmpty_.notify(); + } + + T pop() + { + MutexLockGuard lock(mutex_); + while (queue_.empty()) + { + notEmpty_.wait(); + } + assert(!queue_.empty()); + T res = queue_.pop(); + notFull_.notify(); + return res; + } + + bool empty() const + { + MutexLockGuard lock(mutex_); + return queue_.empty(); + } + + bool full() const + { + MutexLockGuard lock(mutex_); + return queue_.full(); + } + + size_t size() const + { + MutexLockGuard lock(mutex_); + return queue_.size(); + } + + size_t capacity() const + { + return queue_.capacity(); + } + + private: + mutable MutexLock mutex_; + Condition notEmpty_; + Condition notFull_; + BoundedQueue queue_; + }; + +} + +#endif diff --git a/src/Limonp/BoundedQueue.hpp b/src/Limonp/BoundedQueue.hpp new file mode 100644 index 0000000..d438428 --- /dev/null +++ b/src/Limonp/BoundedQueue.hpp @@ -0,0 +1,73 @@ +#ifndef LIMONP_BOUNDED_QUEUE_HPP +#define LIMONP_BOUNDED_QUEUE_HPP + +#include +#include +#include + +namespace Limonp +{ + using namespace std; + template + class BoundedQueue + { + private: + size_t head_; + size_t tail_; + size_t size_; + const size_t capacity_; + vector circular__buffer; + public: + explicit BoundedQueue(size_t capacity): capacity_(capacity), circular__buffer(capacity) + { + head_ = 0; + tail_ = 0; + size_ = 0; + assert(capacity_); + } + ~BoundedQueue(){} + public: + void clear() + { + head_ = 0; + tail_ = 0; + size_ = 0; + } + bool empty() const + { + return !size_; + } + bool full() const + { + return capacity_ == size_; + } + size_t size() const + { + return size_; + } + size_t capacity() const + { + return capacity_; + } + + void push(const T& t) + { + assert(!full()); + circular__buffer[tail_] = t; + tail_ = (tail_ + 1) % capacity_; + size_ ++; + } + + T pop() + { + assert(!empty()); + size_t oldPos = head_; + head_ = (head_ + 1) % capacity_; + size_ --; + return circular__buffer[oldPos]; + } + + }; +} + +#endif diff --git a/src/Limonp/CastFloat.hpp b/src/Limonp/CastFloat.hpp new file mode 100644 index 0000000..ebd8b64 --- /dev/null +++ b/src/Limonp/CastFloat.hpp @@ -0,0 +1,90 @@ +#ifndef LIMONP_CAST_FUNCTS_H +#define LIMONP_CAST_FUNCTS_H + +namespace Limonp +{ + namespace CastFloat + { + //logical and or + static const int sign_32 = 0xC0000000; + static const int exponent_32 = 0x07800000; + static const int mantissa_32 = 0x007FE000; + static const int sign_exponent_32 = 0x40000000; + static const int loss_32 = 0x38000000; + + static const short sign_16 = (short)0xC000; + static const short exponent_16 = (short)0x3C00; + static const short mantissa_16 = (short)0x03FF; + static const short sign_exponent_16 = (short)0x4000; + static const int exponent_fill_32 = 0x38000000; + + //infinite + static const short infinite_16 = (short) 0x7FFF; + static const short infinitesmall_16 = (short) 0x0000; + + inline float intBitsToFloat(unsigned int x) + { + union + { + float f; + int i; + }u; + u.i = x; + return u.f; + } + + inline int floatToIntBits(float f) + { + union + { + float f; + int i ; + }u; + u.f = f; + return u.i; + } + + inline short floatToShortBits(float f) + { + int fi = floatToIntBits(f); + + // 提取关键信息 + short sign = (short) ((unsigned int)(fi & sign_32) >> 16); + short exponent = (short) ((unsigned int)(fi & exponent_32) >> 13); + short mantissa = (short) ((unsigned int)(fi & mantissa_32) >> 13); + // 生成编码结果 + short code = (short) (sign | exponent | mantissa); + // 无穷大量、无穷小量的处理 + if ((fi & loss_32) > 0 && (fi & sign_exponent_32) > 0) { + // 当指数符号为1时(正次方),且左234位为1,返回无穷大量 + return (short) (code | infinite_16); + } + if (((fi & loss_32) ^ loss_32) > 0 && (fi & sign_exponent_32) == 0) { + // 当指数符号位0时(负次方),且左234位为0(与111异或>0),返回无穷小量 + return infinitesmall_16; + } + + return code; + } + + inline float shortBitsToFloat(short s) + { + /* + * 指数空余3位:若符号位为1,补0;若符号位为0,补1。 尾数位在后补0(13个) + */ + int sign = ((int) (s & sign_16)) << 16; + int exponent = ((int) (s & exponent_16)) << 13; + // 指数符号位为0,234位补1 + if ((s & sign_exponent_16) == 0 && s != 0) { + exponent |= exponent_fill_32; + } + int mantissa = ((int) (s & mantissa_16)) << 13; + // 生成解码结果 + int code = sign | exponent | mantissa; + return intBitsToFloat(code); + + } + } +} + +#endif diff --git a/src/Limonp/CodeConverter.hpp b/src/Limonp/CodeConverter.hpp index 8831752..4075ead 100644 --- a/src/Limonp/CodeConverter.hpp +++ b/src/Limonp/CodeConverter.hpp @@ -13,12 +13,12 @@ namespace Limonp public: CodeConverter(const char *from_charset,const char *to_charset) { - _iconv_handle = iconv_open(to_charset,from_charset); + iconv__handle = iconv_open(to_charset,from_charset); } ~CodeConverter() { - iconv_close(_iconv_handle); + iconv_close(iconv__handle); } bool convert(const string& from, string& to) const @@ -28,7 +28,7 @@ namespace Limonp to.resize(from_size * 2); // iconv failed, may be you can raise this 2 to bigger number. char * pto = (char*)to.c_str(); size_t to_size = to.size(); - if(size_t(-1) == iconv(_iconv_handle, &pfrom, &from_size, &pto, &to_size)) + if(size_t(-1) == iconv(iconv__handle, &pfrom, &from_size, &pto, &to_size)) { to.clear(); return false; @@ -37,7 +37,7 @@ namespace Limonp return true; } private: - iconv_t _iconv_handle; + iconv_t iconv__handle; }; inline bool code_convert(const char* from_charset, const char* to_charset, const string& from, string& to) diff --git a/src/Limonp/Condition.hpp b/src/Limonp/Condition.hpp new file mode 100644 index 0000000..13c14ed --- /dev/null +++ b/src/Limonp/Condition.hpp @@ -0,0 +1,48 @@ +/* + * https://github.com/chenshuo/muduo/blob/master/muduo/base/Condition.h + */ + +#ifndef LIMONP_CONDITION_HPP +#define LIMONP_CONDITION_HPP + +#include "MutexLock.hpp" + +namespace Limonp +{ + class Condition : NonCopyable + { + public: + explicit Condition(MutexLock& mutex) + : mutex_(mutex) + { + LIMONP_CHECK(!pthread_cond_init(&pcond_, NULL)); + } + + ~Condition() + { + LIMONP_CHECK(!pthread_cond_destroy(&pcond_)); + } + + void wait() + { + LIMONP_CHECK(!pthread_cond_wait(&pcond_, mutex_.getPthreadMutex())); + } + + void notify() + { + LIMONP_CHECK(!pthread_cond_signal(&pcond_)); + } + + void notifyAll() + { + LIMONP_CHECK(!pthread_cond_broadcast(&pcond_)); + } + + private: + MutexLock& mutex_; + pthread_cond_t pcond_; + }; + +} + +#endif diff --git a/src/Limonp/Config.hpp b/src/Limonp/Config.hpp index 31c4dd0..cce94c1 100644 --- a/src/Limonp/Config.hpp +++ b/src/Limonp/Config.hpp @@ -20,15 +20,15 @@ namespace Limonp public: explicit Config(const string& filePath) { - _loadFile(filePath); + loadFile_(filePath); } public: operator bool () { - return !_map.empty(); + return !map_.empty(); } private: - void _loadFile(const string& filePath) + void loadFile_(const string& filePath) { ifstream ifs(filePath.c_str()); assert(ifs); @@ -54,7 +54,7 @@ namespace Limonp string& value = vecBuf[1]; trim(key); trim(value); - if(!_map.insert(make_pair(key, value)).second) + if(!map_.insert(make_pair(key, value)).second) { fprintf(stderr, "key[%s] already exits.\n", key.c_str()); assert(false); @@ -66,36 +66,52 @@ namespace Limonp public: bool get(const string& key, string& value) const { - map::const_iterator it = _map.find(key); - if(_map.end() != it) + map::const_iterator it = map_.find(key); + if(map_.end() != it) { value = it->second; return true; } return false; } + bool get(const string& key, int & value) const + { + string str; + if(!get(key, str)) { + return false; + } + value = atoi(str.c_str()); + return true; + } const char* operator [] (const char* key) const { if(NULL == key) { return NULL; } - map::const_iterator it = _map.find(key); - if(_map.end() != it) + map::const_iterator it = map_.find(key); + if(map_.end() != it) { return it->second.c_str(); } return NULL; } + public: + string getConfigInfo() const + { + string res; + res << *this; + return res; + } private: - map _map; + map map_; private: friend ostream& operator << (ostream& os, const Config& config); }; inline ostream& operator << (ostream& os, const Config& config) { - return os << config._map; + return os << config.map_; } } diff --git a/src/Limonp/HandyMacro.hpp b/src/Limonp/HandyMacro.hpp index 1468690..0f9102c 100644 --- a/src/Limonp/HandyMacro.hpp +++ b/src/Limonp/HandyMacro.hpp @@ -1,7 +1,8 @@ -#ifndef LIMONP_MACRO_DEF_H -#define LIMONP_MACRO_DEF_H +#ifndef LIMONP_HANDY_MACRO_HPP +#define LIMONP_HANDY_MACRO_HPP -#include +#include +#include #define LIMONP_CHECK(exp) \ if(!(exp)){fprintf(stderr, "File:%s, Line:%d Exp:[" #exp "] is true, abort.\n", __FILE__, __LINE__); abort();} diff --git a/src/Limonp/InitOnOff.hpp b/src/Limonp/InitOnOff.hpp index 563ef6a..b74f0ff 100644 --- a/src/Limonp/InitOnOff.hpp +++ b/src/Limonp/InitOnOff.hpp @@ -6,14 +6,14 @@ namespace Limonp class InitOnOff { public: - InitOnOff(){_setInitFlag(false);}; + InitOnOff():isInited_(false){}; ~InitOnOff(){}; protected: - bool _isInited; - bool _getInitFlag()const{return _isInited;}; - bool _setInitFlag(bool flag){return _isInited = flag;}; + bool isInited_; + bool getInitFlag_()const{return isInited_;}; + bool setInitFlag_(bool flag){return isInited_ = flag;}; public: - operator bool() const {return _getInitFlag();}; + operator bool() const {return getInitFlag_();}; }; } diff --git a/src/Limonp/LocalVector.hpp b/src/Limonp/LocalVector.hpp index a293d7f..ce1a741 100644 --- a/src/Limonp/LocalVector.hpp +++ b/src/Limonp/LocalVector.hpp @@ -22,23 +22,23 @@ namespace Limonp typedef T value_type; typedef size_t size_type; private: - T _buffer[LOCAL_VECTOR_BUFFER_SIZE]; - T * _ptr; - size_t _size; - size_t _capacity; + T buffer_[LOCAL_VECTOR_BUFFER_SIZE]; + T * ptr_; + size_t size_; + size_t capacity_; public: LocalVector() { - _init(); + init_(); }; LocalVector(const LocalVector& vec) { - _init(); + init_(); *this = vec; } LocalVector(const_iterator begin, const_iterator end) // TODO: make it faster { - _init(); + init_(); while(begin != end) { push_back(*begin++); @@ -46,7 +46,7 @@ namespace Limonp } LocalVector(size_t size, const T& t) // TODO: make it faster { - _init(); + init_(); while(size--) { push_back(t); @@ -54,68 +54,68 @@ namespace Limonp } ~LocalVector() { - if(_ptr != _buffer) + if(ptr_ != buffer_) { - free(_ptr); + free(ptr_); } }; public: LocalVector& operator = (const LocalVector& vec) { clear(); - _size = vec.size(); - _capacity = vec.capacity(); - if(vec._buffer == vec._ptr) + size_ = vec.size(); + capacity_ = vec.capacity(); + if(vec.buffer_ == vec.ptr_) { - memcpy(_buffer, vec._buffer, sizeof(T) * _size); - _ptr = _buffer; + memcpy(buffer_, vec.buffer_, sizeof(T) * size_); + ptr_ = buffer_; } else { - _ptr = (T*) malloc(vec.capacity() * sizeof(T)); - assert(_ptr); - memcpy(_ptr, vec._ptr, vec.size() * sizeof(T)); + ptr_ = (T*) malloc(vec.capacity() * sizeof(T)); + assert(ptr_); + memcpy(ptr_, vec.ptr_, vec.size() * sizeof(T)); } return *this; } private: - void _init() + void init_() { - _ptr = _buffer; - _size = 0; - _capacity = LOCAL_VECTOR_BUFFER_SIZE; + ptr_ = buffer_; + size_ = 0; + capacity_ = LOCAL_VECTOR_BUFFER_SIZE; } public: T& operator [] (size_t i) { - return _ptr[i]; + return ptr_[i]; } const T& operator [] (size_t i) const { - return _ptr[i]; + return ptr_[i]; } void push_back(const T& t) { - if(_size == _capacity) + if(size_ == capacity_) { - assert(_capacity); - reserve(_capacity * 2); + assert(capacity_); + reserve(capacity_ * 2); } - _ptr[_size ++ ] = t; + ptr_[size_ ++ ] = t; } void reserve(size_t size) { - if(size <= _capacity) + if(size <= capacity_) { return; } T * next = (T*)malloc(sizeof(T) * size); assert(next); - T * old = _ptr; - _ptr = next; - memcpy(_ptr, old, sizeof(T) * _capacity); - _capacity = size; - if(old != _buffer) + T * old = ptr_; + ptr_ = next; + memcpy(ptr_, old, sizeof(T) * capacity_); + capacity_ = size; + if(old != buffer_) { free(old); } @@ -126,27 +126,27 @@ namespace Limonp } size_t size() const { - return _size; + return size_; } size_t capacity() const { - return _capacity; + return capacity_; } const_iterator begin() const { - return _ptr; + return ptr_; } const_iterator end() const { - return _ptr + _size; + return ptr_ + size_; } void clear() { - if(_ptr != _buffer) + if(ptr_ != buffer_) { - free(_ptr); + free(ptr_); } - _init(); + init_(); } }; diff --git a/src/Limonp/Md5.hpp b/src/Limonp/Md5.hpp new file mode 100644 index 0000000..98bda92 --- /dev/null +++ b/src/Limonp/Md5.hpp @@ -0,0 +1,432 @@ +#ifndef __MD5_H__ +#define __MD5_H__ + +// Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +// rights reserved. + +// License to copy and use this software is granted provided that it +// is identified as the "RSA Data Security, Inc. MD5 Message-Digest +// Algorithm" in all material mentioning or referencing this software +// or this function. +// +// License is also granted to make and use derivative works provided +// that such works are identified as "derived from the RSA Data +// Security, Inc. MD5 Message-Digest Algorithm" in all material +// mentioning or referencing the derived work. +// +// RSA Data Security, Inc. makes no representations concerning either +// the merchantability of this software or the suitability of this +// software for any particular purpose. It is provided "as is" +// without express or implied warranty of any kind. +// +// These notices must be retained in any copies of any part of this +// documentation and/or software. + + + +// The original md5 implementation avoids external libraries. +// This version has dependency on stdio.h for file input and +// string.h for memcpy. +#include +#include +#include + +namespace Limonp +{ + +//#pragma region MD5 defines +// Constants for MD5Transform routine. +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + + +// F, G, H and I are basic MD5 functions. +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +// ROTATE_LEFT rotates x left n bits. +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +// Rotation is separate from addition to prevent recomputation. +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +//#pragma endregion + + +typedef unsigned char BYTE ; + +// POINTER defines a generic pointer type +typedef unsigned char *POINTER; + +// UINT2 defines a two byte word +typedef unsigned short int UINT2; + +// UINT4 defines a four byte word +typedef unsigned int UINT4; + +static unsigned char PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +// convenient object that wraps +// the C-functions for use in C++ only +class MD5 +{ +private: + struct __context_t { + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ + } context ; + + //#pragma region static helper functions + // The core of the MD5 algorithm is here. + // MD5 basic transformation. Transforms state based on block. + static void MD5Transform( UINT4 state[4], unsigned char block[64] ) + { + UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode (x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + // Zeroize sensitive information. + memset((POINTER)x, 0, sizeof (x)); + } + + // Encodes input (UINT4) into output (unsigned char). Assumes len is + // a multiple of 4. + static void Encode( unsigned char *output, UINT4 *input, unsigned int len ) + { + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } + } + + // Decodes input (unsigned char) into output (UINT4). Assumes len is + // a multiple of 4. + static void Decode( UINT4 *output, unsigned char *input, unsigned int len ) + { + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | + (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); + } + //#pragma endregion + + +public: + // MAIN FUNCTIONS + MD5() + { + Init() ; + } + + // MD5 initialization. Begins an MD5 operation, writing a new context. + void Init() + { + context.count[0] = context.count[1] = 0; + + // Load magic initialization constants. + context.state[0] = 0x67452301; + context.state[1] = 0xefcdab89; + context.state[2] = 0x98badcfe; + context.state[3] = 0x10325476; + } + + // MD5 block update operation. Continues an MD5 message-digest + // operation, processing another message block, and updating the + // context. + void Update( + unsigned char *input, // input block + unsigned int inputLen ) // length of input block + { + unsigned int i, index, partLen; + + // Compute number of bytes mod 64 + index = (unsigned int)((context.count[0] >> 3) & 0x3F); + + // Update number of bits + if ((context.count[0] += ((UINT4)inputLen << 3)) + < ((UINT4)inputLen << 3)) + context.count[1]++; + context.count[1] += ((UINT4)inputLen >> 29); + + partLen = 64 - index; + + // Transform as many times as possible. + if (inputLen >= partLen) { + memcpy((POINTER)&context.buffer[index], (POINTER)input, partLen); + MD5Transform (context.state, context.buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform (context.state, &input[i]); + + index = 0; + } + else + i = 0; + + /* Buffer remaining input */ + memcpy((POINTER)&context.buffer[index], (POINTER)&input[i], inputLen-i); + } + + // MD5 finalization. Ends an MD5 message-digest operation, writing the + // the message digest and zeroizing the context. + // Writes to digestRaw + void Final() + { + unsigned char bits[8]; + unsigned int index, padLen; + + // Save number of bits + Encode( bits, context.count, 8 ); + + // Pad out to 56 mod 64. + index = (unsigned int)((context.count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + Update( PADDING, padLen ); + + // Append length (before padding) + Update( bits, 8 ); + + // Store state in digest + Encode( digestRaw, context.state, 16); + + // Zeroize sensitive information. + memset((POINTER)&context, 0, sizeof (context)); + + writeToString() ; + } + + /// Buffer must be 32+1 (nul) = 33 chars long at least + void writeToString() + { + int pos ; + + for( pos = 0 ; pos < 16 ; pos++ ) + sprintf( digestChars+(pos*2), "%02x", digestRaw[pos] ) ; + } + + +public: + // an MD5 digest is a 16-byte number (32 hex digits) + BYTE digestRaw[ 16 ] ; + + // This version of the digest is actually + // a "printf'd" version of the digest. + char digestChars[ 33 ] ; + + /// Load a file from disk and digest it + // Digests a file and returns the result. + const char* digestFile( const char *filename ) + { + if (NULL == filename || strcmp(filename, "") == 0) + return NULL; + + Init() ; + + FILE *file; + + unsigned char buffer[1024] ; + + if((file = fopen (filename, "rb")) == NULL) + { + return NULL; + } + int len; + while( (len = fread( buffer, 1, 1024, file )) ) + Update( buffer, len ) ; + Final(); + + fclose( file ); + + return digestChars ; + } + + /// Digests a byte-array already in memory + const char* digestMemory( BYTE *memchunk, int len ) + { + if (NULL == memchunk) + return NULL; + + Init() ; + Update( memchunk, len ) ; + Final() ; + + return digestChars ; + } + + // Digests a string and prints the result. + const char* digestString(const char *string ) + { + if (string == NULL) + return NULL; + + Init() ; + Update( (unsigned char*)string, strlen(string) ) ; + Final() ; + + return digestChars ; + } +}; + +inline bool md5String(const char* str, std::string& res) +{ + if (NULL == str) + { + res = ""; + return false; + } + + MD5 md5; + const char *pRes = md5.digestString(str); + if (NULL == pRes) + { + res = ""; + return false; + } + + res = pRes; + return true; +} + +inline bool md5File(const char* filepath, std::string& res) +{ + if (NULL == filepath || strcmp(filepath, "") == 0) + { + res = ""; + return false; + } + + MD5 md5; + const char *pRes = md5.digestFile(filepath); + + if (NULL == pRes) + { + res = ""; + return false; + } + + res = pRes; + return true; +} +} +#endif diff --git a/src/Limonp/MutexLock.hpp b/src/Limonp/MutexLock.hpp new file mode 100644 index 0000000..d0d546c --- /dev/null +++ b/src/Limonp/MutexLock.hpp @@ -0,0 +1,57 @@ +#ifndef LIMONP_MUTEX_LOCK_HPP +#define LIMONP_MUTEX_LOCK_HPP + +#include +#include "NonCopyable.hpp" +#include "HandyMacro.hpp" + +namespace Limonp +{ + class MutexLock: NonCopyable + { + private: + pthread_mutex_t mutex_; + public: + pthread_mutex_t* getPthreadMutex() + { + return &mutex_; + } + public: + MutexLock() + { + LIMONP_CHECK(!pthread_mutex_init(&mutex_, NULL)); + } + ~MutexLock() + { + LIMONP_CHECK(!pthread_mutex_destroy(&mutex_)); + } + private: + void lock() + { + LIMONP_CHECK(!pthread_mutex_lock(&mutex_)); + } + void unlock() + { + LIMONP_CHECK(!pthread_mutex_unlock(&mutex_)); + } + friend class MutexLockGuard; + }; + class MutexLockGuard: NonCopyable + { + public: + explicit MutexLockGuard(MutexLock & mutex) + : mutex_(mutex) + { + mutex_.lock(); + } + ~MutexLockGuard() + { + mutex_.unlock(); + } + private: + MutexLock & mutex_; + }; +#define MutexLockGuard(x) assert(false); +} + +#endif diff --git a/src/Limonp/MysqlClient.hpp b/src/Limonp/MysqlClient.hpp index 0512a89..570ac37 100644 --- a/src/Limonp/MysqlClient.hpp +++ b/src/Limonp/MysqlClient.hpp @@ -5,7 +5,7 @@ #include #include #include -#include "logger.hpp" +#include "Logger.hpp" #include "InitOnOff.hpp" namespace Limonp @@ -16,62 +16,62 @@ namespace Limonp public: typedef vector< vector > RowsType; private: - const string _host; - const size_t _port; - const string _user; - const string _passwd; - const string _db; - const string _charset; + const string host_; + const size_t port_; + const string user_; + const string passwd_; + const string db_; + const string charset_; public: - MysqlClient(const string& host, size_t port, const string& user, const string& passwd, const string& db, const string& charset = "utf8"): _host(host), _port(port), _user(user), _passwd(passwd), _db(db), _charset(charset), _conn(NULL) + MysqlClient(const string& host, size_t port, const string& user, const string& passwd, const string& db, const string& charset = "utf8"): host_(host), port_(port), user_(user), passwd_(passwd), db_(db), charset_(charset), conn_(NULL) { - _setInitFlag(_init()); + setInitFlag_(init_()); } ~MysqlClient() { - if(_conn) + if(conn_) { - mysql_close(_conn); + mysql_close(conn_); } }; private: - bool _init() + bool init_() { //cout<run(); + return NULL; + } + }; +} + +#endif diff --git a/src/Limonp/ThreadPool.hpp b/src/Limonp/ThreadPool.hpp new file mode 100644 index 0000000..493c2ce --- /dev/null +++ b/src/Limonp/ThreadPool.hpp @@ -0,0 +1,105 @@ +#ifndef LIMONP_THREAD_POOL_HPP +#define LIMONP_THREAD_POOL_HPP + +#include "Thread.hpp" +#include "BlockingQueue.hpp" + +namespace Limonp +{ + class ITask + { + public: + virtual void run() = 0; + virtual ~ITask() {} + }; + + template + ITask* CreateTask(ArgType arg) + { + return new TaskType(arg); + } + template + ITask* CreateTask(ArgType0 arg0, ArgType1 arg1) + { + return new TaskType(arg0, arg1); + } + + //class ThreadPool; + class ThreadPool: NonCopyable + { + private: + class Worker: public IThread + { + private: + ThreadPool * ptThreadPool_; + public: + Worker(ThreadPool* pool): ptThreadPool_(pool) + { + assert(ptThreadPool_); + } + virtual ~Worker() + { + } + public: + virtual void run() + { + while(true) + { + ITask * task = ptThreadPool_->queue_.pop(); + if(task == NULL) + { + break; + } + task->run(); + delete task; + } + } + }; + private: + friend class Worker; + private: + vector threads_; + BoundedBlockingQueue queue_; + //mutable MutexLock mutex_; + //Condition isEmpty__; + public: + ThreadPool(size_t threadNum, size_t queueMaxSize): threads_(threadNum), queue_(queueMaxSize)//, mutex_(), isEmpty__(mutex_) + { + assert(threadNum); + assert(queueMaxSize); + for(size_t i = 0; i < threads_.size(); i ++) + { + threads_[i] = new Worker(this); + } + } + ~ThreadPool() + { + for(size_t i = 0; i < threads_.size(); i ++) + { + queue_.push(NULL); + } + for(size_t i = 0; i < threads_.size(); i ++) + { + threads_[i]->join(); + delete threads_[i]; + } + } + + public: + void start() + { + for(size_t i = 0; i < threads_.size(); i++) + { + threads_[i]->start(); + } + } + + void add(ITask* task) + { + assert(task); + queue_.push(task); + } + }; +} + +#endif diff --git a/test/testdata/server.conf b/test/testdata/server.conf index fdf54c9..01321db 100644 --- a/test/testdata/server.conf +++ b/test/testdata/server.conf @@ -3,6 +3,8 @@ #socket listen port port=11200 +thread_number=4 +queue_max_size=4096 #dict path dict_path=../dict/jieba.dict.utf8