对一个memcache的封装

来源:互联网 发布:淘宝店铺招牌怎么制作 编辑:程序博客网 时间:2024/04/28 03:40

最近对一个memcache进行封装,感觉还不错 由于注释比较多,就不一一解释了。

头文件

#pragma once


#include <libmemcached/memcached.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <unistd.h>


class ESMemcache
{
public:
ESMemcache(void);
~ESMemcache(void);
public:
bool Init(char* pIPPort, int msec=1000);
bool SetRecord(char* key, const char* value, const size_t bytes, const time_t expire = 0);
bool Replace(char* key, const char* value, const size_t bytes, const time_t expire = 0);
void GetRecord(const char* key, std::string &value);
bool DeleteRecord(const char* key);
bool Increment(const char *key, int offset, uint64_t &value);
bool Decrement(const char *key, int offset, uint64_t &value);
bool IsKeyExist(const char *key);
private:
int setTimeOut(int msec);
memcached_return rc;
memcached_st *memc;


};

cpp

#include "ESMemcache.h"
using namespace std;


ESMemcache::ESMemcache(void)
{
}


ESMemcache::~ESMemcache(void)
{
}


int ESMemcache::setTimeOut(int msec)
{
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, msec);
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, msec);
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, msec);
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, -1);
return 0;
}


bool ESMemcache::Init(char* pIPPort, int msec)
{
memc = memcached_create(NULL);
int nPort = 0;
char * pszPort = strchr(pIPPort, ':');
if (pszPort) {
nPort = atoi(pszPort + 1);
*pszPort = 0;
}
setTimeOut(msec);
rc = memcached_server_add(memc, pIPPort, nPort);
if(rc != MEMCACHED_SUCCESS)
return false;

return rc == MEMCACHED_SUCCESS;
}




bool ESMemcache::SetRecord(char* key, const char* value, const size_t bytes, const time_t expire)
{
rc = memcached_set(memc, key, strlen(key), value, bytes, expire, 0);
return rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED;
}


bool ESMemcache::Replace(char* key, const char* value, const size_t bytes, const time_t expire)
{
rc = memcached_replace(memc, key, strlen(key), value, bytes, expire, 0);
return rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED;
}




void ESMemcache::GetRecord(const char* key, std::string &value)
{
size_t value_length = 0;
uint32_t flags = 0;
char *val = memcached_get(memc, key, strlen(key), &value_length, &flags, &rc);
if(val !=NULL)
{
value = val;
free(val);
}
else
{
value.clear();
}
}


bool ESMemcache::DeleteRecord(const char* key)
{


rc = memcached_delete(memc, key, strlen(key), 0);
return rc == MEMCACHED_SUCCESS;
}


bool ESMemcache::Increment(const char *key, int offset, uint64_t &value)
{
rc = memcached_increment(memc, key, strlen(key), offset, &value);
return rc == MEMCACHED_SUCCESS;
}


bool ESMemcache::Decrement(const char *key, int offset, uint64_t &value)
{
rc = memcached_decrement(memc, key, strlen(key), offset, &value);
return rc == MEMCACHED_SUCCESS;
}


bool ESMemcache::IsKeyExist(const char *key)
{
size_t value_length = 0;
uint32_t flags = 0;
memcached_get(memc, key, strlen(key), &value_length, &flags, &rc);
if (rc == MEMCACHED_NOTFOUND) {
return false;
}
return true;
}

packet的base类,偷懒,将所有实现都放在头文件中了,有洁癖的可以自己拆


#pragma once



#ifndef ES_TCP_MAX_BUFFER    //TCP socket 最大接收 Buffer Size
#   define  ES_TCP_MAX_BUFFER    1024*16
#endif


#ifndef _WINDEF_
typedef unsigned char       BYTE;
#endif
// STL头文件定义
#include <string>
#include <queue>
#include <vector>
#include <deque>
#include <list>
#include <iostream>
#include <sstream>
#include <map>
#include <arpa/inet.h>
#include <iomanip>
using namespace std;


#if WIN32
typedef long long       int64_t;
#endif


#ifndef WIN32
#   define _atoi64 atoll
#endif


#define     SERVER_PACEKTVER    1
#define     PROTOL_HEADER_SIZE  8


/*
struct TPkgHeader //包头
{
    char  cmdConst[2]; //ES
    short cmd;
    short cVersion;
    short length; //body长度
};
*/




