多線程記錄二進制流文件

一個生產者多消費者的應用 , 代碼裏目前就先簡單用了單生成單消費,

每一局麻將都需要記錄:每一次的發牌,抓牌,出牌 ,喫碰槓胡聽;

把所有的牌 序列化成二進制存入文件

每一局麻將生成一個key  , 可隨意自己組合

 

下面代碼思路僅供參考, 還未測試過; 可修改成多線程日誌

主線程唯一需要在開始的時候調用一次 start ,  記錄用push;

2種模式可選, 一種不關閉文件handle, 直到一局遊戲結束,再關閉

一種每次打開,寫入,關閉;

 

2種寫入方式, 一種寫入2進制流 ,

一種把2進制流轉成一個個unsigned long儲存在文件

[ 14張牌從 0x01 ~ 0x48 ]  0x48需要 7 位,因此每張牌用7位來儲存,最多 98 位,

對於一個unsigned long 最多儲存 4 張牌,  因此有14張牌時需要 4個unsigned long

 


class ErrorInfo{
    static const SIZE_T ERR_MSG_SIZE = 1 << 13;
    static CRITICAL_SECTION err_cs;
    static std::once_flag oneflag;
public:
    static void init(){
        std::call_once(ErrorInfo::oneflag,&ErrorInfo::init_cs);
    }
    static void init_cs(){
           InitializeCriticalSectionAndSpinCount(&ErrorInfo::err_cs, 4000);
    }

    static std::string getError(DWORD err){
        EnterCriticalSection(&ErrorInfo::err_cs);
        static HANDLE g_heap = HeapCreate(0, ERR_MSG_SIZE, 0);
        static char *buf = (char*)HeapAlloc(g_heap, 0, ERR_MSG_SIZE);
        static std::string errstr;
        static std::stringstream ss;
        ss.str("");
        ss.clear();
        errstr.clear();
        DWORD syslocale = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
        DWORD ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL, err, syslocale, buf, ERR_MSG_SIZE, NULL);

        if (!ret){
            static HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL, DONT_RESOLVE_DLL_REFERENCES);
            if (hDll){
                //如果在dll中查找,FORMAT_MESSAGE_FROM_HMODULE 添加上去, 第2個參數填寫句柄
                ret = FormatMessageA(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                    hDll, err, syslocale, buf, ERR_MSG_SIZE, NULL);
            }
        }
        if (ret && buf){
            buf[ret] = 0;
            errstr = buf;
            LeaveCriticalSection(&ErrorInfo::err_cs);
            return errstr;
        }
        ss << err;
        ss >> errstr;
        LeaveCriticalSection(&ErrorInfo::err_cs);
        return errstr;
    }
};
CRITICAL_SECTION ErrorInfo::err_cs;
std::once_flag ErrorInfo::oneflag;

#include <bitset>
struct  FileHandleData{
    HANDLE hFile;
    volatile bool inUse;
    std::string filepath;
    FileHandleData(HANDLE file = INVALID_HANDLE_VALUE, bool inUse = false):hFile(file),inUse(inUse){}
};
struct  storeData{
    std::string key;  //隨意的key
    std::string data; //數據
    int type; //類型[抓牌,出牌,喫碰槓等]
    int seat; //座位號
    storeData(const char * key, const char *data , int nDataLen , int type, int seat):key(key),data(data,nDataLen) , type(type) , seat(seat){}
    storeData(storeData && obj) throw() : key(std::move(obj.key)),data(std::move(obj.data)) , type(obj.type) , seat(obj.seat){}
    storeData & operator=(storeData && obj) throw(){
        if(this != &obj){
            key = std::move(obj.key);
            data = std::move(obj.data);
            type = obj.type;
            seat = obj.seat;
        }
        return *this;
    }
};
struct restoreData{
   int nLen;
   int type;
   int seat;
   char handCards[14];
   char buf[0];
};

