update husky to be hpp

This commit is contained in:
wyy 2013-11-30 05:12:10 -08:00
parent 0ba5522b42
commit 5799d6d487
8 changed files with 315 additions and 590 deletions

View File

@ -1,8 +1,4 @@
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
SET(LIBHUSKY_SRC Daemon.cpp ServerFrame.cpp)
ADD_LIBRARY(husky STATIC ${LIBHUSKY_SRC})
INSTALL(TARGETS husky ARCHIVE DESTINATION lib/CppJieba/Husky)
INSTALL(FILES Daemon.h globals.h HttpReqInfo.hpp ServerFrame.h ThreadManager.hpp DESTINATION include/CppJieba/Husky)
INSTALL(FILES HttpReqInfo.hpp ServerFrame.hpp ThreadManager.hpp DESTINATION include/CppJieba/Husky)

View File

@ -1,191 +0,0 @@
#include "Daemon.h"
namespace Husky
{
IWorkHandler * Daemon::m_pHandler;
int Daemon::m_nChildPid = 0;
const char* Daemon::m_pidFile = NULL;
bool Daemon::isAbnormalExit(int pid, int status)
{
bool bRestart = true;
if (WIFEXITED(status)) //exit()or return
{
LogDebug("child normal termination, exit pid = %d, status = %d", pid, WEXITSTATUS(status));
bRestart = false;
}
else if (WIFSIGNALED(status)) //signal方式退出
{
LogError("abnormal termination, pid = %d, signal number = %d%s", pid, WTERMSIG(status),
#ifdef WCOREDUMP
WCOREDUMP(status) ? " (core file generated)" :
#endif
"");
if (WTERMSIG(status) == SIGKILL)
{
bRestart = false;
LogError("has been killed by user , exit pid = %d, status = %d", pid, WEXITSTATUS(status));
}
}
else if (WIFSTOPPED(status)) //暂停的子进程退出
{
LogError("child stopped, pid = %d, signal number = %d", pid, WSTOPSIG(status));
}
else
{
LogError("child other reason quit, pid = %d, signal number = %d", pid, WSTOPSIG(status));
}
return bRestart;
}
bool Daemon::start()
{
string masterPidStr = loadFile2Str(m_pidFile);
int masterPid = atoi(masterPidStr.c_str());
if(masterPid)
{
if (kill(masterPid, 0) == 0)
{
LogError("Another instance exist, ready to quit!");
return false;
}
}
initAsDaemon();
char buf[64];
sprintf(buf, "%d", getpid());
if (!WriteStr2File(m_pidFile,buf ,"w"))
{
LogFatal("Write master pid fail!");
}
while(true)
{
pid_t pid = fork();
if (0 == pid)// child process do
{
signal(SIGUSR1, sigChildHandler);
signal(SIGPIPE, SIG_IGN);
signal(SIGTTOU, SIG_IGN);
signal(SIGTTIN, SIG_IGN);
signal(SIGTERM, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
if(!m_pHandler->init())
{
LogFatal("m_pHandler init failed!");
return false;
}
#ifdef DEBUG
LogDebug("Worker init ok pid = %d",(int)getpid());
#endif
if (!m_pHandler->run())
{
LogError("m_pHandler run finish with failure!");
return false;
}
#ifdef DEBUG
LogDebug("run finish -ok!");
#endif
//if(!m_pHandler->dispose())
//{
// LogError("m_pHandler dispose with failure!");
// return false;
//}
#ifdef DEBUG
//LogDebug("Worker dispose -ok!");
#endif
exit(0);
}
m_nChildPid=pid;
int status;
pid = wait(&status);
if (!isAbnormalExit(pid, status))
{
LogDebug("child exit normally! and Daemon exit");
break;
}
}
return true;
}
bool Daemon::stop()
{
string masterPidStr = loadFile2Str(m_pidFile);
int masterPid = atoi(masterPidStr.c_str());
if(masterPid)
{
#ifdef DEBUG
LogDebug("read last masterPid[%d]",masterPid);
#endif
if (kill(masterPid, 0) == 0)
{
#ifdef DEBUG
LogDebug("find previous daemon pid= %d, current pid= %d", masterPid, getpid());
#endif
kill(masterPid, SIGTERM);
int tryTime = 200;
while (kill(masterPid, 0) == 0 && --tryTime)
{
sleep(1);
}
if (!tryTime && kill(masterPid, 0) == 0)
{
LogError("Time out shutdown fail!");
return false;
}
LogInfo("previous daemon pid[%d] shutdown ok.", masterPid);
return true;
}
}
LogError("Another instance doesn't exist, ready to quit!");
return false;
}
void Daemon::initAsDaemon()
{
if (fork() > 0)
exit(0);
setsid();
signal(SIGPIPE, SIG_IGN);
signal(SIGTTOU, SIG_IGN);
signal(SIGTTIN, SIG_IGN);
signal(SIGTERM, sigMasterHandler);
signal(SIGINT, sigMasterHandler);
signal(SIGQUIT, sigMasterHandler);
signal(SIGKILL, sigMasterHandler);
}
void Daemon::sigMasterHandler(int sig)
{
kill(m_nChildPid,SIGUSR1);
LogDebug("master = %d sig child =%d!",getpid(),m_nChildPid);
}
void Daemon::sigChildHandler(int sig)
{
if (sig == SIGUSR1)
{
m_pHandler->dispose();
LogDebug("master = %d signal accept current pid =%d!",getppid(),getpid());
}
}
}

View File

@ -1,51 +0,0 @@
#ifndef HUSKY_DAEMON_H_
#define HUSKY_DAEMON_H_
#include "globals.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <signal.h>
#include "../Limonp/logger.hpp"
namespace Husky
{
using namespace Limonp;
class IWorkHandler
{
public:
virtual ~IWorkHandler(){}
virtual bool init() = 0;
virtual bool dispose() = 0;
virtual bool run() = 0;
};
class Daemon
{
public:
Daemon(IWorkHandler * workHandler, const char* pidFile)
{
m_pHandler = workHandler;
m_pidFile = pidFile;
}
~Daemon(){};
public:
bool start();
bool stop();
public:
static void initAsDaemon();
static void sigMasterHandler(int sig);
static void sigChildHandler(int sig);
static bool isAbnormalExit(int pid, int status);
private:
//static IRequestHandler* m_pHandler;
//static ServerFrame m_ServerFrame;
static int m_nChildPid;
static IWorkHandler * m_pHandler;
static const char* m_pidFile;
};
}
#endif

View File

@ -3,9 +3,7 @@
#include <iostream>
#include <string>
#include "../Limonp/logger.hpp"
#include "../Limonp/str_functs.hpp"
#include "globals.h"
#include "Limonp/logger.hpp"
namespace Husky
{

View File

@ -1,231 +0,0 @@
#include "ServerFrame.h"
namespace Husky
{
const struct timeval ServerFrame::m_timev = {SOCKET_TIMEOUT, 0};
pthread_mutex_t ServerFrame::m_pmAccept;
bool ServerFrame::m_bShutdown = false;
bool ServerFrame::dispose()
{
m_bShutdown=true;
if (SOCKET_ERROR==closesocket(m_lsnSock))
{
LogError("error [%s]", strerror(errno));
return false;
}
int sockfd;
struct sockaddr_in dest;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
LogError("error [%s]", strerror(errno));
return false;
}
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(m_nLsnPort);
if (inet_aton("127.0.0.1", (struct in_addr *) &dest.sin_addr.s_addr) == 0)
{
LogError("error [%s]", strerror(errno));
return false;
}
if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) < 0)
{
LogError("error [%s]", strerror(errno));
}
close(sockfd);
if(!m_pHandler->dispose())
{
LogFatal("m_pHandler dispose failed.");
}
return true;
}
bool ServerFrame::run()
{
if(SOCKET_ERROR==listen(m_lsnSock,LISEN_QUEUR_LEN))
{
LogError("error [%s]", strerror(errno));
return false;
}
ThreadManager thrMngr;
int i;
SPara para;
para.hSock=m_lsnSock;
para.pHandler=m_pHandler;
for (i=0;i<m_nThreadCount;i++)
{
if (0!=thrMngr.CreateThread(ServerThread, &para))
{
break;
}
}
LogDebug("expect thread count %d, real count %d",m_nThreadCount,i);
if(i==0)
{
LogError("error [%s]", strerror(errno));
return false;
}
LogInfo("server start to run.........");
if (thrMngr.WaitMultipleThread()!=0)
{
return false;
}
return true;
}
void* ServerFrame::ServerThread(void *lpParameter )
{
SPara *pPara=(SPara*)lpParameter;
SOCKET hSockLsn=pPara->hSock;
IRequestHandler *pHandler=pPara->pHandler;
int nRetCode;
linger lng;
char chRecvBuf[RECV_BUFFER];
SOCKET hClientSock;
string strHttpResp;
sockaddr_in clientaddr;
socklen_t nSize = sizeof(clientaddr);
while(!m_bShutdown)
{
HttpReqInfo httpReq;
pthread_mutex_lock(&m_pmAccept);
hClientSock=accept(hSockLsn,(sockaddr *)&clientaddr, &nSize);
pthread_mutex_unlock(&m_pmAccept);
if(hClientSock==SOCKET_ERROR)
{
if(!m_bShutdown)
LogError("error [%s]", strerror(errno));
continue;
}
httpReq[CLIENT_IP_K] = inet_ntoa(clientaddr.sin_addr);// inet_ntoa is not thread safety at some version
lng.l_linger=1;
lng.l_onoff=1;
if(SOCKET_ERROR==setsockopt(hClientSock,SOL_SOCKET,SO_LINGER,(char*)&lng,sizeof(lng)))
{
LogError("error [%s]", strerror(errno));
}
if(SOCKET_ERROR==setsockopt(hClientSock,SOL_SOCKET,SO_RCVTIMEO,(char*)&m_timev,sizeof(m_timev)))
{
LogError("error [%s]", strerror(errno));
}
if(SOCKET_ERROR==setsockopt(hClientSock,SOL_SOCKET,SO_SNDTIMEO,(char*)&m_timev,sizeof(m_timev)))
{
LogError("error [%s]", strerror(errno));
}
string strRec;
string strSnd;
memset(chRecvBuf,0,sizeof(chRecvBuf));
nRetCode = recv(hClientSock, chRecvBuf, RECV_BUFFER, 0);
strRec = chRecvBuf;
#ifdef HUKSY_DEBUG
LogDebug("request[%s]", strRec.c_str());
#endif
if(SOCKET_ERROR==nRetCode)
{
LogDebug("error [%s]", strerror(errno));
closesocket(hClientSock);
continue;
}
if(0==nRetCode)
{
LogDebug("connection has been gracefully closed");
closesocket(hClientSock);
continue;
}
httpReq.load(strRec);
pHandler->do_GET(httpReq, strSnd);
char chHttpHeader[2048];
sprintf(chHttpHeader, RESPONSE_FORMAT, RESPONSE_CHARSET_UTF8, int(strSnd.length()));
strHttpResp=chHttpHeader;
strHttpResp+=strSnd;
#ifdef HUKSY_DEBUG
LogDebug("response'body [%s]", strSnd.c_str());
#endif
if (SOCKET_ERROR==send(hClientSock,strHttpResp.c_str(),strHttpResp.length(),0))
{
LogError("error [%s]", strerror(errno));
}
closesocket(hClientSock);
}
return 0;
}
bool ServerFrame::init()
{
if (!BindToLocalHost(m_lsnSock,m_nLsnPort))
{
LogFatal("BindToLocalHost failed.");
return false;
}
LogInfo("init ok {port:%d, threadNum:%d}", m_nLsnPort, m_nThreadCount);
if(!m_pHandler->init())
{
LogFatal("m_pHandler init failed.");
return false;
}
return true;
}
bool ServerFrame::BindToLocalHost(SOCKET &sock,u_short nPort)
{
sock=socket(AF_INET,SOCK_STREAM,0);
if(INVALID_SOCKET==sock)
{
LogError("error [%s]", strerror(errno));
return false;
}
int nRet = 1;
if(SOCKET_ERROR==setsockopt(m_lsnSock, SOL_SOCKET, SO_REUSEADDR, (char*)&nRet, sizeof(nRet)))
{
LogError("error [%s]", strerror(errno));
}
struct sockaddr_in addrSock;
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(nPort);
addrSock.sin_addr.s_addr=htonl(INADDR_ANY);
int retval;
retval = ::bind(sock,(sockaddr*)&addrSock,sizeof(sockaddr));
if(SOCKET_ERROR==retval)
{
LogError("error [%s]", strerror(errno));
closesocket(sock);
return false;
}
return true;
}
}