typedef unsigned long long __u64;
#define de_htonll(x) \
({ \
    __u64 __x = (x); \
    ((__u64)( \
    (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \
    (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \
    (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \
    (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) <<  8) | \
    (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >>  8) | \
    (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
    (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \
    (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \
})




inline long long htonll(long long hvalue)
{
    //判断本机是大端还是小端
    short  i=20;
    if( htons(i) == i ) //本地是大端
    {
        return hvalue;
    } 
    else //本地是小端,需要转换
    {
        return (long long)de_htonll(hvalue);
    }
}


inline long long ntohll(long long nvalue)
{
    //判断本机是大端还是小端
    short  i=20;
    if( htons(i) == i ) //本地是大端
    {
        return nvalue;
    } 
    else //本地是小端,需要转换
    {
        return (long long)de_htonll(nvalue);
    }
}




inline string ESHexDumpImp(const void *pdata, unsigned int len)
{
        string outstr;
       if(pdata == 0 || len == 0)
        {
            return "";
        }
    
        int cnt = 0;
        int n = 0;
        int cnt2 = 0;
        stringstream  sstr;
        const char *data = (const char *)pdata;
        sstr<<"Address               Hexadecimal values                  Printable\n";
        sstr<<"-------  -----------------------------------------------  -------------\n";
        unsigned char buffer[20];
        unsigned int rpos = 0;


        while ( 1 )
        {
                if(len <= rpos)
                {
                        break;
                }
                if(len >= rpos + 16)
                {
                        memcpy(buffer, data + rpos, 16);
                        rpos += 16;
                        cnt = 16;
                }
                else
                {
                        memcpy(buffer, data + rpos, len - rpos);
                        cnt = len - rpos;
                        rpos = len;
                }
                if(cnt <= 0)
                {
                        outstr = sstr.str();
                        return outstr;
                }


                sstr << setw(7) << ( int ) rpos << "  ";


                cnt2 = 0;
                for ( n = 0; n < 16; n++ )
                {
                        cnt2 = cnt2 + 1;
                        if ( cnt2 <= cnt )
                        {
                                sstr << hex << setw(2) << setfill ( '0' ) <<  (unsigned int)buffer[n];
                        }
                        else
                        {
                                sstr << "  ";
                        }
                        sstr << " ";
                }


                sstr << setfill ( ' ' );


                sstr << " ";
                cnt2 = 0;
                for ( n = 0; n < 16; n++ )
                {
                        cnt2 = cnt2 + 1;
                        if ( cnt2 <= cnt )
                        {
                                if ( buffer[n] < 32 || 126 < buffer[n] )
                                {
                                        sstr << '.';
                                }
                                else
                                {
                                        sstr << buffer[n];
                                }
                        }
                }
                sstr << "\n";
                sstr << dec;
        }


        outstr = sstr.str();
        return outstr;
}






template <unsigned _buffer_size, unsigned _header_size>
class PacketBase
{
public:
    char *packet_buf(void)   {return m_strBuf;}
    unsigned packet_size(void)    {return m_nPacketSize;}
protected:
PacketBase(void){}
    ~PacketBase(void){}
    enum
    {
        PACKET_HEADER_SIZE = _header_size,
        PACKET_BUFFER_SIZE = _buffer_size
    };
unsigned  m_nPacketSize ; // 实际报文总长度
    unsigned  m_nBufPos;
    char m_strBuf[PACKET_BUFFER_SIZE];  // 报文包缓存


protected:
    ////////////////////////////////////////////////////////////////////////////////
    bool _copy(const void *pInBuf, unsigned nLen)
    {
        if(NULL==pInBuf || nLen > PACKET_BUFFER_SIZE){
            return false;
}


        _reset();
        memcpy(m_strBuf, pInBuf, nLen);
        m_nPacketSize = nLen;
        //assert(m_nPacketSize>PACKET_HEADER_SIZE);
        return true;
    }
    ////////////////////////////////////////////////////////////////////////////////
    void _begin(short nCmdType, short cVersion)
    {
        _reset();
        _writeHeader("ES", sizeof(char)*2, 0);// 命令码


        short cmdType = htons(nCmdType);
        _writeHeader((char*)&cmdType, sizeof(short), 2);// 命令码
        
        short version = htons(cVersion);
        _writeHeader((char*)&version, sizeof(short), 4);       // 版本号
    }


    void _SetBegin(short nCmdType)
    {
        short cmdType = htons(nCmdType);
        _writeHeader((char*)&cmdType, sizeof(short), 2);// 命令码
    }
public:
    short GetCmdType(void)
    {
        short nCmdType;
        _readHeader((char*)&nCmdType, sizeof(short), 2);// 命令码
        return ntohs(nCmdType);
    }
    short GetVersion(void)
    {
        short c;
        _readHeader((char *)&c, sizeof(short), 4);  // 版本号
        return ntohs(c);
    }
    short GetBodyLength(void)
    {
        short nLen;
        _readHeader((char*)&nLen, sizeof(short), 6);// 包正文长度
        return ntohs(nLen);
    }


protected:
    void _end(unsigned /*sequence*/ = 0)
    {
        short nBody = m_nPacketSize - PACKET_HEADER_SIZE;
        short bodyLen = htons(nBody);
        _writeHeader((char*)&bodyLen, sizeof(short), 6);  // 包正文长度
    }


    /////////////////////////////////////////////////////////////////////////////////
    void _reset(void)
    {
        memset(m_strBuf, 0, PACKET_BUFFER_SIZE);
        m_nBufPos = PACKET_HEADER_SIZE;
        m_nPacketSize = PACKET_HEADER_SIZE;
    }
    // 取出一个变量
    bool _Read(char *pOut, unsigned nLen)
    {
        if((nLen + m_nBufPos) > m_nPacketSize )
            return false ;


        memcpy(pOut, m_strBuf + m_nBufPos, nLen);
        m_nBufPos += nLen;
        return true;
    }
    //取出变量并从包中移除
    bool _ReadDel(char *pOut, unsigned nLen)
    {
        if(!_Read(pOut, nLen)){
            return false;
}
        memcpy(m_strBuf + m_nBufPos - nLen, m_strBuf + m_nBufPos, PACKET_BUFFER_SIZE - m_nBufPos);
        m_nBufPos -= nLen;
        m_nPacketSize -= nLen;
        _end();
        return true;
    }
    //读撤消
    void _readundo(unsigned nLen)
    {
        m_nBufPos -= nLen;
    }
    //读出当前POS位置的BUFFER指针
    char *_readpoint(unsigned nLen) //注意返回的是指针 请慎重使用string
    {
        if((nLen + m_nBufPos) > m_nPacketSize){
            return NULL; 
}
        char *p = &m_strBuf[m_nBufPos];
        m_nBufPos += nLen;
        return p;


    }
    // 写入一个变量
    bool _Write(const char *pIn, unsigned nLen)
    {
        if( (nLen + m_nPacketSize) > PACKET_BUFFER_SIZE){
            return false ;
}
        memcpy(m_strBuf+m_nPacketSize, pIn, nLen);
        m_nPacketSize += nLen;
        return true;
    }
    //插入一个变量
    bool _Insert(const char *pIn, unsigned nLen)
    {
        if((nLen + m_nPacketSize) > PACKET_BUFFER_SIZE){
            return false;
}
        memcpy(m_strBuf+PACKET_HEADER_SIZE+nLen, m_strBuf+PACKET_HEADER_SIZE, m_nPacketSize-PACKET_HEADER_SIZE);
        memcpy(m_strBuf+PACKET_HEADER_SIZE, pIn, nLen);
        m_nPacketSize += nLen;
        _end();
        return true;
    }
    // 写入一个变量
    bool _writezero(void)
    {
        if((m_nPacketSize + 1) > PACKET_BUFFER_SIZE){
            return false ;
}
        memset(m_strBuf+m_nPacketSize, '\0', sizeof(char)) ;
        m_nPacketSize ++;
        return true;
    }
    // readHeader
    void _readHeader(char *pOut, unsigned nLen, unsigned nPos)
    {
        if( nPos+nLen <= PACKET_HEADER_SIZE)
        {
            memcpy(pOut, m_strBuf+nPos, nLen) ;
        }
    }
    // writeHeader
    void _writeHeader(char *pIn, unsigned nLen, unsigned nPos)
    {
        if( nPos+nLen <= PACKET_HEADER_SIZE)
        {
            memcpy(m_strBuf+nPos, pIn, nLen) ;
        }
    }
};


template <unsigned BUFFER_SIZE, unsigned HEADER_SIZE=PROTOL_HEADER_SIZE>
class InputPacket: public PacketBase<BUFFER_SIZE, HEADER_SIZE>
{
public:
    typedef PacketBase<BUFFER_SIZE, HEADER_SIZE> base;


    int ReadInt(void)
    {
        //这里必需初始化
        int nValue = -1; 
        base::_Read((char*)&nValue, sizeof(int)); 
        return ntohl(nValue);
    } 


    short ReadShort(void)
    {
        short nValue = -1; 
        base::_Read((char*)&nValue, sizeof(short)); 
        return ntohs(nValue);
    }


    BYTE ReadByte(void)
    {
        BYTE nValue = -1; 
        base::_Read((char*)&nValue, sizeof(BYTE)); 
        return nValue;
    }


    int64_t ReadInt64(void)
    {
        int64_t nValue = -1; 
        base::_Read((char*)&nValue, sizeof(int64_t));
        return ntohll(nValue);
    }


    bool ReadString(char *pOutString, unsigned nMaxLen)
    {
        int nLen = ReadInt();
        if(nLen == -1){  //这里必需判断
            return false;
}
        if(nLen > nMaxLen || nLen+base::m_nBufPos>base::m_nPacketSize )
        {
            base::_readundo(sizeof(unsigned));
            return false;
        }
        return base::_Read(pOutString, nLen);
    }


    char *ReadChar(void)
    {
        unsigned nLen = ReadInt();
        if(nLen == (unsigned)-1 || nLen+base::m_nBufPos>base::m_nPacketSize) {
base::_readundo(sizeof(unsigned));
return NULL;
}
        return base::_readpoint(nLen);
    }


    bool ReadString(string &str)
    {
        char *p = ReadChar();
        str =  (p == NULL ? "" : p);
return p != NULL;
    }


    int ReadBinary(char *pBuf, unsigned nMaxLen)
    {
        unsigned nLen = ReadInt();
        if(nLen == (unsigned)-1 || nLen > nMaxLen || nLen+base::m_nBufPos>base::m_nPacketSize )
        {
            base::_readundo(sizeof(unsigned));
            return -1;
        }
        if(base::_Read(pBuf, nLen)){
            return nLen ;
}
        return 0;
    }
    void Reset(void)
    {
        base::_reset();
    }
    bool Copy(const void *pInBuf, unsigned nLen)
    {
        return base::_copy(pInBuf, nLen);
    }
};


template <unsigned BUFFER_SIZE, unsigned HEADER_SIZE=PROTOL_HEADER_SIZE>
class OutputPacket: public PacketBase<BUFFER_SIZE, HEADER_SIZE>
{
public:
    OutputPacket(void){}
public:
    typedef PacketBase<BUFFER_SIZE, HEADER_SIZE> base;


    bool WriteInt(int nValue)
    {
        int value = htonl(nValue);
        return base::_Write((char*)&value, sizeof(int));
    }


    bool WriteInt64(int64_t nValue)     
    {
        int64_t value = htonll(nValue);
        return base::_Write((char*)&value, sizeof(int64_t));
    }


    bool WriteByte(BYTE nValue)     
    {
        return base::_Write((char*)&nValue, sizeof(BYTE));
    }


    bool WriteShort(short nValue)
    {
        short value = htons(nValue);
        return base::_Write((char*)&value, sizeof(short));
    }


    //在正文首插入数据
    bool InsertInt(int nValue)
    {
        int value = htonl(nValue);
        return base::_Insert((char*)&value, sizeof(int));
    }


    bool InsertByte(BYTE nValue)    
    {
        return base::_Insert((char*)&nValue, sizeof(BYTE));
    }


    bool WriteString(const char *pString)
    {
        int nLen = (int)strlen(pString) ;
        WriteInt(nLen + 1) ;
        return base::_Write(pString, nLen) && base::_writezero();
    }


    bool WriteString(const string &strDate)
    {
        int nLen = strDate.size();
        WriteInt(nLen + 1) ;
        return base::_Write(strDate.c_str(), nLen) && base::_writezero();
    }


    bool WriteBinary(const char *pBuf, unsigned nLen)
    {
        WriteInt(nLen) ;
        return base::_Write(pBuf, nLen) ;
    }
    bool Copy(const void *pInBuf, unsigned nLen)
    {
        return base::_copy(pInBuf, nLen);
    }
    void Begin(short nCommand, char cVersion = SERVER_PACEKTVER)
    {
        base::_begin(nCommand, cVersion);
    }
    void End(void)
    {
        base::_end();
    }
   
    void SetBegin(short nCommand)
    {
        base::_SetBegin(nCommand);
    }
};


typedef InputPacket<ES_TCP_MAX_BUFFER>   ESInputPacket;
typedef OutputPacket<ES_TCP_MAX_BUFFER>  ESOutputPacket;