class RecordFile
{
    CRITICAL_SECTION write_cs;
    CRITICAL_SECTION prepare_cs;
    CRITICAL_SECTION errlog_cs;
    CONDITION_VARIABLE write_cond;
    HANDLE hSem;
    deque<storeData> prepare_queue;
    deque<std::string> wait_for_close_queue;
    deque<storeData> write_queue;
    std::unordered_map<std::string,FileHandleData> write_map;
    HANDLE hThreadProducer;
    unsigned tid_producer;
    HANDLE hThreadConsumers[4];
    unsigned tid_consumers[4];
    bool bStopPrepare;
    bool bStopProcess;
    bool bAllDone;
    bool bStarted;
    int m_writeThreadCcount;
    int m_operate;
    int m_writeMode;
    std::string cur_dir_name;
    HANDLE hErrorLog;
    std::string errorLogPath;
    std::list<restoreData*> m_restoreList;
public:
    enum eOperate { OPENFILE = 1, CLOSEFILE = 2};
    enum eSpinCount { SpinCountMin = 1000, SpinCountNormal = 2000, SpinCountMax = 4000};
    enum eSemaphoreCount{ SemMin = 200 , SemNormal = 1000 , SemMax = 2000};
    enum eWriteMode{ WriteModeStream = 1, WriteModeLong = 2};

