#include "PatchMonitor.h" #include "GSESingleton.h" #include "../Common/Util.h" CPatchMonitor::CPatchMonitor() : m_MonitorThread(0), m_bQuit(false) { } CPatchMonitor::~CPatchMonitor(void) { } void CPatchMonitor::SetPatchPath(string strPath, CPatchFileMng* pMng) { char szBuf[MAX_FILE_NAME]; getcwd(szBuf, MAX_FILE_NAME); MONITOR_OBJ mOjb; mOjb.strFilePath = szBuf; mOjb.strFilePath.append(1, PATH_DELIMITER); mOjb.strFilePath.append(strPath); mOjb.nObj = 0; mOjb.pMng = pMng; m_MonitorObjs.push_back(mOjb); } void CPatchMonitor::ThreadProc() throw(GSEException) { const int BUFSIZE = 1024; char szBuf[BUFSIZE]; memset(szBuf, 0, sizeof(szBuf)); #ifdef WIN32 HANDLE hOjbs[64]; assert(m_MonitorObjs.size() < 64); OVERLAPPED ov; memset(&ov, 0, sizeof(ov)); DWORD dwRetValue = 0; for (size_t nIndex = 0; nIndex < m_MonitorObjs.size(); nIndex++) { BOOL bRet = ReadDirectoryChangesW(m_MonitorObjs[nIndex].nObj, szBuf, sizeof(szBuf), FALSE, FILE_NOTIFY_CHANGE_FILE_NAME, &dwRetValue, &ov, NULL); assert(bRet); hOjbs[nIndex] = (HANDLE)(m_MonitorObjs[nIndex].nObj); } #else for (size_t nIndex = 0; nIndex < m_MonitorObjs.size(); nIndex++) { m_MonitorObjs[nIndex].nObj = inotify_add_watch(m_hPatchDir, m_MonitorObjs[nIndex].strFilePath.c_str(), IN_CREATE | IN_DELETE | IN_MOVED_TO); } fd_set fsPatch; FD_ZERO(&fsPatch); FD_SET(m_hPatchDir, &fsPatch); timeval tvWait; tvWait.tv_sec = 30; tvWait.tv_usec = 0; #endif while (!m_bQuit) { #ifdef WIN32 DWORD dwWait = WaitForMultipleObjects(m_MonitorObjs.size(), hOjbs, FALSE, 1000); if (dwWait >= WAIT_OBJECT_0 && dwWait < m_MonitorObjs.size()) { LPOVERLAPPED lpOv = NULL; GetOverlappedResult(m_MonitorObjs[dwWait - WAIT_OBJECT_0].nObj, &ov, &dwRetValue, TRUE); PFILE_NOTIFY_INFORMATION pFNI = reinterpret_cast(szBuf); do { char szFileName[MAX_FILE_NAME]; WideCharToMultiByte(CP_ACP, 0, pFNI->FileName, pFNI->FileNameLength, szFileName, MAX_FILE_NAME, 0, 0); if (pFNI->Action == FILE_ACTION_ADDED) { CUtil::Msg("add patch tmp %s\n", szFileName); } if (pFNI->Action == FILE_ACTION_RENAMED_NEW_NAME) { CUtil::Msg("add patch %s\n", szFileName); AddPatchFile(szFileName, dwWait - WAIT_OBJECT_0); } if (pFNI->Action == FILE_ACTION_REMOVED) { CUtil::Msg("delete patch %s \n", szFileName); DelPatchFile(szFileName, dwWait - WAIT_OBJECT_0); } if (pFNI->NextEntryOffset == 0) { break; } pFNI = reinterpret_cast(szBuf + pFNI->NextEntryOffset); } while(pFNI != 0); memset(szBuf, 0, sizeof(szBuf)); memset(&ov, 0, sizeof(ov)); ReadDirectoryChangesW(m_MonitorObjs[dwWait - WAIT_OBJECT_0].nObj, szBuf, sizeof(szBuf), FALSE, FILE_NOTIFY_CHANGE_FILE_NAME, &dwRetValue, &ov, NULL); } #else int nRet = select(m_hPatchDir + 1, &fsPatch, NULL, NULL, &tvWait); if (nRet < 0) { CUtil::Msg("select failed.error code:%d", errno); continue; } else if (!nRet) { //time out CUtil::Msg("patch monitor time out\n"); } else if (FD_ISSET(m_hPatchDir, &fsPatch)) { int nLen = 0; nLen = read(m_hPatchDir, szBuf, BUFSIZE); if (nLen < 0) { CUtil::Msg("read failed .err no :%d", errno); break; } int nIndex = 0; while (nIndex < nLen) { inotify_event* pIe = reinterpret_cast(&szBuf[nIndex]); if (pIe->len) { if (pIe->mask & IN_CREATE && !(pIe->mask & IN_ISDIR)) { CUtil::Msg("add patch tmp %s\n", pIe->name); } if (pIe->mask & IN_DELETE && !(pIe->mask & IN_ISDIR)) { CUtil::Msg("delete patch %s \n", pIe->name); DelPatchFile(pIe->name, FindMonitorIndex(pIe->wd)); } if (pIe->mask & IN_MOVED_TO && !(pIe->mask & IN_ISDIR)) { CUtil::Msg("add patch %s\n", pIe->name); AddPatchFile(pIe->name, FindMonitorIndex(pIe->wd)); } } nIndex += sizeof(inotify_event) + pIe->len; } memset(szBuf, 0, BUFSIZE); } FD_CLR(m_hPatchDir, &fsPatch); FD_ZERO(&fsPatch); FD_SET(m_hPatchDir, &fsPatch); tvWait.tv_sec = 30; tvWait.tv_usec = 0; #endif } #ifndef WIN32 for (size_t nIndex = 0; nIndex < m_MonitorObjs.size(); nIndex++) { inotify_rm_watch(m_hPatchDir, m_MonitorObjs[nIndex].nObj); } #endif } void CPatchMonitor::Terminate() throw(GSEException) { m_bQuit = true; } int CPatchMonitor::Start() { #ifdef WIN32 for (size_t nIndex = 0; nIndex < m_MonitorObjs.size(); nIndex++) { m_MonitorObjs[nIndex].nObj = CreateFile(m_MonitorObjs[nIndex].strFilePath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); if (INVALID_HANDLE_VALUE == m_MonitorObjs[nIndex].nObj) { CUtil::Msg("createfile failed in patchmonitor.err no:%d\n", GetLastError()); return -1; } } #else m_hPatchDir = inotify_init(); if (m_hPatchDir < 0) { CUtil::Msg("inotify_init failed in patchmonitor.err no:%d\n", errno); return -1; } #endif m_MonitorThread = GSECreateThread(this, false); return 0; } int CPatchMonitor::Stop() { m_bQuit = true; GSEDestroyThread(m_MonitorThread); m_MonitorThread = 0; #ifdef WIN32 for (size_t nIndex = 0; nIndex < m_MonitorObjs.size(); nIndex++) { CloseHandle(m_MonitorObjs[nIndex].nObj); } #else close(m_hPatchDir); m_hPatchDir = -1; #endif return 0; } int CPatchMonitor::AddPatchFile(const char* szFileName, int nIndex) { if (nIndex == -1) { return 0; } char szPatchFileName[MAX_FILE_NAME]; sprintf(szPatchFileName, "%s%c%s", m_MonitorObjs[nIndex].strFilePath.c_str(), PATH_DELIMITER, szFileName); m_MonitorObjs[nIndex].pMng->CreatePatchFile(szPatchFileName); return 0; } int CPatchMonitor::DelPatchFile(const char *szFileName, int nIndex) { if (nIndex == -1) { return 0; } char szPatchFileName[MAX_FILE_NAME]; sprintf(szPatchFileName, "%s%c%s", m_MonitorObjs[nIndex].strFilePath.c_str(), PATH_DELIMITER, szFileName); m_MonitorObjs[nIndex].pMng->DeletePatchFile(szPatchFileName); return 0; } #ifdef WIN32 int CPatchMonitor::FindMonitorIndex(HANDLE nObj) #else int CPatchMonitor::FindMonitorIndex(int nObj) #endif { int nRet = -1; for (size_t nIndex = 0; nIndex < m_MonitorObjs.size(); nIndex++) { if (nObj == m_MonitorObjs[nIndex].nObj) { nRet = nIndex; break; } } return nRet; }