View File

@ -1,85 +0,0 @@
#ifndef HUSKY_SERVERFRAME_H
#define HUSKY_SERVERFRAME_H
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <vector>
#include "globals.h"
#include "ThreadManager.hpp"
#include "HttpReqInfo.hpp"
#include "Daemon.h"
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket close
#define RECV_BUFFER 10240
#define LISEN_QUEUR_LEN 1024
namespace Husky
{
using namespace Limonp;
typedef int SOCKET;
class IRequestHandler
{
public:
virtual ~IRequestHandler(){};
public:
virtual bool init() = 0;
virtual bool dispose() = 0;
virtual bool do_GET(const HttpReqInfo& httpReq, string& res) = 0;
};
struct SPara
{
SOCKET hSock;
IRequestHandler * pHandler;
};
class ServerFrame: public IWorkHandler
{
public:
ServerFrame(unsigned nPort, unsigned nThreadCount, IRequestHandler* pHandler)
{
m_nLsnPort = nPort;
m_nThreadCount = nThreadCount;
m_pHandler = pHandler;
pthread_mutex_init(&m_pmAccept,NULL);
};
virtual ~ServerFrame(){pthread_mutex_destroy(&m_pmAccept);};
virtual bool init();
virtual bool dispose();
virtual bool run();
protected:
bool BindToLocalHost(SOCKET &sock,u_short nPort);
static void * ServerThread(void * lpParameter );
private:
u_short m_nLsnPort;
u_short m_nThreadCount;
SOCKET m_lsnSock;
IRequestHandler *m_pHandler;
static bool m_bShutdown;
static pthread_mutex_t m_pmAccept;
static const struct timeval m_timev;
};
}
#endif

