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是监控模块的回调函数,自定义文件处理。
阅读全文
0 0
- linux下c++实现文件监控
- Linux下使用inotify实现文件监控
- C#实现实时监控文件目录下的变化
- Linux下使用inotify实现对文件的监控
- Linux 下监控文件自动实现swoole framework热更新
- Linux下C语言实现文件复制
- 多线程实现文件拷贝(Linux下C++)
- Linux下C语言实现文件拷贝
- linux下C语言实现文件复制
- linux下包监控程序[C语言]
- linux下c语言实现搜索根目录下所有文件
- Linux下使用inotify监控文件动作
- Linux下使用inotify监控文件动作
- linux下使用inotify监控文件变化
- Linux下使用inotify监控文件动作
- Linux下使用mjpg-streamer实现监控
- linux下实现监控进程网络带宽
- netlink+kprobe实现linux下进程监控
- 什么是Punycode-
- hashCode()、equals()以及compareTo()方法的理解 (整理)
- lua解析json
- hdu1075
- 操作系统-进程和线程管理
- linux下c++实现文件监控
- 4. Median of Two Sorted Arrays
- WIN10如何设置默认便签应用
- 稳定排序和不稳定排序
- 阿里巴巴2018秋招在线编程测验--射击场
- NOIP2016原题终结测试(2017081801)
- 推荐给初入web前端几种常用的设计框架
- 深入学习js之浅谈对象(对象的常见特性)
- C++ 将int转换为string的两种方法【to_string和sstream】