#define _CRT_SECURE_NO_WARNINGS #include #include #include "AnyCleaner.h" #include "RtpFilesCleaner.h" #include "json.h" #include "RtpFast.h" //#include "CRtpFrame.h" ClearRtpFiles::ClearRtpFiles() { //Start(); } ClearRtpFiles::~ClearRtpFiles() { Stop(); std::list::iterator iter; for (iter = list_src_rtpfiles.begin(); iter != list_src_rtpfiles.end();) { delete (*iter); *iter = NULL; iter = list_src_rtpfiles.erase(iter); } list_src_rtpfiles.clear(); for (iter = list_backup_rtpfiles.begin(); iter != list_backup_rtpfiles.end();) { delete (*iter); *iter = NULL; iter = list_backup_rtpfiles.erase(iter); } list_backup_rtpfiles.clear(); } bool ClearRtpFiles::LoadDeviceInfo() { char* text = NULL; FILE* pf = fopen("anycleaner.cfg", "rb+"); if (!pf) { BLOG_ERROR("open anycleaner.cfg failed"); //printf("open deveice.config failed\n"); return false; } fseek(pf, 0, SEEK_END); long lSize = ftell(pf); text = (char*)malloc(lSize); rewind(pf); fread(text, sizeof(char), lSize, pf); std::string filedata = std::string(text, lSize); free(text); fclose(pf); nlohmann::json j = nlohmann::json::parse(filedata); std::string src = j["duty_spool"]; src_path = src; std::string backup = j["standby_spool"]; backup_path = backup; checktime = j["check_interval"]; remaining_memory = j["storage_freespace"]; retension_day = j["retension_day"]; return true; } int ClearRtpFiles::Get_Channel_List(std::vector* pVecFolderName, char* folder_name) { char fileFound[256]; WIN32_FIND_DATAA info; HANDLE hp; char* folder_path = NULL; sprintf(fileFound, ("%s\\*.*"), folder_name); hp = FindFirstFileA(fileFound, &info); if (hp == INVALID_HANDLE_VALUE) return -1; do { if ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY) continue; // "." if (info.cFileName[0] == '.' && info.cFileName[1] == '\0') continue; // ".." if (info.cFileName[0] == '.' && info.cFileName[1] == '.' && info.cFileName[2] == '\0') continue; // find one directory folder_path = new char[256]; if (!folder_path) break; sprintf(folder_path, "%s\\%s", folder_name, info.cFileName); pVecFolderName->push_back(folder_path); folder_path = NULL; } while (FindNextFileA(hp, &info)); FindClose(hp); return 0; } int ClearRtpFiles::Get_Date_List(std::vector* pVecFolderName, char* folder_name) { char fileFound[256]; WIN32_FIND_DATAA info; HANDLE hp; char* folder_path = NULL; sprintf(fileFound, ("%s\\*.*"), folder_name); hp = FindFirstFileA(fileFound, &info); if (hp == INVALID_HANDLE_VALUE) return -1; do { if ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY) continue; // "." if (info.cFileName[0] == '.' && info.cFileName[1] == '\0') continue; // ".." if (info.cFileName[0] == '.' && info.cFileName[1] == '.' && info.cFileName[2] == '\0') continue; // find one directory folder_path = new char[256]; if (!folder_path) break; sprintf(folder_path, "%s\\%s", folder_name, info.cFileName); pVecFolderName->push_back(folder_path); folder_path = NULL; } while (FindNextFileA(hp, &info)); FindClose(hp); return 0; } void ClearRtpFiles::Get_DateFiles(std::vector* vec_foldernames, const char* src_folder) { char* curr_folder = new char[256]; memset(curr_folder, 0, 256); sprintf(curr_folder, "%s", src_folder); Get_Date_List(vec_foldernames, (char*)src_folder); } void ClearRtpFiles::Get_Channel(std::vector* vec_foldernames,const char* src_folder) { char* curr_folder = new char[256]; memset(curr_folder,0,256); sprintf(curr_folder, "%s", src_folder); Get_Channel_List(vec_foldernames, (char*)src_folder); } int ClearRtpFiles::rtp_listfile(std::list* list_rtpfiles, const char* src_folder) { std::vector vec_foldernames; char* curr_folder = new char[256]; if (!curr_folder) { //CONSOLELOG(ERROR) << "mem is not enough to process folder: " << src_folder; return -1; } sprintf(curr_folder, "%s", src_folder); vec_foldernames.push_back(curr_folder); CDiscHelper::GetFolderName(&vec_foldernames, (char*)src_folder, true); for (unsigned int f = 0; f < vec_foldernames.size(); f++) { std::vector vec_filenames; CDiscHelper::GetFileName(&vec_filenames, vec_foldernames.at(f)); if (vec_filenames.empty()) { //CONSOLELOG(INFO) << "there is no files under folder: " << vec_foldernames.at(f); continue; } // #process all the rtp files for (unsigned int v = 0; v < vec_filenames.size(); v++) { if (!CDiscHelper::IsMatchExt(vec_filenames.at(v), (char*)".rtp")) continue; // ignore non rtp files RTPFILEDESC* rtp_filedesc = new RTPFILEDESC; if (!rtp_filedesc) { //CONSOLELOG(ERROR) << "mem is limited to process more files."; break; } memset(rtp_filedesc, 0, sizeof(*rtp_filedesc)); sprintf(rtp_filedesc->file_name, "%s", vec_filenames.at(v)); rtp_filedesc->file_size = CDiscHelper::GetFileSize(rtp_filedesc->file_name); std::string srcdata = std::string(rtp_filedesc->file_name); std::string data = srcdata; while (true) { if (data.npos != data.find("\\")) { data = data.substr(data.find("\\") + 1); } else { break; } } rtp_filedesc->name = data; char fold[100] = ""; memcpy(fold, srcdata.c_str(), srcdata.find(data) - 1); data = std::string(fold); while (true) { if (data.npos != data.find("\\")) { data = data.substr(data.find("\\") + 1); } else { break; } } memcpy(rtp_filedesc->folder, data.c_str(),data.size()); list_rtpfiles->push_back(rtp_filedesc); } CDiscHelper::ClearFolderName(&vec_filenames); } CDiscHelper::ClearFolderName(&vec_foldernames); return 0; } std::wstring s2ws(const std::string& s) { int len; int slength = (int)s.length() + 1; len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0); wchar_t* buf = new wchar_t[len]; MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len); std::wstring r(buf); delete[] buf; return r; } void ClearRtpFiles::Delete_file(std::string filename) { { std::string file = filename; std::wstring stemp = s2ws(file); LPCWSTR result = stemp.c_str(); BOOL del = DeleteFile(result); if (!del) { DWORD error_rus = GetLastError(); BLOG_DEBUG(fmt::format("[F] *** failed to DeleteFile {},code{} ***", file, error_rus)); } } { std::string file = filename; file += ".gop"; std::wstring stemp = s2ws(file); LPCWSTR result = stemp.c_str(); BOOL del = DeleteFile(result); if (!del) { DWORD error_rus = GetLastError(); BLOG_DEBUG(fmt::format("[F] *** failed to DeleteFile {},code{} ***", file, error_rus)); } } } int ClearRtpFiles::Identical_file_check() { std::string src; std::string back; std::list::iterator iter = list_backup_rtpfiles.begin(); for (iter; iter != list_backup_rtpfiles.end();) { back = std::string((*iter)->folder); for (auto l : list_src_rtpfiles) { src = std::string(l->folder); if (back == src) { if ((*iter)->name == l->name) { //delete file Delete_file((*iter)->file_name); } } } iter++; } for (iter = list_src_rtpfiles.begin(); iter != list_src_rtpfiles.end();) { delete (*iter); *iter = NULL; iter = list_src_rtpfiles.erase(iter); } list_src_rtpfiles.clear(); for (iter = list_backup_rtpfiles.begin(); iter != list_backup_rtpfiles.end();) { delete (*iter); *iter = NULL; iter = list_backup_rtpfiles.erase(iter); } list_backup_rtpfiles.clear(); return 0; } std::string get_Item(std::string src) { std::string data = src; while (true) { if (data.npos != data.find("\\")) { data = data.substr(data.find("\\") + 1); } else { break; } } return data; } /*通过调用ShFileOperation来实现整个目录的删除*/ /*只删除单个目录*/ BOOL ClearRtpFiles::SHDeleteFolder(std::string pstrFolder, BOOL bAllowUndo) { std::string file = pstrFolder; std::wstring stemp = s2ws(file); LPCWSTR result = stemp.c_str(); int iPathLen = wcslen(result); if (iPathLen >= MAX_PATH) { return FALSE; } /*确保目录的路径以2个\0结尾*/ TCHAR tczFolder[MAX_PATH + 1]; ZeroMemory(tczFolder, (MAX_PATH + 1) * sizeof(TCHAR)); wcscpy(tczFolder, result); tczFolder[iPathLen] = _T('\0'); tczFolder[iPathLen + 1] = _T('\0'); SHFILEOPSTRUCT FileOp; ZeroMemory(&FileOp, sizeof(SHFILEOPSTRUCT)); FileOp.fFlags |= FOF_SILENT; /*不显示进度*/ FileOp.fFlags |= FOF_NOERRORUI; /*不报告错误信息*/ FileOp.fFlags |= FOF_NOCONFIRMATION;/*直接删除,不进行确认*/ FileOp.hNameMappings = NULL; FileOp.hwnd = NULL; FileOp.lpszProgressTitle = NULL; FileOp.wFunc = FO_DELETE; FileOp.pFrom = tczFolder; /*要删除的目录,必须以2个\0结尾*/ FileOp.pTo = NULL; /*根据传递的bAllowUndo参数确定是否删除到回收站*/ if (bAllowUndo) { FileOp.fFlags |= FOF_ALLOWUNDO; /*删除到回收站*/ } else { FileOp.fFlags &= ~FOF_ALLOWUNDO; /*直接删除,不放入回收站*/ } /*删除目录*/ if (0 == SHFileOperation(&FileOp)) { return TRUE; } else { return FALSE; } } void ClearRtpFiles::Get_Channels(const char* backup_folder, const char* src_folder) { Get_Channel(&vec_src_foldernames, src_folder); if (vec_src_foldernames.empty()) { BLOG_ERROR(fmt::format("[F] *** failed to load src_folder file vec_src_foldernames {}***", src_folder)); return; } Get_Channel(&vec_back_foldernames, backup_folder); if (vec_back_foldernames.empty()) { BLOG_ERROR(fmt::format("[F] *** failed to load src_folder file vec_back_foldernames {}***", backup_folder)); return; } for (auto back : vec_back_foldernames) { std::string bak = std::string(back); std::string back_channel = get_Item(bak); for (auto src : vec_src_foldernames) { std::string src_ = std::string(src); std::string src_channel = get_Item(src_); if (back_channel == src_channel) { Get_List_File(bak.c_str(), src_.c_str()); Identical_file_check(); break; } } } //删除备份的空目录 { std::vector::iterator iter; for (auto back : vec_back_foldernames) { Get_DateFiles(&vec_back_date_folder, back); for (auto d : vec_back_date_folder) { std::string file = std::string(d); std::wstring stemp = s2ws(file); LPCWSTR result = stemp.c_str(); BOOL ret = PathIsDirectoryEmpty(result); if (ret) SHDeleteFolder(file, false); } for (iter = vec_back_date_folder.begin(); iter != vec_back_date_folder.end();) { delete (*iter); *iter = NULL; iter = vec_back_date_folder.erase(iter); } vec_back_date_folder.clear(); } } //剩余空间小于要求值,删除主存储 std::string serial = std::string(vec_src_foldernames.front()); serial = serial.substr(0, serial.find("\\")); int gb_data = Get_Disk_Free(serial); int index = 0; int i = 0; if (remaining_memory >= gb_data) { for (auto s : vec_src_foldernames) { Get_DateFiles(&vec_src_date_folder, s); if (vec_src_date_folder.size() >= retension_day) { index = vec_src_date_folder.size() - retension_day; for (auto d : vec_src_date_folder) { if (i >= index) break; SHDeleteFolder(d,false); i++; } } std::vector::iterator iter; for (iter = vec_src_date_folder.begin(); iter != vec_src_date_folder.end();) { delete (*iter); *iter = NULL; iter = vec_src_date_folder.erase(iter); } vec_src_date_folder.clear(); i = 0; } } std::vector::iterator iter; for (iter = vec_src_foldernames.begin(); iter != vec_src_foldernames.end();) { delete (*iter); *iter = NULL; iter = vec_src_foldernames.erase(iter); } vec_src_foldernames.clear(); for (iter = vec_back_foldernames.begin(); iter != vec_back_foldernames.end();) { delete (*iter); *iter = NULL; iter = vec_back_foldernames.erase(iter); } vec_back_foldernames.clear(); } int ClearRtpFiles::Get_List_File(const char* backup_folder, const char* src_folder) { // # read in file list and divide then into trunk ... rtp_listfile(&list_src_rtpfiles, src_folder); if (list_src_rtpfiles.empty()) { BLOG_WARN(fmt::format("[F] *** src_folder file[{}] is empty***", src_folder)); return -1; } rtp_listfile(&list_backup_rtpfiles, backup_folder); if (list_backup_rtpfiles.empty()) { BLOG_WARN(fmt::format("[F] *** backup_folder file[{}] is empty ***", backup_folder)); return -1; } return 1; } int ClearRtpFiles::Get_Disk_Free(std::string serial) { int pSize = MultiByteToWideChar(CP_OEMCP, 0, serial.c_str(), serial.size() + 1, NULL, 0); TCHAR* buf = new wchar_t[pSize]; MultiByteToWideChar(CP_OEMCP, 0, serial.c_str(), serial.size() + 1, buf, pSize); ULARGE_INTEGER available, total, free; //ULARGE_INTEGER 一个64位的无符号整型值 /*if (GetDiskFreeSpaceEx(TEXT("D:"), (ULARGE_INTEGER*)&available, (ULARGE_INTEGER*)&total, (ULARGE_INTEGER*)&free)) {*/ if (GetDiskFreeSpaceEx(buf, (ULARGE_INTEGER*)&available, (ULARGE_INTEGER*)&total, (ULARGE_INTEGER*)&free)) { //printf(" | 总容量 = %.2f GB,可用空间 = %.2f GB,空闲空间 = %.2f GB\n",GB(total), GB(available), GB(free)); } else { BLOG_ERROR(fmt::format("[F] *** failed to Get_Disk_Free ***")); //puts("获取容量信息失败"); } int available_ = GB(available); return available_; } void ClearRtpFiles::init() { life_worker = new CAppLifeThread(); life_worker->Start(); Start(); } void ClearRtpFiles::Action() { while (!IsAborted()) { Get_Channels(backup_path.c_str(), src_path.c_str()); /*Get_List_File(backup_path.c_str(), src_path.c_str());*/ /*Identical_file_check();*/ std::this_thread::sleep_for(std::chrono::minutes(checktime)); } }