313
src/Husky/ServerFrame.hpp Normal file
View File

@ -0,0 +1,313 @@
#ifndef HUSKY_SERVERFRAME_H
#define HUSKY_SERVERFRAME_H
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <vector>
#include "ThreadManager.hpp"
#include "HttpReqInfo.hpp"
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket close
#define RECV_BUFFER 10240
#define LISEN_QUEUR_LEN 1024
namespace Husky
{
using namespace Limonp;
typedef int SOCKET;
const struct timeval SOCKET_TIMEOUT = {2, 0};
const char* const RESPONSE_FORMAT = "HTTP/1.1 200 OK\r\nConnection: close\r\nServer: FrameServer/1.0.0\r\nContent-Type: text/json; charset=%s\r\nContent-Length: %d\r\n\r\n";
const char* const RESPONSE_CHARSET_UTF8 = "UTF-8";
const char* const RESPONSE_CHARSET_GB2312 = "GB2312";
const char* const CLIENT_IP_K = "CLIENT_IP";
typedef unsigned short u_short;
typedef unsigned int u_int;
class IRequestHandler
{
public:
virtual ~IRequestHandler(){};
public:
virtual bool init() = 0;
virtual bool dispose() = 0;
virtual bool do_GET(const HttpReqInfo& httpReq, string& res) = 0;
};
struct SPara
{
SOCKET hSock;
IRequestHandler * pHandler;
pthread_mutex_t * ppmAccept;
bool * pShutdown;
};
class ServerFrame//: public IWorkHandler
{
private:
pthread_mutex_t m_pmAccept;
bool m_bShutdown;
public:
ServerFrame(unsigned nPort, unsigned nThreadCount, IRequestHandler* pHandler)
{
m_nLsnPort = nPort;
m_nThreadCount = nThreadCount;
m_pHandler = pHandler;
m_bShutdown = false;
pthread_mutex_init(&m_pmAccept,NULL);
};
virtual ~ServerFrame(){pthread_mutex_destroy(&m_pmAccept);};
virtual bool init()
{
if (!BindToLocalHost(m_lsnSock,m_nLsnPort))
{
LogFatal("BindToLocalHost failed.");
return false;
}
LogInfo("init ok {port:%d, threadNum:%d}", m_nLsnPort, m_nThreadCount);
if(!m_pHandler->init())
{
LogFatal("m_pHandler init failed.");
return false;
}
return true;
}
virtual bool dispose()
{
m_bShutdown=true;
if (SOCKET_ERROR==closesocket(m_lsnSock))
{
LogError("error [%s]", strerror(errno));
return false;
}
int sockfd;
struct sockaddr_in dest;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
LogError("error [%s]", strerror(errno));
return false;
}
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(m_nLsnPort);
if (inet_aton("127.0.0.1", (struct in_addr *) &dest.sin_addr.s_addr) == 0)
{
LogError("error [%s]", strerror(errno));
return false;
}
if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) < 0)
{
LogError("error [%s]", strerror(errno));
}
close(sockfd);
if(!m_pHandler->dispose())
{
LogFatal("m_pHandler dispose failed.");
}
return true;
}
virtual bool run()
{
if(SOCKET_ERROR==listen(m_lsnSock,LISEN_QUEUR_LEN))
{
LogError("error [%s]", strerror(errno));
return false;
}
ThreadManager thrMngr;
int i;
SPara para;
para.hSock=m_lsnSock;
para.pHandler=m_pHandler;
para.ppmAccept=&m_pmAccept;
para.pShutdown=&m_bShutdown;
for (i=0;i<m_nThreadCount;i++)
{
if (0!=thrMngr.CreateThread(ServerThread, &para))
{
break;
}
}
LogDebug("expect thread count %d, real count %d",m_nThreadCount,i);
if(i==0)
{
LogError("error [%s]", strerror(errno));
return false;
}
LogInfo("server start to run.........");
if (thrMngr.WaitMultipleThread()!=0)
{
return false;
}
return true;
}
protected:
bool BindToLocalHost(SOCKET &sock,u_short nPort)
{
sock=socket(AF_INET,SOCK_STREAM,0);
if(INVALID_SOCKET==sock)
{
LogError("error [%s]", strerror(errno));
return false;
}
int nRet = 1;
if(SOCKET_ERROR==setsockopt(m_lsnSock, SOL_SOCKET, SO_REUSEADDR, (char*)&nRet, sizeof(nRet)))
{
LogError("error [%s]", strerror(errno));
}
struct sockaddr_in addrSock;
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(nPort);
addrSock.sin_addr.s_addr=htonl(INADDR_ANY);
int retval;
retval = ::bind(sock,(sockaddr*)&addrSock,sizeof(sockaddr));
if(SOCKET_ERROR==retval)
{
LogError("error [%s]", strerror(errno));
closesocket(sock);
return false;
}
return true;
}
static void * ServerThread(void * lpParameter )
{
SPara *pPara=(SPara*)lpParameter;
SOCKET hSockLsn=pPara->hSock;
IRequestHandler *pHandler=pPara->pHandler;
bool* pShutdown = pPara->pShutdown;
pthread_mutex_t* ppmAccept = pPara->ppmAccept;
int nRetCode;
linger lng;
char chRecvBuf[RECV_BUFFER];
SOCKET hClientSock;
string strHttpResp;
sockaddr_in clientaddr;
socklen_t nSize = sizeof(clientaddr);
while(!(*pShutdown))
{
HttpReqInfo httpReq;
pthread_mutex_lock(ppmAccept);
hClientSock=accept(hSockLsn,(sockaddr *)&clientaddr, &nSize);
pthread_mutex_unlock(ppmAccept);
if(hClientSock==SOCKET_ERROR)
{
if(!(*pShutdown))
LogError("error [%s]", strerror(errno));
continue;
}
httpReq[CLIENT_IP_K] = inet_ntoa(clientaddr.sin_addr);// inet_ntoa is not thread safety at some version
lng.l_linger=1;
lng.l_onoff=1;
if(SOCKET_ERROR==setsockopt(hClientSock,SOL_SOCKET,SO_LINGER,(char*)&lng,sizeof(lng)))
{
LogError("error [%s]", strerror(errno));
}
if(SOCKET_ERROR==setsockopt(hClientSock,SOL_SOCKET,SO_RCVTIMEO,(char*)&SOCKET_TIMEOUT,sizeof(SOCKET_TIMEOUT)))
{
LogError("error [%s]", strerror(errno));
}
if(SOCKET_ERROR==setsockopt(hClientSock,SOL_SOCKET,SO_SNDTIMEO,(char*)&SOCKET_TIMEOUT,sizeof(SOCKET_TIMEOUT)))
{
LogError("error [%s]", strerror(errno));
}
string strRec;
string strSnd;
memset(chRecvBuf,0,sizeof(chRecvBuf));
nRetCode = recv(hClientSock, chRecvBuf, RECV_BUFFER, 0);
strRec = chRecvBuf;
#ifdef HUKSY_DEBUG
LogDebug("request[%s]", strRec.c_str());
#endif
if(SOCKET_ERROR==nRetCode)
{
LogDebug("error [%s]", strerror(errno));
closesocket(hClientSock);
continue;
}
if(0==nRetCode)
{
LogDebug("connection has been gracefully closed");
closesocket(hClientSock);
continue;
}
httpReq.load(strRec);
pHandler->do_GET(httpReq, strSnd);
char chHttpHeader[2048];
sprintf(chHttpHeader, RESPONSE_FORMAT, RESPONSE_CHARSET_UTF8, int(strSnd.length()));
strHttpResp=chHttpHeader;
strHttpResp+=strSnd;
#ifdef HUKSY_DEBUG
LogDebug("response'body [%s]", strSnd.c_str());
#endif
if (SOCKET_ERROR==send(hClientSock,strHttpResp.c_str(),strHttpResp.length(),0))
{
LogError("error [%s]", strerror(errno));
}
closesocket(hClientSock);
}
return 0;
}
private:
u_short m_nLsnPort;
u_short m_nThreadCount;
SOCKET m_lsnSock;
IRequestHandler *m_pHandler;
//static bool m_bShutdown;
//static pthread_mutex_t m_pmAccept;
};
}
#endif

View File

@ -1,24 +0,0 @@
#ifndef HUSKY_GLOBALS_H
#define HUSKY_GLOBALS_H
#include <string>
#include <vector>
#include <set>
#include <string>
#include <stdlib.h>
namespace Husky
{
const char* const RESPONSE_CHARSET_UTF8 = "UTF-8";
const char* const RESPONSE_CHARSET_GB2312 = "GB2312";
const char* const CLIENT_IP_K = "CLIENT_IP";
const unsigned int SOCKET_TIMEOUT = 2;
const char* const RESPONSE_FORMAT = "HTTP/1.1 200 OK\r\nConnection: close\r\nServer: FrameServer/1.0.0\r\nContent-Type: text/json; charset=%s\r\nContent-Length: %d\r\n\r\n";
typedef unsigned short u_short;
typedef unsigned int u_int;
}
#endif