    RecordFile(int operate =CLOSEFILE ,int writeMode = WriteModeStream, int writeThreadCount = 1):bAllDone(false),
        bStarted(false),
        bStopProcess(false),
        bStopPrepare(false),
        m_operate(operate),m_writeMode(writeMode),
        m_writeThreadCcount(writeThreadCount)
    {
        cur_dir_name = std::string(typeid(*this).name()).substr(6);
        errorLogPath = cur_dir_name + "/errorlog.log";
        ErrorInfo::init();

    }
    void push(const char * key, const char * data , int nDataLen, int type , int seat){
        EnterCriticalSection(&prepare_cs);
        prepare_queue.emplace_back(key,data,nDataLen, type , seat);
        LeaveCriticalSection(&prepare_cs);
        ReleaseSemaphore(hSem,1,0);
    }
    void start(){
        if(bStarted)
            return;
        if(!(OPENFILE == m_operate || CLOSEFILE  == m_operate )){
            return;
        }
        bStarted = true;
        bAllDone = false;
        bStopProcess = false;
        bStopPrepare = false;
        hThreadProducer = NULL;
        memset(hThreadConsumers,0,sizeof(hThreadConsumers));
        InitializeCriticalSectionAndSpinCount(&write_cs , SpinCountMax);
        InitializeCriticalSectionAndSpinCount(&prepare_cs , SpinCountMax);
        InitializeCriticalSectionAndSpinCount(&errlog_cs , SpinCountMax);
        InitializeConditionVariable(&write_cond);

        hSem = CreateSemaphoreW(0,0,SemMax,NULL);
        if(!RecordFile::pathExists(cur_dir_name.c_str())){
            CreateDirectoryA(cur_dir_name.c_str(),NULL);
        }
        hErrorLog = CreateFileA(errorLogPath.c_str(),GENERIC_WRITE|GENERIC_READ,FILE_SHARE_READ ,
                                NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
        if(hErrorLog != INVALID_HANDLE_VALUE){
            setAppendFileHandle(hErrorLog);
        }
        hThreadProducer = (HANDLE)_beginthreadex(0,0,&RecordFile::mem_func_prepare,(void*)this,0,&tid_producer);
        for(int i = 0 ; i <m_writeThreadCcount; ++i)
            hThreadConsumers[i] = (HANDLE)_beginthreadex(0,0,&RecordFile::mem_func_process ,(void*)this,0,&tid_consumers[i]);

    }
    virtual ~RecordFile(){
        stop();
    }
    void log_error(const std::string &str){
        if(hErrorLog == INVALID_HANDLE_VALUE){
            return;
        }
        DWORD recv= 0 ;
        EnterCriticalSection(&errlog_cs);
        if(WriteFile(hErrorLog,str.c_str(),str.size() * sizeof(char),&recv,0)){
            FlushFileBuffers(hErrorLog);
        }
        LeaveCriticalSection(&errlog_cs);
    }
    static bool pathExists(const char * path){
        WIN32_FILE_ATTRIBUTE_DATA attr = { 0 };
        return 0 != GetFileAttributesExA(path, GetFileExInfoStandard, &attr);
    }
    void stop(){
        if(bAllDone || !bStarted)
            return;
        bAllDone = true;
        bStarted = false;
        EnterCriticalSection(&prepare_cs);
        bStopPrepare = true;
        LeaveCriticalSection(&prepare_cs);
        ReleaseSemaphore(&hSem,1,0);
        EnterCriticalSection(&write_cs);
        bStopProcess = true;
        LeaveCriticalSection(&write_cs);
        WakeAllConditionVariable(&write_cond);
        if(hThreadProducer){
            WaitForSingleObject(hThreadProducer,INFINITE);
            CloseHandle(hThreadProducer);
            hThreadProducer = 0;
        }

        WaitForMultipleObjects(m_writeThreadCcount,hThreadConsumers,TRUE,INFINITE);
        for(int i = 0 ; i < m_writeThreadCcount ; ++i){
            if(hThreadConsumers[i]){
                CloseHandle(hThreadConsumers[i]);
                hThreadConsumers[i] = 0;
            }
        }

        CloseHandle(hSem);
        hSem = NULL;
        DeleteCriticalSection(&write_cs);
        DeleteCriticalSection(&prepare_cs);
        DeleteCriticalSection(&errlog_cs);
    }
    bool setAppendFileHandle(HANDLE fileHandle){
        LARGE_INTEGER pos = {0};
        if(fileHandle != INVALID_HANDLE_VALUE){
            return SetFilePointerEx(fileHandle,pos,0,FILE_END);
        }
        return false;
    }
    static unsigned int mem_func_prepare(void * arg){
        RecordFile * p = (RecordFile * )arg;
        if( OPENFILE == p->m_operate)
            return p->__prepareOpenFileMode__();
        else if(CLOSEFILE == p->m_operate)
            return p->__prepareCloseFileEachTime__();
    }
    static unsigned int mem_func_process(void * arg){
        RecordFile * p = (RecordFile * )arg;
        if(OPENFILE == p->m_operate)
            return p->__processOpenFileMode__();
        else if(CLOSEFILE == p->m_operate)
            return p->__processCloseFileEachTime__();
    }
    std::string getFileName(const char * key){
        char filepath[MAX_PATH] = {0};
        SYSTEMTIME lt = {0};
        GetLocalTime(&lt);
        int len = cur_dir_name.size();
        memcpy(filepath,cur_dir_name.c_str(),len* sizeof(char));
        sprintf_s(filepath+len,MAX_PATH - len,"/%04d.%02d.%02d %02d.%02d.%02d.%04d-%s.txt",
                  lt.wYear,lt.wMonth,lt.wDay,lt.wHour,lt.wMinute,lt.wSecond,lt.wMilliseconds,
                  key);
        return filepath;
    }
    std::list<restoreData *> * restore(const char * key){
        std::string filepath = findFile(key);
        if(filepath.empty())
            return NULL;
        if(m_writeMode == WriteModeStream){
            readStreamBin(filepath);
        }
        else if(m_writeMode == WriteModeLong){
            readLong(filepath);
        }
        return &m_restoreList;
    }
    void readLong(const std::string & filepath){
        DWORD nBytesRead;
        BOOL bResult;
        HANDLE hFile = CreateFileA(filepath.c_str(),GENERIC_READ,
                                   FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,
                                   NULL);
        if(hFile == INVALID_HANDLE_VALUE)
            return;
        string sbuf;
        unsigned long storeArr[4] = {0};
        int metaData[3]  = {0};
        while(1){
            int nLen = 0;
            int type  =0 ;
            int seat = 0;
            sbuf.clear();
            memset(storeArr,0,sizeof(storeArr));
            memset(metaData,0,sizeof(metaData));
            bResult = ReadFile(hFile,&metaData,sizeof(metaData) , &nBytesRead, 0);
            if (bResult &&  nBytesRead == 0)
                break;
            nLen = metaData[0];
            type = metaData[1];
            seat = metaData[2];
            cout << "nlen:" << nLen << "," << type<< "," << seat <<endl;
            ReadFile(hFile,storeArr,nLen * sizeof(unsigned long ) ,&nBytesRead,0);
            if (bResult &&  nBytesRead == 0)
                break;
            int needBytesLen =  nLen > 3 ? 98 : nLen * 28;
            cout << "needBytesLen:" <<  needBytesLen << endl;
            restoreData *  pData = (restoreData *)malloc(sizeof(restoreData) + needBytesLen);
            memset(pData->buf,0,needBytesLen);
            memset(pData->handCards,0,14*sizeof(char));
            for(int i = 0 ; i < nLen; ++i){
                if(3 == i){
                    bitset<14> bs14(storeArr[i]);
                    sbuf.append(bs14.to_string());
                }
                else{
                    bitset<28> bs28(storeArr[i]);
                    sbuf.append(bs28.to_string());
                }
            }
            memcpy(pData->buf,sbuf.c_str(),needBytesLen);
            for(int i = 0 ; i < needBytesLen / 7 ; ++i){
                bitset<7> bs(sbuf.substr(i*7,7))  ;
                pData->handCards[i] = (char)bs.to_ulong();
                cout << (int)pData->handCards[i]  << " ";
            }
            m_restoreList.push_back(pData);
            cout << endl;
        }
    }
    void readStreamBin(const std::string & filepath){
        DWORD nBytesRead;
        BOOL bResult;
        HANDLE hFile = CreateFileA(filepath.c_str(),GENERIC_READ,
                                   FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,
                                   NULL);
        if(hFile == INVALID_HANDLE_VALUE)
            return;
        std::string sbuf;
        while(1){
            int nLen = 0;
            int type  =0 ;
            int seat = 0;
            sbuf.clear();
            bResult = ReadFile(hFile,&nLen,sizeof(nLen) , &nBytesRead, 0);
            if (bResult &&  nBytesRead == 0)
                break;
            bResult = ReadFile(hFile,&type,sizeof(type) , &nBytesRead, 0);
            if (bResult &&  nBytesRead == 0)
                break;
            bResult = ReadFile(hFile,&seat,sizeof(seat) , &nBytesRead, 0);
            if (bResult &&  nBytesRead == 0)
                break;
            restoreData *  pData = (restoreData *)malloc(sizeof(restoreData) + nLen);
            memset(pData->buf,0,nLen);
            memset(pData->handCards,0,14*sizeof(char));
            pData->nLen = nLen;
            pData->type = type;
            pData->seat = seat;
            bResult = ReadFile(hFile,pData->buf,nLen,&nBytesRead,0);
            if (bResult &&  nBytesRead == 0)
                break;
            sbuf.assign(pData->buf , nLen);
            cout << sbuf << endl;
            for(int i = 0 ; i < nLen / 7 ; ++i){
                bitset<7> bis(sbuf.substr(i * 7, 7));
                pData->handCards[i] = bis.to_ulong();
                cout << (int)pData->handCards[i] << " ";
            }
            cout << endl;
            m_restoreList.push_back(pData);
        }
    }
    std::string findFile(const char * key){
        char filepath[MAX_PATH] = {0};
        memcpy(filepath , cur_dir_name.c_str(),cur_dir_name.size());
        sprintf_s(filepath+ cur_dir_name.size(), MAX_PATH-cur_dir_name.size(),
                  "/*%s*",key);
        WIN32_FIND_DATAA FindFileData;
        HANDLE hFind;
        hFind = FindFirstFileA(filepath,&FindFileData);
        if(hFind == INVALID_HANDLE_VALUE)
            return "";
        FindClose(hFind);

        return   cur_dir_name  + "/"+ string(FindFileData.cFileName);
    }
    virtual unsigned int __prepareCloseFileEachTime__(){
        std::string filepath;
        bool bInsert_ok = false;
        std::string errmsg;
        while(true){
            bInsert_ok = false;
            WaitForSingleObject(hSem,INFINITE);
            EnterCriticalSection(&prepare_cs);
            if(bStopPrepare){
                LeaveCriticalSection(&prepare_cs);
                break;
            }
            storeData data = std::move(prepare_queue.front());
            prepare_queue.pop_front();
            LeaveCriticalSection(&prepare_cs);
            EnterCriticalSection(&write_cs);
            auto iter_find = write_map.find(data.key);
            auto iter_end = write_map.end();
            if(iter_find == iter_end){
                filepath = getFileName(data.key.c_str());
                FileHandleData fileInfo;
                fileInfo.filepath = filepath;
                fileInfo.inUse = false;
                bInsert_ok = write_map.insert(std::make_pair(data.key,fileInfo)).second;
                if(bInsert_ok){
                    write_queue.push_back(std::move(data));
                    LeaveCriticalSection(&write_cs);
                    WakeConditionVariable(&write_cond);
                }
                else{
                    LeaveCriticalSection(&write_cs);
                    errmsg =  __FUNCTION__;
                    errmsg += " insert " + data.key + " failed\r\n";
                    log_error(errmsg);
                }
            }
            else{
                write_queue.push_back(std::move(data));
                LeaveCriticalSection(&write_cs);
                WakeConditionVariable(&write_cond);
            }
        }
        return 0;
    }
    virtual unsigned int __processCloseFileEachTime__(){
        std::string errmsg;
        bool bFind = false;
        std::string filepath;
        DWORD lastError = 0;
        DWORD dwWriten = 0;
        bool hasError = false;
        int totalSize = 0;
        static ostringstream oss;
        static const int bufLen = sizeof(int) * 3+ (98 * sizeof(char) );
        static char buf[bufLen] = {0};
        while(true){
            bFind = false;
            hasError = false;
            oss.clear();
            oss.str("");
            EnterCriticalSection(&write_cs);
            while(!bStopProcess && write_queue.empty()){
                SleepConditionVariableCS(&write_cond,&write_cs,INFINITE);
            }
            if(bStopProcess){
                LeaveCriticalSection(&write_cs);
                break;
            }
            storeData data = std::move(write_queue.front());
            write_queue.pop_front();
            auto iter_find  = write_map.find(data.key);
            bFind = (iter_find != write_map.end());
            if(!bFind){
                LeaveCriticalSection(&write_cs);
                errmsg = __FUNCTION__;
                errmsg += " write_map find error\r\n";
                log_error(errmsg);
                continue;
            }
            volatile bool * pInUse = &iter_find->second.inUse;
            if(*pInUse == true){
                write_queue.push_back(std::move(data));
                LeaveCriticalSection(&write_cs);
                WakeConditionVariable(&write_cond);
                continue;
            }
            *pInUse = true;
            filepath = iter_find->second.filepath;
            LeaveCriticalSection(&write_cs);
            HANDLE hFile = CreateFileA(filepath.c_str(),GENERIC_READ|GENERIC_WRITE,
                                      FILE_SHARE_READ,0,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,
                                      NULL);
            if(hFile != INVALID_HANDLE_VALUE){
                setAppendFileHandle(hFile);
                totalSize = 0 ;
                if(WriteModeStream == m_writeMode)
                   totalSize = transferDataToBin(buf,bufLen,oss,data);
                else {
                    totalSize = transferDataToLong(buf,bufLen, oss,data);
                }
                cout << "total : " << totalSize << endl;
                if(WriteFile(hFile,buf,totalSize,&dwWriten,0)){
                    FlushFileBuffers(hFile);
                    CloseHandle(hFile);
                }
                else{
                    lastError = GetLastError();
                    hasError  = true;
                }
            }
            else{
                lastError = GetLastError();
                hasError = true;
            }
            EnterCriticalSection(&write_cs);
            *pInUse = false;
            LeaveCriticalSection(&write_cs);
            if(hasError){
                errmsg = ErrorInfo::getError(lastError);
                errmsg += "\r\n";
                log_error(errmsg);
            }
        }
        return 0;
    }
    int transferDataToLong(char * target_buf, int target_buf_len , std::ostringstream &transferStream, const storeData & data){
        if(NULL == target_buf || 0 == target_buf_len){
            return 0;
        }
        transferStream.clear();
        transferStream.str("");
        memset(target_buf,0,target_buf_len);
        int nDataLen = data.data.size();
        for(int i  = 0 ;  i < nDataLen ; ++i){
            bitset<7> bs(data.data[i]);
            transferStream << bs.to_string();
        }
        std::string str = transferStream.str();
        cout << "trase:" << transferStream.str() << ", size:" << transferStream.str().size() << endl;
        int needLongCount = 1;
        int nLen = transferStream.str().size();
        if(nLen <= 28)
            needLongCount = 1;
        else if(nLen / 28 >= 1)
            needLongCount += nLen / 28;
        cout << "long count :" << needLongCount << endl;
        int seat = data.seat;
        int type = data.type;
        char * pbuf = target_buf;
        memcpy(pbuf,&needLongCount,sizeof(needLongCount));
        pbuf+= sizeof(needLongCount);
        memcpy(pbuf,&type,sizeof(type));
        pbuf += sizeof(type);
        memcpy(pbuf, &seat , sizeof(seat));
        pbuf += sizeof(seat);
        unsigned long bit_long;
        for(int i = 0; i < needLongCount ; ++i){
            if( 3== i){
                bitset<14> bs(str.substr(i*28,14));
                bit_long = bs.to_ulong();
                memcpy(pbuf, &bit_long , sizeof(bit_long));
                cout << "long:" << bs.to_ulong() << ",str:" << bs.to_string()  << ",size:" <<  bs.to_string().size()<< endl;
            }
            else{
                bitset<28> bs(str.substr(i*28,28));
                bit_long = bs.to_ulong();
                memcpy(pbuf, &bit_long , sizeof(bit_long));
                pbuf+= sizeof(bit_long);
                cout << "long : " << bs.to_ulong() << ", str:" << bs.to_string() << ",size:" <<  bs.to_string().size() << endl;
            }
            cout << endl;
        }
        cout << (target_buf - pbuf)<< endl;
        int totalSize =  sizeof(type) + sizeof(needLongCount) + sizeof(seat) + needLongCount * sizeof(unsigned long);
        cout << "total: " << totalSize << endl;
        return totalSize;
    }
    int transferDataToBin(char * target_buf, int target_buf_len , std::ostringstream &transferStream, const storeData & data){
        if(NULL == target_buf || 0 == target_buf_len){
            return 0;
        }
        transferStream.clear();
        transferStream.str("");
        memset(target_buf,0,target_buf_len);
        int nDataLen = data.data.size();
        for(int i  = 0 ;  i < nDataLen ; ++i){
            bitset<7> bs(data.data[i]);
            transferStream << bs.to_string();
        }
        int seat = data.seat;
        int type = data.type;
        int nLen = transferStream.str().size();
        char * pbuf = target_buf;
        memcpy(pbuf,&nLen,sizeof(nLen));
        pbuf+= sizeof(nLen);
        memcpy(pbuf,&type,sizeof(type));
        pbuf += sizeof(type);
        memcpy(pbuf, &seat , sizeof(seat));
        pbuf += sizeof(seat);
        memcpy(pbuf,transferStream.str().c_str(),nLen);
        return sizeof(seat) + sizeof(type) + sizeof(nLen) + nLen * sizeof(char);
    }

    virtual unsigned int __prepareOpenFileMode__(){
        bool bFind = false;
        std::string filepath;
        bool bInsert_ok = false;
        std::string errmsg;
        DWORD errorNo =0;
        while(1){
            bFind = false;
            bInsert_ok = false;
            WaitForSingleObject(hSem,INFINITE);
            EnterCriticalSection(&prepare_cs);
            if(bStopPrepare){
                LeaveCriticalSection(&prepare_cs);
                break;
            }
            storeData data = std::move(prepare_queue.front());
            prepare_queue.pop_front();
            LeaveCriticalSection(&prepare_cs);
            EnterCriticalSection(&write_cs);
            auto iter = write_map.find(data.key);
            if(iter != write_map.end()){
                bFind = true;
            }
            if(!bFind){
                filepath = getFileName(data.key.c_str());
                HANDLE hFile = CreateFileA(filepath.c_str(),GENERIC_READ|GENERIC_WRITE,
                                                      FILE_SHARE_READ,0,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,
                                                      NULL);
                if(hFile != INVALID_HANDLE_VALUE){
                    FileHandleData fileinfo;
                    fileinfo.hFile = hFile;
                    fileinfo.filepath = filepath;
                    fileinfo.inUse = false;
                    bInsert_ok = write_map.insert(make_pair(data.key , fileinfo)).second;
                    if(bInsert_ok){
                        write_queue.push_back(std::move(data));
                        LeaveCriticalSection(&write_cs);
                        WakeConditionVariable(&write_cond);
                    }
                    else{
                        LeaveCriticalSection(&write_cs);
                        errmsg = __FUNCTION__;
                        errmsg += " write_map insert failed \r\n";
                        log_error(errmsg);
                    }
                }
                else{
                    errorNo = GetLastError();
                    LeaveCriticalSection(&write_cs);
                    errmsg = ErrorInfo::getError(errorNo);
                    log_error(errmsg);
                }
            }
            else{
                write_queue.push_back(std::move(data));
                LeaveCriticalSection(&write_cs);
                WakeConditionVariable(&write_cond);
            }
        }
        return 0;
    }
    virtual unsigned int __processOpenFileMode__(){
        bool bFind = false;
        std::string errmsg;
        DWORD errorNo = 0;
        DWORD dwWriten = 0;
        bool hasError = false;
        int totalSize = 0;
        static ostringstream oss;
        static const int bufLen = sizeof(int) *3+ 98 * sizeof(char) ;
        static char buf[bufLen] = {0};
        while (true) {
            bFind = false;
            hasError = false;
            EnterCriticalSection(&write_cs);
            while(!bStopProcess && write_queue.empty()){
                SleepConditionVariableCS(&write_cond,&write_cs,INFINITE);
            }
            if(bStopProcess){
                LeaveCriticalSection(&write_cs);
                break;
            }
            storeData data = std::move(write_queue.front());
            write_queue.pop_front();
            auto iter = write_map.find(data.key);
            if(iter != write_map.end())
                bFind = true;
            if(!bFind){
                LeaveCriticalSection(&write_cs);
                errmsg = __FUNCTION__;
                errmsg += " write_map find error \r\n";
                log_error(errmsg);
                continue;
            }
            if(iter->second.inUse){
                write_queue.push_back(std::move(data));
                LeaveCriticalSection(&write_cs);
                WakeConditionVariable(&write_cond);
                continue;
            }
            volatile bool *pInUse = &iter->second.inUse;
            *pInUse = true;
            HANDLE hFile = iter->second.hFile;
            LeaveCriticalSection(&write_cs);

            if( INVALID_HANDLE_VALUE == hFile){
                errmsg = __FUNCTION__;
                errmsg += " hFile : INVALID_HANDLE_VALUE\r\n";
                log_error(errmsg);
                continue;
            }
            totalSize = 0;
            if(RecordFile::WriteModeStream == m_writeMode)
                totalSize = transferDataToBin(buf,bufLen,oss,data);
            else {
                totalSize = transferDataToLong(buf,bufLen ,oss,data);
            }
            if(WriteFile(hFile,buf, totalSize,&dwWriten,0)){
                FlushFileBuffers(hFile);
            }
            else{
                hasError= true;
                errorNo = GetLastError();
            }
            EnterCriticalSection(&write_cs);
            *pInUse = false;
            LeaveCriticalSection(&write_cs);
            if(hasError){
                errmsg = __FUNCTION__;
                errmsg += ErrorInfo::getError(errorNo);
                errmsg += "\r\n";
                log_error(errmsg);
            }
        }
        return 0;
    }
private:
    RecordFile(const RecordFile&);
    RecordFile& operator=(const RecordFile &);
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章