linux下c++实现文件监控

来源:互联网 发布:东北大学软件工程硕士 编辑:程序博客网 时间:2024/06/01 08:07

HotSwitchDict.h

#ifndef _HOTSWITCH_DICT_H_#define _HOTSWITCH_DICT_H_#include <string>#include <pthread.h>#include <unistd.h>#include <fstream>#include <sys/stat.h>#include <iostream>#include <time.h>#include <stdint.h>using std::string;using std::cerr;using std::endl;using std::cout;namespace hsd {/** * @brief 获取当前时间 */inline string _getCurrentTime(){    time_t t = time(NULL);    /*本地时间:日期,时间 年月日,星期,时分秒*/    struct tm* c_t = localtime(&t);    char buf[20];    sprintf(buf, "%d-%d-%d %d:%d:%d", c_t->tm_year+1900, c_t->tm_mon,                     c_t->tm_mday, c_t->tm_hour, c_t->tm_min, c_t->tm_sec);    return string(buf);}template <class DictType> class HotSwitchDict;template <class DictType> void* monitorThread(void *arg){    HotSwitchDict<DictType> * pHotDict = (HotSwitchDict<DictType>*)arg;    bool needSleep = false;    uint32_t curSleepTime = 0;        // 检测是否需要停止检测    while( !pHotDict->m_stopMonitor )    {        if( needSleep ) {            if( curSleepTime++ < pHotDict->m_sleepTime ) {                sleep(1);                continue;            }            else {                needSleep = false;                curSleepTime = 0;            }        }        // 检测pHotDict->m_pSwitchDict是否不为空 2012-08-12        // 不为空,判断是否到底备用词典的延迟生命周期        if( pHotDict->m_pSwitchDict != NULL ) {            delete pHotDict->m_pSwitchDict;            pHotDict->m_pSwitchDict = NULL;        }        // 检测新文件是否到来        if(pHotDict->isNewDictArrived())        {            // 构造新的DictType类型指针            pHotDict->m_pSwitchDict =                     pHotDict->newDictFunc(pHotDict->getNewDictFileName());            // 判断词典是否加载成功            if(pHotDict->m_pSwitchDict == NULL) {                cerr << "[WARNING] [" << _getCurrentTime() <<                             "] Error when load new Dictionary!" << endl;            }            else {                // 加读锁后,交换m_pCurDict和m_pSwitchDict指针                DictType * pDictTemp = pHotDict->m_pCurDict;                pthread_rwlock_wrlock(&pHotDict->m_rwLock);                pHotDict->m_pCurDict = pHotDict->m_pSwitchDict;                // 不在删除,直接将m_pSwitchDict指向原来的内存空间                // 保证指针不删除原来m_pCurDict的指针                pHotDict->m_pSwitchDict = pDictTemp;                pthread_rwlock_unlock(&pHotDict->m_rwLock);                //  delete pDictTemp;                // 修改当前内存中的词典名字                pHotDict->switchFileName();                cout << "[INFO] [" << _getCurrentTime()                          << "] New Dictionary Switched!" << endl;            }            needSleep = true;        }        else { // 继续监控            needSleep = true;        }    }  return NULL;}// 默认的词典构建对象函数template <class DictType>inline DictType * DefaultNewDictFunc(const string & fileName){    DictType * tmpDict;    try {        tmpDict = new DictType(fileName.c_str());    }    catch (int e) {        return NULL;    }    return tmpDict;}template <class DictType>class HotSwitchDict{    public:        typedef DictType* (*NewDictFunc)(const string & fileName);        // 友元函数,需要操作HotSwitchDict的private变量        friend void * monitorThread<DictType>(void * arg);        /**         * @brief HotSwitchDict 构造函数         * @param fileName 词典的文件名         * @param flagFile 词典的监控文件,保存新词典的名字和md5码         * @param sleepTime 每次词典监控的扫描时间间隔         */        HotSwitchDict(const string & fileName, const string & flagFile,                                     uint32_t sleepTime = 1)        : m_pCurDict(NULL), m_pSwitchDict(NULL), m_fileName(fileName),            m_newFileName(""), m_flagFile(flagFile), m_sleepTime(sleepTime),             m_stopMonitor(false)        {            pthread_rwlock_init(&m_rwLock, NULL);            m_lastUpdateTime = 0;            if( sleepTime < 10 || sleepTime > 3600 ) {                m_sleepTime = 3600;            }        }        /**         * @brief 初始化函数,用来初始化词典文件以及监控线程         * @ndf 初始化词典的函数指针         * @return 如果初始化不成功,返回false          */        bool init(NewDictFunc ndf)        {            this->setNewDictFunc(ndf);            m_pCurDict = newDictFunc(m_fileName);            if( m_pCurDict == NULL ) {                return false;            }            int err = pthread_create(&m_monitorThread, NULL,                                                 monitorThread<DictType>, (void*)this);            if( err != 0 ) return false;            return true;        }        /**         * @brief 销毁对象,等待监控xiancheng结束,销毁dict指针和读写锁         * todo 屏蔽继承         */        ~HotSwitchDict()         {            if( m_pCurDict != NULL )            {                m_stopMonitor = true;                // 取消线程,避免出现sleep时间过长,导致join需要大量时间                //pthread_cancel(m_monitorThread);                // 等待监控线程结束                pthread_join(m_monitorThread, NULL);                // 销毁对象                delete m_pCurDict;            }            m_pCurDict = NULL;            if( m_pSwitchDict != NULL ) {                delete m_pSwitchDict;                m_pSwitchDict = NULL;            }            // 销毁锁            pthread_rwlock_destroy(&m_rwLock);        }        /**         * @brief 获取当前dict的指针         */        DictType * getCurDict()        {            return m_pCurDict;        }        /**         * @brief 加读锁         */        int32_t rwlock_read_lock()        {            return pthread_rwlock_rdlock(&m_rwLock);        }        /**         * @brief 加写锁         */        int32_t rwlock_write_lock()        {            return pthread_rwlock_wrlock(&m_rwLock);        }        /**         * @brief 解开锁          */        int32_t rwlock_unlock()        {            return pthread_rwlock_unlock(&m_rwLock);        }    private:        HotSwitchDict() {}        /**         * @brief 根据词典文件创建新的dict指针         */        DictType * newDictFunc(const string & fileName)        {            return m_newDictFunc(fileName.c_str());        }        /**         * @brief 判断新词典文件是否存在         */        bool isNewDictArrived()        {            // 读取finish文件,得到新词典对应的文件名            if( access(m_flagFile.c_str(), F_OK|R_OK) < 0 )            {                cerr << "[WARNING] [" << _getCurrentTime() << "] flagFile "                          << m_flagFile << " not exist or not readable" << endl;                return false;            }            // 如果文件修改时间比m_lastUpdateTime大,则读取文件            struct stat buf;            if( stat(m_flagFile.c_str(), &buf) < 0 ) {                return false;            }            time_t flagFileTime = buf.st_ctime;            if( flagFileTime <= m_lastUpdateTime )            {#ifdef DEBUG                cout << "[DEBUG] flagFileTime is smaller than m_lastUpdateTime" << endl;#endif                return false;            }            std::ifstream in(m_flagFile.c_str());            if( !in.is_open() ) {                cerr << "[ERROR] [" << _getCurrentTime() << "] flagFile "                          << m_flagFile << " opened failed" << endl;                return false;            }            string newfileName;            in >> newfileName;            in.close();            // 判定新文件名是否发生变化            if( newfileName == m_fileName ) {#ifdef DEBUG                cout << "[DEBUG] newfileName == m_fileName" << endl;#endif                return false;            }            // 判断新文件是否存在,使用绝对路径            if( access(newfileName.c_str(), F_OK|R_OK) < 0 )            {                cerr << "[WARN] [" << _getCurrentTime() << "] newfileName "                          << newfileName << " not exist or not readable" << endl;                return false;            }            // 保存md5码,并进行验证            m_newFileName = newfileName;            m_lastUpdateTime = flagFileTime;#ifdef DEBUG            cout << "[DEBUG] [" << _getCurrentTime() <<                      "] change m_newFileName to " << m_newFileName << endl;#endif            return true;        }        string getNewDictFileName()        {            return m_newFileName;        }        /**         * @brief 当前词典的文件名修改         */        void switchFileName()        {            m_fileName = m_newFileName;            m_newFileName = "";        }        /**         * @brief 设置从一个文件初始化DictType*类型的函数         */        void setNewDictFunc(NewDictFunc ndf)        {            m_newDictFunc = ndf;        }    private:            DictType * m_pCurDict;        DictType * m_pSwitchDict;        string m_fileName;        string m_newFileName;        string m_flagFile;        uint32_t m_sleepTime;        pthread_rwlock_t m_rwLock;        pthread_t m_monitorThread;        bool m_stopMonitor;        NewDictFunc m_newDictFunc;        time_t m_lastUpdateTime;};}#endif // _HOTSWITCH_DICT_H_

main.cpp

#include "HotSwitchDict.h"#include<iostream>#include<string>#include<fstream>#include<map>using namespace std;using namespace hsd;map<string, float>* process_file(const string &file_name){    char s[1000];    map<string, float> *fea_map;    fea_map = new map<string, float>;    fstream f(file_name.c_str());    f.getline(s, 1000);    cout<<s<<endl;    f.close();    return fea_map;}int main(){    string f_name, flag_file;    f_name = "./data/dict.dat";    flag_file = "./data/dict.dat.md5";    map<string, float>* (*fun)(const string & fileName);    HotSwitchDict< map<string, float> > hs(f_name, flag_file, 3);    fun = process_file;    hs.init(fun);    int i = 0;    while(1);                                                                                               return 1;}

使用方法:
1. 将需要监控的文件路径包括文件名写入flag_file,f_name是实际需要读取的文件。
2. 更新f_name之后,同时更新flag_file中的内容。
3. process_file是监控模块的回调函数,自定义文件处理。

原创粉丝点击