文件监控(二) 代码
文件監(jiān)控(二) 代碼 ,目前監(jiān)控只支持WINDOWS
//①開始監(jiān)控目錄
// ?將監(jiān)控到的文件放入list
void* ThreadWatcher(void* pParam)
{
dzlog_notice("[線程開啟]開始監(jiān)控目錄 ThreadWatcher ?PID : 0x%x ?GetLastError(%s)", pthread_self().p, GetLastErrorInfo());
Cwx_kk_upDlg * dlg = (Cwx_kk_upDlg*)pParam;
char notify[4096]={0};?
DWORD cbBytes = 0;?
TCHAR errorInfo[TF_MAX_PATH_LEN]={0};
FILE_NOTIFY_INFORMATION *pNotify=(FILE_NOTIFY_INFORMATION *)notify;
// **** 重要 ****
// *** ?在CreateFile時指定FILE_FLAG_OVERLAPPED標志 \
ReadDirectoryChangesW時使用lpOverlapped參數(shù)
OVERLAPPED ov;//通知線程退出 ReadDirectoryChangesW
memset(&ov, 0, sizeof(ov));
? ? ov.hEvent = CreateEvent(NULL, false, NULL, NULL);
// GetCurrentDirectory(MAX_PATH,path.GetBuffer(MAX_PATH+1));
CString str;
WCHAR ?wcFileName[TF_MAX_PATH_LEN]={0};
DWORD dwFileNameLength ;
bool bDeleteFileName = true;
char psTemp[TF_MAX_PATH_LEN]={0};
long lRet;
// SetEvent(eventStarted);//release signal
while (TRUE)?
{?
if(m_ExitCode==1)
goto end;
char *cFileName = new char[TF_MAX_PATH_LEN];
memset(cFileName, 0 , TF_MAX_PATH_LEN);
memset(wcFileName, 0 , TF_MAX_PATH_LEN);
bDeleteFileName = true;
//for (i=0;i<numDirs;i++)
lRet = ReadDirectoryChangesW( dlg->kkConfig.hDir, ¬ify, sizeof(notify),
true, FILE_NOTIFY_CHANGE_LAST_WRITE,?
&cbBytes,0, NULL);
if(lRet)
{?
memcpy( wcFileName, pNotify->FileName, pNotify->FileNameLength );
WideCharToMultiByte( CP_ACP, 0, wcFileName, -1, cFileName, TF_MAX_PATH_LEN, NULL, NULL );
sprintf( psTemp, "%s/%s", dlg->kkConfig.ftpPath, cFileName );
if(FileUtil::FindFirstFileExists( psTemp, FILE_ATTRIBUTE_DIRECTORY))
continue;
switch(pNotify->Action)?
{?
case FILE_ACTION_ADDED:?
str.Format("Directory/File added - %s",cFileName);
break;?
case FILE_ACTION_REMOVED:
str.Format("Directory/File removed - %s",cFileName);
break;?
case FILE_ACTION_MODIFIED:?
// WaitForSingleObject(hMutex,-1);//waiting
dlg->m_images.push( cFileName );
// ReleaseMutex(hMutex);//release?
str.Format("Directory/File modified - %s",cFileName);
bDeleteFileName = false;
break;?
case FILE_ACTION_RENAMED_OLD_NAME:?
str.Format("Directory/File rename - %s",cFileName);
break;?
case FILE_ACTION_RENAMED_NEW_NAME:?
str.Format("Directory/File new name - %s",cFileName);
break;?
default:?
break;?
}?
}
dzlog_notice(str);
if(bDeleteFileName)
delete cFileName;
}
end:
sprintf(errorInfo, "[線程退出]開始監(jiān)控目錄 ThreadWatcher ?PID : 0x%x ?GetLastError(%s)", pthread_self().p, GetLastErrorInfo());
dzlog_notice("%s",errorInfo);
CloseHandle(dlg->kkConfig.hDir);
pthread_exit(errorInfo);
return 0;
}
//通過圖片名稱獲取車牌等信息
long ?ParseVehicleFromPicture(KKConfig kkConfig, char *imagePath, VehicleInfo &vehicleInfo)
{
// 圖片的命名為: 時間_車牌_號牌種類_車牌顏色_車輛速度.bmp
// 如: 2014-05-04_16.35.48_京N56Y22_02_2_0.bmp" ? "2014-05-04_16.35.48_京N56Y22_02_2_0_moreInfo.bmp"
//根據(jù)圖片名稱獲取圖片的時間信息, FORMAT ?日期時間_車牌_車牌顏色_車速_違章類型 eg: 2014-1-4_15.02.18_location.jpg
char fileName[256]={0};
long lTime=0;
sprintf( fileName, "%s", (strrchr(imagePath,'\\')+1) );
//fileName 0x0aa8f6f8 "20140504162515_京N56Y22_02_2_0.bmp" char [256]
char *p = strstr(fileName, "_");
char *pre=0;
char DateTime[32]={0};
char *pDateTime = DateTime;
try{
// Date
memcpy( pDateTime, fileName, p-fileName);
pDateTime += (p-fileName);
*pDateTime = ' ';
pDateTime ++;
//Time
pre = p+1;
p = strstr(pre, "_");
memcpy( pDateTime, pre, p-pre);
pre = pDateTime;
while( *pre!='\0'){
if( *pre == '.')
*pre = ':';
pre++;
}
}catch(...){
dzlog_error("解析[日期時間失敗:%s]", fileName);
}
//plate
char plate[32]={0};
try{
pre = p+1;
p = strstr(pre, "_");
memcpy(plate, pre, p-pre);
}catch(...){
dzlog_error("解析[號牌失敗:%s]", fileName);
}
//hpzl 號牌種類
char hpzl[8]={0};
try{
pre = p+1;
p = strstr(pre, "_");
memcpy(hpzl, pre, p-pre);
}catch(...){
dzlog_error("解析[號牌種類失敗:%s]", fileName);
}
//車牌顏色
char hpys[8]={0};
try{
pre = p+1;
p = strstr(pre, "_");
memcpy(hpys, pre, p-pre);
}catch(...){
dzlog_error("解析[車牌顏色失敗:%s]", fileName);
}
// ==================================================
// VehicleInfo *vehicleInfo = new VehicleInfo();
vehicleInfo.cdh = 1;//車道號
sprintf(vehicleInfo.kkbh, kkConfig.id);//卡口編號
sprintf(vehicleInfo.fxlx, kkConfig.direction);//方向類型
sprintf(vehicleInfo.hphm, plate ); //車牌 無牌、未識別、無法識別均用半角“-”表示,其中無號牌要注意hpzl填41
sprintf(vehicleInfo.hpzl, hpzl );//號牌種類 參考GA24.7(如01-大型汽車,02-小型汽車,25-農(nóng)機號牌,41-無號牌,42-假號牌,99-其他號牌),不能為空;
sprintf(vehicleInfo.hpys, hpys );//號牌顏色 0-白色,1-黃色,2-藍色,3-黑色,4-綠色,9-其它顏色,不能為空
sprintf(vehicleInfo.gcsj, DateTime ); //過車時間,e.g: "2003-09-11 11:07:23"
vehicleInfo.clsd = 0;//車輛速度 最長3位,單位:公里/小時
vehicleInfo.clxs = kkConfig.cdSpeedLimit;//車輛限速 最長3位,單位:公里/小時
sprintf(vehicleInfo.wfdm, "1"); //違章類型 ?違章行為編碼 參考GA408.1
vehicleInfo.cwkc = 0;//車外廓長 最長5位,以厘米為單位
sprintf(vehicleInfo.cllx, "K33");//車輛類型 參考GA24.4(K11-大型普通客車,K21-中型普通客車,K31-小型普通客車,K33-轎車,H11-重型普通客車,H21-中型普通客車,M22-輕便二輪摩托車)
sprintf(vehicleInfo.fzhphm, "-");//輔助號牌號碼 無牌、未識別、無法識別均用半角“-”表示,其中無號牌要注意hpzl填41
sprintf(vehicleInfo.csys, "-");//車身顏色
sprintf(vehicleInfo.tplj,"%s/", kkConfig.httpPath);//通行圖片路徑 ?固定部分
sprintf(vehicleInfo.tp1, "%s",imagePath);//通行圖片1 ?變化的部分
return 1;
}
//②處理監(jiān)控到的數(shù)據(jù)
// ?獲取車牌等信息、檢查數(shù)據(jù)庫中是否存在該圖片,若存在則繼續(xù)處理下一個,若不存在則復制圖片從ftp到http,寫入數(shù)據(jù)庫,刪除ftp下的文件
void* ThreadProcessWatchedFiles(void* pParam)
{
dzlog_notice("[線程開啟]處理監(jiān)控到的數(shù)據(jù) ThreadProcessWatchedFiles ?PID : 0x%x ?GetLastError(%s)", pthread_self().p, GetLastErrorInfo());
Cwx_kk_upDlg * dlg = (Cwx_kk_upDlg*)pParam;
TCHAR errorInfo[TF_MAX_PATH_LEN]={0};
char *imagePath = 0;
char ftpFilePath[512]={0};
char ftpPlateFilePath[512]={0};
char httpFilePath[512]={0};
char httpPlateFilePath[512]={0};
bool bExist = false;
char temp[512]={0};
long lRet=0;
char errorValue[512]={0};
VehicleInfo vehicleInfo={0};
TFDB db;
while(true){
if(m_ExitCode==1)
goto end;
if(dlg->m_images.size()<1){
dlg->GetDlgItem( IDC_STATUS )->SetWindowText("空閑等待");
Sleep(10);
continue;
}
sprintf(temp, "正在處理文件隊列,剩余文件數(shù)量: %d ", dlg->m_images.size() );
dlg->GetDlgItem( IDC_STATUS )->SetWindowText(temp);
if(dlg->m_images.empty())
continue;
imagePath = dlg->m_images.front();
dlg->m_images.pop();
if(imagePath==0)
continue;
if(strrstr(imagePath, "_plate.bmp")){
try{
delete imagePath;
}catch(...){ }
continue;
}
sprintf(ftpFilePath, "%s\\%s", dlg->kkConfig.ftpPath, imagePath);// 過車特寫圖FTP
sprintf(httpFilePath, "%s\\%s", dlg->kkConfig.httpPath, imagePath);// 過車特寫圖HTTP
sprintf(ftpPlateFilePath, "%s\\%s_plate.bmp", dlg->kkConfig.ftpPath, imagePath);// 車牌圖片F(xiàn)TP
sprintf(httpPlateFilePath, ?"%s\\%s_plate.bmp", dlg->kkConfig.httpPath, imagePath);//車牌圖片HTTP
//check is file?
if( !FileUtil::FindFirstFileExists( ftpFilePath, FILE_ATTRIBUTE_DIRECTORY) )
{
//check can access
if(_access(ftpFilePath, R_OK) == 0){
lRet = ParseVehicleFromPicture(dlg->kkConfig, imagePath, vehicleInfo);//通過圖片名稱獲取車牌等信息
if(lRet != 1)
continue;
bExist = db.CheckImageExist(imagePath);//檢查文件是否已經(jīng)分析過,不存在則寫入
if( ! bExist){
lRet = db.Add(&vehicleInfo);//寫入數(shù)據(jù)庫
if( lRet == true)
{
CopyFile:
// 過車特寫圖
lRet = FileUtil::CopyFileEx(ftpFilePath, httpFilePath, true);
if(lRet==true){
dzlog_error("Copyed file from [%s] to [%s]", ftpFilePath, httpFilePath);
DeleteFile(ftpFilePath);//處理完成后刪除FTP下的文件
}else{
dzlog_error("Copy file failed [GetLastError %s] from [%s] to [%s]", GetLastErrorInfo() , ftpFilePath, httpFilePath);
}
CopyPlateFile:
//車牌圖片
lRet = FileUtil::CopyFileEx(ftpPlateFilePath, httpPlateFilePath, true);
if(lRet==true){
dzlog_error("Copyed file from [%s] to [%s]", ftpFilePath, httpFilePath);
DeleteFile(ftpPlateFilePath);//處理完成后刪除FTP下的文件
}else{
dzlog_error("Copy file failed [GetLastError %s] from [%s] to [%s]", GetLastErrorInfo() , ftpFilePath, httpFilePath);
}
}
}else{
if(FileUtil::FindFirstFileExists( httpFilePath, false))
DeleteFile(ftpFilePath);//處理完成后刪除FTP下的文件
else
goto CopyFile;
if(FileUtil::FindFirstFileExists( httpPlateFilePath, false))
DeleteFile(ftpPlateFilePath);//處理完成后刪除FTP下的文件
else
goto CopyPlateFile;
}
// flock();
}else{
dzlog_error("cannot access file [%s] ?[GetLastError %s] ", ftpFilePath, ?GetLastErrorInfo());
}
}
try{
if(imagePath)
delete imagePath;
}catch(...){ }
Sleep(10);
}
end:
sprintf(errorInfo, "[線程退出]處理監(jiān)控到的數(shù)據(jù) ThreadProcessWatchedFiles ?PID : 0x%x ?GetLastError(%s)", pthread_self().p, GetLastErrorInfo());
dzlog_notice("%s",errorInfo);
pthread_exit(errorInfo);
return 0;
}
//③上傳數(shù)據(jù)
// ?讀取數(shù)據(jù)庫,獲取未上傳的圖片進行上傳,如果http下的圖片文件不存在,則讀取ftp下的圖片并進行上傳
void* ThreadUpload(void* pParam)
{
dzlog_notice("[線程開啟]上傳數(shù)據(jù) ThreadUpload ?PID : 0x%x ?GetLastError(%s)", pthread_self().p, GetLastErrorInfo());
Cwx_kk_upDlg * dlg = (Cwx_kk_upDlg*)pParam;
TCHAR errorInfo[TF_MAX_PATH_LEN]={0};
queue<VehicleInfo*> listIn;
VehicleInfo *vehicleInfo = 0;
long lRet = 0;
int id = 0;
bool connected = false;
TFDB db;
while(true){
db.Query(listIn);// 查詢未上傳的數(shù)據(jù)
next:
if(m_ExitCode==1)
goto end;
if(listIn.empty()){
Sleep(100);
continue;
}
vehicleInfo = listIn.front();
listIn.pop();
if(vehicleInfo==0)
goto next;
connect:
if( !connected )
lRet = dlg->InitTrans(vehicleInfo);//初始化連接,注冊車道
if( lRet == CONNECT_ERROR){
dzlog_error("網(wǎng)絡(luò)連接失敗") ;
connected = false;
Sleep(2000);
goto connect;
}
connected = true;
id = vehicleInfo->id;
lRet = dlg->UploadInfo(vehicleInfo);//上傳數(shù)據(jù)
if(vehicleInfo)
delete vehicleInfo;
if( lRet == OK)
db.Uploaded( id );//上傳成功
else{
//上傳失敗
if( lRet == FALIED) { //連接成功但是上傳失敗
dzlog_error("連接成功但是上傳失敗 @ id=%d ", id) ; // to do something
}else if( lRet == CONNECT_ERROR){
dzlog_error("網(wǎng)絡(luò)連接失敗 @ id=%d ", ?id) ;
connected = false;
Sleep(100);
goto connect; //重新連接
}
}
goto next;
Sleep(100);
}
end:
sprintf(errorInfo, "[線程退出]上傳數(shù)據(jù) ThreadUpload PID : 0x%x ?GetLastError(%s)", pthread_self().p, GetLastErrorInfo());
dzlog_notice("%s",errorInfo);
pthread_exit(errorInfo);
return 0;
}
#define MAX_THREAD 10
pthread_t thread[MAX_THREAD]={0}; ?
void* pth_join_ret[MAX_THREAD];
/* =========================================================================
* ?余留文件處理線程
* ?處理上次退出后FTP未處理的文件
* ? ?若程序死掉了,自己重啟后首先處理上次余留的FTP上傳的文件
* ? ?1.用FileUtil::ListFiles獲取FTP目錄下未處理的文件
* ? ?2.放入list隊列?
===========================================================================*/
void* ThreadProcessLast(void *pParam)
{
dzlog_notice("[線程開啟]余留文件處理線程 ThreadProcessLast ?PID : 0x%x GetLastError(%s)", pthread_self().p, GetLastErrorInfo());
Cwx_kk_upDlg * dlg = (Cwx_kk_upDlg*)pParam;
TCHAR errorInfo[TF_MAX_PATH_LEN]={0};
list<char *> list;
char *imagePath = 0;
while(true){
if(m_ExitCode==1)
goto end;
FileUtil::ListFiles(dlg->kkConfig.ftpPath, NULL, list, dlg->kkConfig.fileExt, 1, false, true);
while( !list.empty()){
if(m_ExitCode==1)
goto end;
imagePath = list.front();
list.pop_front();
if(imagePath!=0 && dlg->m_images.size()<500)
dlg->m_images.push(imagePath);
}
Sleep(1000);
}
end:
sprintf(errorInfo, "[線程退出]余留文件處理線程 ThreadProcessLast PID : 0x%x GetLastError(%s)", pthread_self().p, GetLastErrorInfo());
dzlog_notice("%s",errorInfo);
pthread_exit(errorInfo);
return 0;
}
//系統(tǒng)資源監(jiān)控
void* ProcessMonitorThread(void *pParam)
{
start:
dzlog_notice("[線程開啟]系統(tǒng)資源監(jiān)控線程 ThreadProcessLast ?PID : 0x%x GetLastError(%s)", pthread_self().p, GetLastErrorInfo());
Cwx_kk_upDlg * dlg = (Cwx_kk_upDlg*)pParam;
TCHAR errorInfo[TF_MAX_PATH_LEN]={0};
char temp[512]={0};
uint64_t ?mem=0;//內(nèi)存使用
uint64_t ?vmem=0;//虛擬內(nèi)存使用
int cpu =0;
int ret=0;
char tempsize[64]={0};
try
{
while( true )
{
if(m_ExitCode==1)
goto end;
cpu = get_cpu_usage();
ret = get_memory_usage( &mem, &vmem);
if( cpu>=0)
sprintf(temp, "CPU: %d%% ", cpu );
if( ret>=0){
sprintf(temp, "%s ?Memery: %s | %s ",temp, SizeFormat(mem, tempsize) , SizeFormat(vmem, tempsize) );
}
sprintf(errorInfo, "系統(tǒng)資源 ProcessMonitorThread [%s] %s ",temp, GetLastErrorInfo());
dzlog_info("%s", errorInfo);
dlg->GetDlgItem(ID_PROCESS_STATE)->SetWindowText(temp);
Sleep(1000);
}
}catch(...){
sprintf(errorInfo, "[線程退出]系統(tǒng)資源監(jiān)控線程 ProcessMonitorThread PID : 0x%x GetLastError(%s)", pthread_self().p, GetLastErrorInfo());
dzlog_notice("%s",errorInfo);
goto start;
}
end:
sprintf(errorInfo, "[線程退出]系統(tǒng)資源監(jiān)控線程 ProcessMonitorThread PID : 0x%x GetLastError(%s)", pthread_self().p, GetLastErrorInfo());
dzlog_notice("%s",errorInfo);
pthread_exit(errorInfo);
return 0;
}
//開始工作線程
void * ThreadStartAll(void *pParam)
{
TCHAR errorInfo[TF_MAX_PATH_LEN]={0};
threadRuning = !threadRuning;
Cwx_kk_upDlg * dlg = (Cwx_kk_upDlg*)pParam;
CMenu *pMenu = AfxGetApp()->m_pMainWnd->GetMenu();?
CMenu *pSubMenu = pMenu->GetSubMenu(2);
dzlog_notice("======================================================================");
if(threadRuning){
dzlog_notice("開始工作線程 StartWatch");
m_ExitCode = 0;
pthread_create(&thread[0], NULL, ThreadProcessLast, pParam);//余留文件處理線程
pthread_create(&thread[1], NULL, ThreadWatcher, pParam); //開啟監(jiān)控目錄線程
pthread_create(&thread[2], NULL, ThreadProcessWatchedFiles, pParam); //開啟處理監(jiān)控到的數(shù)據(jù)處理線程
pthread_create(&thread[3], NULL, ThreadUpload, pParam); //開啟數(shù)據(jù)上傳線程
pthread_create(&thread[4], NULL, ProcessMonitorThread, pParam); //系統(tǒng)資源監(jiān)控
//AfxBeginThread(ThreadWatcher, this);//開啟監(jiān)控目錄線程
//AfxBeginThread(ThreadProcessWatchedFiles, this);//開啟處理監(jiān)控到的數(shù)據(jù)處理線程
//AfxBeginThread(ThreadUpload, this);//開啟數(shù)據(jù)上傳線程
pSubMenu->ModifyMenu(ID_START_WATCH, MF_BYCOMMAND ,ID_START_WATCH,"關(guān)閉監(jiān)控");
}else{
dzlog_notice("關(guān)閉工作線程 OnStartWatch");
m_ExitCode = 1;
Sleep(500);
pthread_join( thread[0], &pth_join_ret[0]);
dzlog_notice("關(guān)閉線程 thread0[余留文件處理線程] ? retruns : %s ", pth_join_ret[0]);
pthread_join( thread[1], &pth_join_ret[1]);
dzlog_notice("關(guān)閉線程 thread1[監(jiān)控目錄線程] ? retruns : %s ", pth_join_ret[1]);
pthread_join( thread[2], &pth_join_ret[2]);
dzlog_notice("關(guān)閉線程 thread2[數(shù)據(jù)處理線程] ? retruns : %s ", pth_join_ret[2]);
pthread_join( thread[3], &pth_join_ret[3]);
dzlog_notice("關(guān)閉線程 thread3[數(shù)據(jù)上傳線程] ? retruns : %s ", pth_join_ret[3]);
pthread_join( thread[4], &pth_join_ret[4]);
dzlog_notice("關(guān)閉線程 thread4[系統(tǒng)資源監(jiān)控線程] ? retruns : %s ", pth_join_ret[4]);
//
pSubMenu->ModifyMenu(ID_START_WATCH, MF_BYCOMMAND ,ID_START_WATCH,"開啟監(jiān)控");
}
sprintf(errorInfo, "[線程退出] 開始工作線程 ThreadStartAll ?PID : 0x%x ", pthread_self() );
pthread_exit(errorInfo);
return 0;
}
//開始監(jiān)控目錄
void Cwx_kk_upDlg::OnStartWatch()
{
//
if( !threadRuning){
FileUtil::CreateFolders(kkConfig.ftpPath);
FileUtil::CreateFolders(kkConfig.httpPath);
kkConfig.hDir = CreateFile( kkConfig.ftpPath ,
FILE_LIST_DIRECTORY,
FILE_SHARE_READ |
FILE_SHARE_WRITE |
FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL);
if( kkConfig.hDir == INVALID_HANDLE_VALUE )
{
sprintf(errorInfo, "打開監(jiān)控目錄失敗[%s][%s]",kkConfig.ftpPath, GetLastErrorInfo() );
dzlog_error(errorInfo);
MessageBox(errorInfo);
return ;
}
}
pthread_t thread;
pthread_create(&thread, NULL, ThreadStartAll, this); //開啟工作線程
}
總結(jié)
以上是生活随笔為你收集整理的文件监控(二) 代码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring MVC+Spring+My
- 下一篇: 遇见未来 | 对话朱贤文: Postgr