/////////////////////////H////////////////////////////
#ifndef LGLIB_DIRMONITOR_H
#define LGLIB_DIRMONITOR_H
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <string>
#include <queue>
#include "Lg_Tread.h"
#include "lg_MultiEvent.h"
#include "lg_LoopBuffer.h"
using namespace std;
//using namespace lglib;
#define BYBUF 1024
#define BUFSIZE 10240
namespace lglib
{
//缓冲块标志
class Watch_tag
{
public:
Watch_tag(HANDLE h, int sisz=BUFSIZE);
~Watch_tag();
BOOL GetChangeInfo();
BOOL IsEnd();
BOOL IsInvoke();
string GetCurrentString();
uint32 GetAction();
Watch_tag& operator++();
private:
HANDLE m_hDir;
FILE_NOTIFY_INFORMATION* fni;
char* m_pstr;
int32 offset;
uint32 m_len;
uint32 m_Action;
BOOL m_bIsInvoke;
BOOL m_bSucceed;
};
class lg_DirMonitor;
class lg_DirWatch : public lg_Thread
{
public:
lg_DirWatch();
virtual ~lg_DirWatch();
BOOL Init(string path,lg_DirMonitor* pMo);
void Release();
void run();
private:
Watch_tag* m_pWatch;
HANDLE m_hDir;
string m_path;
BOOL m_bIsInited;
lg_DirMonitor* m_pMonitor;
};
class lg_DirMonitor : public lg_Thread
{
public:
lg_DirMonitor(string strDirName);
virtual ~lg_DirMonitor();
BOOL Init();
void run();
void Save();
void SetData(Watch_tag* p);
private:
typedef queue<Watch_tag*> QList;
int CopyToBuffer(const string head,string content,const uint32 SerNum);
enum Dir_Event
{
Exit = 0,
ProcessData,
EndPos
};
string m_strMoniDir;
BOOL m_bIsInited;
lg_DirWatch w1;
lg_Mutex m_Mutex;
QList m_Queue;
lg_MultiEvent *m_MultiEvent;
lg_LoopBuffer * m_LoopBuf;
};
}
#endif //LGLIB_DIRMONITOR_H
///////////////////////////CPP/////////////////////////
#include "stdafx.h"
#include "DirMonitor.h"
#include "lg_Exception.h"
//使用VC6的时候注意:在winbase.h前面定义#define _WIN32_WINNT 0x0500
//否则无法通过编译
#include <winbase.h>
#include <io.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
namespace lglib
{
/************************************************************************/
/* Watch_tag实现 */
/************************************************************************/
Watch_tag::Watch_tag(HANDLE hdl, int size)
: m_hDir(hdl),m_len(size),offset(-1),fni(NULL),m_bIsInvoke(FALSE),m_Action(0),m_bSucceed(FALSE)
{
m_pstr = new char[size];
}
Watch_tag::~Watch_tag()
{
delete [] m_pstr;
}
BOOL Watch_tag::GetChangeInfo()
{
if(m_bIsInvoke)
throw lg_Exception("Watch_tag::GetChangeInfo()","重复调用Watch_tag::GetChangeInfo()",0x00000001);
m_bIsInvoke = TRUE;
m_bSucceed = ReadDirectoryChangesW(
m_hDir,
m_pstr,
BUFSIZE,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME |
FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_CREATION |
FILE_NOTIFY_CHANGE_SIZE,
&m_len,
NULL,
NULL);
if(m_bSucceed){
fni=(FILE_NOTIFY_INFORMATION*)m_pstr;
}
return m_bSucceed;
}
BOOL Watch_tag::IsEnd()
{
if(!m_bIsInvoke)
throw lg_Exception("Watch_tag::IsEnd()","没有调用Watch_tag::GetChangeInfo()",0x00000002);
if(!m_bSucceed)
throw lg_Exception("Watch_tag::IsEnd()","调用Watch_tag::GetChangeInfo()失败",0x00000003);
if(offset == -1)
return FALSE;
return offset<=0;
}
BOOL Watch_tag::IsInvoke()
{
return m_bIsInvoke;
}
string Watch_tag::GetCurrentString()
{
if(!m_bIsInvoke)
throw lg_Exception("Watch_tag::GetCurrentString()","没有调用Watch_tag::GetChangeInfo()",0x00000004);
if(!m_bSucceed)
throw lg_Exception("Watch_tag::GetCurrentString()","调用Watch_tag::GetChangeInfo()失败",0x00000005);
WCHAR wcFileName[BYBUF] = {0};
memcpy( wcFileName, fni->FileName, fni->FileNameLength );
char cFileName[BYBUF];
WideCharToMultiByte( CP_ACP, 0, wcFileName, -1, cFileName, BYBUF, NULL, NULL );
string temp = cFileName;
return temp;
}
uint32 Watch_tag::GetAction()
{
if(!m_bIsInvoke)
throw lg_Exception("Watch_tag::GetAction()","没有调用Watch_tag::GetChangeInfo()",0x00000006);
if(!m_bSucceed)
throw lg_Exception("Watch_tag::GetAction()","调用Watch_tag::GetChangeInfo()失败",0x00000007);
return fni->Action;
}
Watch_tag& Watch_tag::operator ++()
{
if(!m_bIsInvoke)
throw lg_Exception("Watch_tag::operator ++","没有调用Watch_tag::GetChangeInfo()",0x00000008);
if(!m_bSucceed)
throw lg_Exception("Watch_tag::operator ++","调用Watch_tag::GetChangeInfo()失败",0x00000009);
offset = fni->NextEntryOffset;
fni=(PFILE_NOTIFY_INFORMATION)((uint8*)fni + offset);
return *this;
}
/************************************************************************/
/* lg_DirMonitor实现 */
/************************************************************************/
lg_DirMonitor::lg_DirMonitor(string strDirName)
: m_strMoniDir(strDirName),m_bIsInited(FALSE),m_MultiEvent(NULL),m_LoopBuf(NULL)
{
lg_Thread::setThreadName("lg_DirMonitor");
}
lg_DirMonitor::~lg_DirMonitor()
{
w1.Release();
if(m_MultiEvent)
m_MultiEvent->set(Exit);
if(m_bIsInited)
quit();
for(int i = 0;i < m_Queue.size();i++)
{
delete m_Queue.front();
}
m_Queue.empty();
Sleep(1);
if(m_MultiEvent)
{
delete m_MultiEvent;
m_MultiEvent = NULL;
}
if(m_LoopBuf)
{
delete m_LoopBuf;
m_LoopBuf = NULL;
}
}
void lg_DirMonitor::Save()
{
CString Filename;
Filename.Format("d:\\FileRec.txt");
m_LoopBuf->Save(Filename.GetBuffer(0));
}
void lg_DirMonitor::SetData(Watch_tag* p)
{
m_Mutex.lock(__FILE__,__LINE__);
m_Queue.push(p);
m_Mutex.unlock(__FILE__,__LINE__);
m_MultiEvent->set(ProcessData);
}
BOOL lg_DirMonitor::Init()
{
m_MultiEvent = new lg_MultiEvent(EndPos);
m_LoopBuf = new lg_LoopBuffer;
m_LoopBuf->InitBuffer(1024000);
m_bIsInited = TRUE;
start();
w1.Init(m_strMoniDir,this);
return TRUE;
}
int lg_DirMonitor::CopyToBuffer(const string head,string content,const uint32 SerNum)
{
char Output[1024];
sprintf(Output,"%s<%s><%ld>\r\n",head.c_str(),content.c_str(),SerNum);
return m_LoopBuf->WriteBuffer(reinterpret_cast<uint8*>(Output),strlen(Output));
}
void lg_DirMonitor::run()
{
uint32 dwFileModify = 0;
uint32 dwFileAdd = 0;
uint32 dwFileRemove = 0;
while(isCanLoop())
{
//从列表中取出数据
Dir_Event Event = (Dir_Event)m_MultiEvent->wait();
switch(Event)
{
case Exit:
LGTRACE(Output_Console,"收到退出信号");
return;
break;
case ProcessData:
m_MultiEvent->reset(ProcessData);
uint32 count = m_Queue.size();
for(int32 i = 0;i < count;i++)
{
Watch_tag* p = m_Queue.front();
while(!p->IsEnd())
{
switch(p->GetAction())
{
case FILE_ACTION_MODIFIED:
{
string temp = p->GetCurrentString();
int Ret = CopyToBuffer("ModifyFile:",temp,++dwFileModify);
}
break;
case FILE_ACTION_ADDED:
{
string temp = p->GetCurrentString();
int Ret = CopyToBuffer("AddFile:",temp,++dwFileAdd);
}
break;
case FILE_ACTION_REMOVED:
{
string temp = p->GetCurrentString();
int Ret = CopyToBuffer("RemoveFile:",temp,++dwFileRemove);
}
break;
}
++(*p);
}
m_Mutex.lock(__FILE__,__LINE__);
m_Queue.pop();
m_Mutex.unlock(__FILE__,__LINE__);
delete p;
}
}
Sleep(1);
}
LGTRACE(Output_Console,"正常退出");
}
/************************************************************************/
/* lg_DirWatch实现 */
/************************************************************************/
lg_DirWatch::lg_DirWatch() : m_bIsInited(FALSE),m_hDir(INVALID_HANDLE_VALUE),m_pMonitor(NULL)
{
lg_Thread::setThreadName("lg_DirWatch");
}
lg_DirWatch::~lg_DirWatch()
{
if(m_bIsInited)
quit();
if(m_pWatch)
{
delete m_pWatch;
m_pWatch = NULL;
}
}
BOOL lg_DirWatch::Init(string path,lg_DirMonitor* pMo)
{
if(INVALID_HANDLE_VALUE != m_hDir)
throw lg_Exception("lg_DirMonitor::Init()","句柄已经有效,重复初始化!",0x0000000A);
if(path.size() == 0)
throw lg_Exception("lg_DirMonitor::Init()","所提供的路径为空!",0x0000000B);
if(access(path.c_str(),0) != 0)
throw lg_Exception("lg_DirMonitor::Init()","提供的路径不存在!",0x0000000C);
m_path = path;
m_pMonitor = pMo;
m_bIsInited = TRUE;
m_hDir = CreateFile(
m_path.c_str(),
FILE_LIST_DIRECTORY,
FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
//如果FILE_FLAG_OVERLAPPED标志不使用,就不能直接CloseHandle,否则调用会挂起
FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, // file attributes
NULL);
if ( INVALID_HANDLE_VALUE == m_hDir )
{
throw lg_Exception("lg_DirMonitor::Init()","打开文件失败",0x0000000D);
}
start();
return TRUE;
}
void lg_DirWatch::Release()
{
if(INVALID_HANDLE_VALUE != m_hDir)
CloseHandle(m_hDir);
}
void lg_DirWatch::run()
{
while(isCanLoop())
{
m_pWatch = new Watch_tag(m_hDir,BUFSIZE);
if(m_pWatch->GetChangeInfo())
{
m_pMonitor->SetData(m_pWatch);
m_pWatch = NULL;
}
else
{
DWORD Err = GetLastError();
uint32 nTempSize = 2048;
char* szTemp = new char[ nTempSize ];
// 格式化错误信息
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, Err,
MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
szTemp,
nTempSize,
NULL);
TRACE("%s\n",szTemp);
delete [] szTemp;
LGTRACE(Output_Console,"lg_DirWatch遇到错误退出");
return;
}
}
LGTRACE(Output_Console,"lg_DirWatch正常退出");
}
}