RtpFilesCleaner.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <tchar.h>
  3. #include <Shlwapi.h>
  4. #include "AnyCleaner.h"
  5. #include "RtpFilesCleaner.h"
  6. #include "json.h"
  7. #include "RtpFast.h"
  8. //#include "CRtpFrame.h"
  9. ClearRtpFiles::ClearRtpFiles()
  10. {
  11. //Start();
  12. }
  13. ClearRtpFiles::~ClearRtpFiles()
  14. {
  15. Stop();
  16. std::list<RTPFILEDESC*>::iterator iter;
  17. for (iter = list_src_rtpfiles.begin(); iter != list_src_rtpfiles.end();) {
  18. delete (*iter);
  19. *iter = NULL;
  20. iter = list_src_rtpfiles.erase(iter);
  21. }
  22. list_src_rtpfiles.clear();
  23. for (iter = list_backup_rtpfiles.begin(); iter != list_backup_rtpfiles.end();) {
  24. delete (*iter);
  25. *iter = NULL;
  26. iter = list_backup_rtpfiles.erase(iter);
  27. }
  28. list_backup_rtpfiles.clear();
  29. }
  30. bool ClearRtpFiles::LoadDeviceInfo()
  31. {
  32. char* text = NULL;
  33. FILE* pf = fopen("anycleaner.cfg", "rb+");
  34. if (!pf) {
  35. BLOG_ERROR("open anycleaner.cfg failed");
  36. //printf("open deveice.config failed\n");
  37. return false;
  38. }
  39. fseek(pf, 0, SEEK_END);
  40. long lSize = ftell(pf);
  41. text = (char*)malloc(lSize);
  42. rewind(pf);
  43. fread(text, sizeof(char), lSize, pf);
  44. std::string filedata = std::string(text, lSize);
  45. free(text);
  46. fclose(pf);
  47. nlohmann::json j = nlohmann::json::parse(filedata);
  48. std::string src = j["duty_spool"];
  49. src_path = src;
  50. std::string backup = j["standby_spool"];
  51. backup_path = backup;
  52. checktime = j["check_interval"];
  53. remaining_memory = j["storage_freespace"];
  54. retension_day = j["retension_day"];
  55. return true;
  56. }
  57. int ClearRtpFiles::Get_Channel_List(std::vector<char*>* pVecFolderName, char* folder_name)
  58. {
  59. char fileFound[256];
  60. WIN32_FIND_DATAA info;
  61. HANDLE hp;
  62. char* folder_path = NULL;
  63. sprintf(fileFound, ("%s\\*.*"), folder_name);
  64. hp = FindFirstFileA(fileFound, &info);
  65. if (hp == INVALID_HANDLE_VALUE) return -1;
  66. do {
  67. if ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY) continue;
  68. // "."
  69. if (info.cFileName[0] == '.' && info.cFileName[1] == '\0') continue;
  70. // ".."
  71. if (info.cFileName[0] == '.' && info.cFileName[1] == '.' && info.cFileName[2] == '\0') continue;
  72. // find one directory
  73. folder_path = new char[256];
  74. if (!folder_path) break;
  75. sprintf(folder_path, "%s\\%s", folder_name, info.cFileName);
  76. pVecFolderName->push_back(folder_path);
  77. folder_path = NULL;
  78. } while (FindNextFileA(hp, &info));
  79. FindClose(hp);
  80. return 0;
  81. }
  82. int ClearRtpFiles::Get_Date_List(std::vector<char*>* pVecFolderName, char* folder_name)
  83. {
  84. char fileFound[256];
  85. WIN32_FIND_DATAA info;
  86. HANDLE hp;
  87. char* folder_path = NULL;
  88. sprintf(fileFound, ("%s\\*.*"), folder_name);
  89. hp = FindFirstFileA(fileFound, &info);
  90. if (hp == INVALID_HANDLE_VALUE) return -1;
  91. do {
  92. if ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY) continue;
  93. // "."
  94. if (info.cFileName[0] == '.' && info.cFileName[1] == '\0') continue;
  95. // ".."
  96. if (info.cFileName[0] == '.' && info.cFileName[1] == '.' && info.cFileName[2] == '\0') continue;
  97. // find one directory
  98. folder_path = new char[256];
  99. if (!folder_path) break;
  100. sprintf(folder_path, "%s\\%s", folder_name, info.cFileName);
  101. pVecFolderName->push_back(folder_path);
  102. folder_path = NULL;
  103. } while (FindNextFileA(hp, &info));
  104. FindClose(hp);
  105. return 0;
  106. }
  107. void ClearRtpFiles::Get_DateFiles(std::vector<char*>* vec_foldernames, const char* src_folder)
  108. {
  109. char* curr_folder = new char[256];
  110. memset(curr_folder, 0, 256);
  111. sprintf(curr_folder, "%s", src_folder);
  112. Get_Date_List(vec_foldernames, (char*)src_folder);
  113. }
  114. void ClearRtpFiles::Get_Channel(std::vector<char*>* vec_foldernames,const char* src_folder)
  115. {
  116. char* curr_folder = new char[256];
  117. memset(curr_folder,0,256);
  118. sprintf(curr_folder, "%s", src_folder);
  119. Get_Channel_List(vec_foldernames, (char*)src_folder);
  120. }
  121. int ClearRtpFiles::rtp_listfile(std::list<RTPFILEDESC*>* list_rtpfiles, const char* src_folder)
  122. {
  123. std::vector<char*> vec_foldernames;
  124. char* curr_folder = new char[256];
  125. if (!curr_folder) {
  126. //CONSOLELOG(ERROR) << "mem is not enough to process folder: " << src_folder;
  127. return -1;
  128. }
  129. sprintf(curr_folder, "%s", src_folder);
  130. vec_foldernames.push_back(curr_folder);
  131. CDiscHelper::GetFolderName(&vec_foldernames, (char*)src_folder, true);
  132. for (unsigned int f = 0; f < vec_foldernames.size(); f++) {
  133. std::vector<char*> vec_filenames;
  134. CDiscHelper::GetFileName(&vec_filenames, vec_foldernames.at(f));
  135. if (vec_filenames.empty()) {
  136. //CONSOLELOG(INFO) << "there is no files under folder: " << vec_foldernames.at(f);
  137. continue;
  138. }
  139. // #process all the rtp files
  140. for (unsigned int v = 0; v < vec_filenames.size(); v++) {
  141. if (!CDiscHelper::IsMatchExt(vec_filenames.at(v), (char*)".rtp")) continue; // ignore non rtp files
  142. RTPFILEDESC* rtp_filedesc = new RTPFILEDESC;
  143. if (!rtp_filedesc) {
  144. //CONSOLELOG(ERROR) << "mem is limited to process more files.";
  145. break;
  146. }
  147. memset(rtp_filedesc, 0, sizeof(*rtp_filedesc));
  148. sprintf(rtp_filedesc->file_name, "%s", vec_filenames.at(v));
  149. rtp_filedesc->file_size = CDiscHelper::GetFileSize(rtp_filedesc->file_name);
  150. std::string srcdata = std::string(rtp_filedesc->file_name);
  151. std::string data = srcdata;
  152. while (true) {
  153. if (data.npos != data.find("\\")) {
  154. data = data.substr(data.find("\\") + 1);
  155. }
  156. else {
  157. break;
  158. }
  159. }
  160. rtp_filedesc->name = data;
  161. char fold[100] = "";
  162. memcpy(fold, srcdata.c_str(), srcdata.find(data) - 1);
  163. data = std::string(fold);
  164. while (true) {
  165. if (data.npos != data.find("\\")) {
  166. data = data.substr(data.find("\\") + 1);
  167. }
  168. else {
  169. break;
  170. }
  171. }
  172. memcpy(rtp_filedesc->folder, data.c_str(),data.size());
  173. list_rtpfiles->push_back(rtp_filedesc);
  174. }
  175. CDiscHelper::ClearFolderName(&vec_filenames);
  176. }
  177. CDiscHelper::ClearFolderName(&vec_foldernames);
  178. return 0;
  179. }
  180. std::wstring s2ws(const std::string& s)
  181. {
  182. int len; int slength = (int)s.length() + 1;
  183. len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0); wchar_t* buf = new wchar_t[len];
  184. MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
  185. std::wstring r(buf);
  186. delete[] buf;
  187. return r;
  188. }
  189. void ClearRtpFiles::Delete_file(std::string filename)
  190. {
  191. {
  192. std::string file = filename;
  193. std::wstring stemp = s2ws(file);
  194. LPCWSTR result = stemp.c_str();
  195. BOOL del = DeleteFile(result);
  196. if (!del) {
  197. DWORD error_rus = GetLastError();
  198. BLOG_DEBUG(fmt::format("[F] *** failed to DeleteFile {},code{} ***", file, error_rus));
  199. }
  200. }
  201. {
  202. std::string file = filename;
  203. file += ".gop";
  204. std::wstring stemp = s2ws(file);
  205. LPCWSTR result = stemp.c_str();
  206. BOOL del = DeleteFile(result);
  207. if (!del) {
  208. DWORD error_rus = GetLastError();
  209. BLOG_DEBUG(fmt::format("[F] *** failed to DeleteFile {},code{} ***", file, error_rus));
  210. }
  211. }
  212. }
  213. int ClearRtpFiles::Identical_file_check()
  214. {
  215. std::string src;
  216. std::string back;
  217. std::list<RTPFILEDESC*>::iterator iter = list_backup_rtpfiles.begin();
  218. for (iter; iter != list_backup_rtpfiles.end();) {
  219. back = std::string((*iter)->folder);
  220. for (auto l : list_src_rtpfiles) {
  221. src = std::string(l->folder);
  222. if (back == src) {
  223. if ((*iter)->name == l->name) {
  224. //delete file
  225. Delete_file((*iter)->file_name);
  226. }
  227. }
  228. }
  229. iter++;
  230. }
  231. for (iter = list_src_rtpfiles.begin(); iter != list_src_rtpfiles.end();) {
  232. delete (*iter);
  233. *iter = NULL;
  234. iter = list_src_rtpfiles.erase(iter);
  235. }
  236. list_src_rtpfiles.clear();
  237. for (iter = list_backup_rtpfiles.begin(); iter != list_backup_rtpfiles.end();) {
  238. delete (*iter);
  239. *iter = NULL;
  240. iter = list_backup_rtpfiles.erase(iter);
  241. }
  242. list_backup_rtpfiles.clear();
  243. return 0;
  244. }
  245. std::string get_Item(std::string src)
  246. {
  247. std::string data = src;
  248. while (true) {
  249. if (data.npos != data.find("\\")) {
  250. data = data.substr(data.find("\\") + 1);
  251. }
  252. else {
  253. break;
  254. }
  255. }
  256. return data;
  257. }
  258. /*通过调用ShFileOperation来实现整个目录的删除*/
  259. /*只删除单个目录*/
  260. BOOL ClearRtpFiles::SHDeleteFolder(std::string pstrFolder, BOOL bAllowUndo)
  261. {
  262. std::string file = pstrFolder;
  263. std::wstring stemp = s2ws(file);
  264. LPCWSTR result = stemp.c_str();
  265. int iPathLen = wcslen(result);
  266. if (iPathLen >= MAX_PATH)
  267. {
  268. return FALSE;
  269. }
  270. /*确保目录的路径以2个\0结尾*/
  271. TCHAR tczFolder[MAX_PATH + 1];
  272. ZeroMemory(tczFolder, (MAX_PATH + 1) * sizeof(TCHAR));
  273. wcscpy(tczFolder, result);
  274. tczFolder[iPathLen] = _T('\0');
  275. tczFolder[iPathLen + 1] = _T('\0');
  276. SHFILEOPSTRUCT FileOp;
  277. ZeroMemory(&FileOp, sizeof(SHFILEOPSTRUCT));
  278. FileOp.fFlags |= FOF_SILENT; /*不显示进度*/
  279. FileOp.fFlags |= FOF_NOERRORUI; /*不报告错误信息*/
  280. FileOp.fFlags |= FOF_NOCONFIRMATION;/*直接删除,不进行确认*/
  281. FileOp.hNameMappings = NULL;
  282. FileOp.hwnd = NULL;
  283. FileOp.lpszProgressTitle = NULL;
  284. FileOp.wFunc = FO_DELETE;
  285. FileOp.pFrom = tczFolder; /*要删除的目录,必须以2个\0结尾*/
  286. FileOp.pTo = NULL;
  287. /*根据传递的bAllowUndo参数确定是否删除到回收站*/
  288. if (bAllowUndo) {
  289. FileOp.fFlags |= FOF_ALLOWUNDO; /*删除到回收站*/
  290. } else {
  291. FileOp.fFlags &= ~FOF_ALLOWUNDO; /*直接删除,不放入回收站*/
  292. }
  293. /*删除目录*/
  294. if (0 == SHFileOperation(&FileOp)) {
  295. return TRUE;
  296. } else {
  297. return FALSE;
  298. }
  299. }
  300. void ClearRtpFiles::Get_Channels(const char* backup_folder, const char* src_folder)
  301. {
  302. Get_Channel(&vec_src_foldernames, src_folder);
  303. if (vec_src_foldernames.empty()) {
  304. BLOG_ERROR(fmt::format("[F] *** failed to load src_folder file vec_src_foldernames {}***", src_folder));
  305. return;
  306. }
  307. Get_Channel(&vec_back_foldernames, backup_folder);
  308. if (vec_back_foldernames.empty()) {
  309. BLOG_ERROR(fmt::format("[F] *** failed to load src_folder file vec_back_foldernames {}***", backup_folder));
  310. return;
  311. }
  312. for (auto back : vec_back_foldernames) {
  313. std::string bak = std::string(back);
  314. std::string back_channel = get_Item(bak);
  315. for (auto src : vec_src_foldernames) {
  316. std::string src_ = std::string(src);
  317. std::string src_channel = get_Item(src_);
  318. if (back_channel == src_channel) {
  319. Get_List_File(bak.c_str(), src_.c_str());
  320. Identical_file_check();
  321. break;
  322. }
  323. }
  324. }
  325. //删除备份的空目录
  326. {
  327. std::vector<char*>::iterator iter;
  328. for (auto back : vec_back_foldernames) {
  329. Get_DateFiles(&vec_back_date_folder, back);
  330. for (auto d : vec_back_date_folder) {
  331. std::string file = std::string(d);
  332. std::wstring stemp = s2ws(file);
  333. LPCWSTR result = stemp.c_str();
  334. BOOL ret = PathIsDirectoryEmpty(result);
  335. if (ret)
  336. SHDeleteFolder(file, false);
  337. }
  338. for (iter = vec_back_date_folder.begin(); iter != vec_back_date_folder.end();) {
  339. delete (*iter);
  340. *iter = NULL;
  341. iter = vec_back_date_folder.erase(iter);
  342. }
  343. vec_back_date_folder.clear();
  344. }
  345. }
  346. //剩余空间小于要求值,删除主存储
  347. std::string serial = std::string(vec_src_foldernames.front());
  348. serial = serial.substr(0, serial.find("\\"));
  349. int gb_data = Get_Disk_Free(serial);
  350. int index = 0;
  351. int i = 0;
  352. if (remaining_memory >= gb_data) {
  353. for (auto s : vec_src_foldernames) {
  354. Get_DateFiles(&vec_src_date_folder, s);
  355. if (vec_src_date_folder.size() >= retension_day) {
  356. index = vec_src_date_folder.size() - retension_day;
  357. for (auto d : vec_src_date_folder) {
  358. if (i >= index)
  359. break;
  360. SHDeleteFolder(d,false);
  361. i++;
  362. }
  363. }
  364. std::vector<char*>::iterator iter;
  365. for (iter = vec_src_date_folder.begin(); iter != vec_src_date_folder.end();) {
  366. delete (*iter);
  367. *iter = NULL;
  368. iter = vec_src_date_folder.erase(iter);
  369. }
  370. vec_src_date_folder.clear();
  371. i = 0;
  372. }
  373. }
  374. std::vector<char*>::iterator iter;
  375. for (iter = vec_src_foldernames.begin(); iter != vec_src_foldernames.end();) {
  376. delete (*iter);
  377. *iter = NULL;
  378. iter = vec_src_foldernames.erase(iter);
  379. }
  380. vec_src_foldernames.clear();
  381. for (iter = vec_back_foldernames.begin(); iter != vec_back_foldernames.end();) {
  382. delete (*iter);
  383. *iter = NULL;
  384. iter = vec_back_foldernames.erase(iter);
  385. }
  386. vec_back_foldernames.clear();
  387. }
  388. int ClearRtpFiles::Get_List_File(const char* backup_folder, const char* src_folder)
  389. {
  390. // # read in file list and divide then into trunk ...
  391. rtp_listfile(&list_src_rtpfiles, src_folder);
  392. if (list_src_rtpfiles.empty()) {
  393. BLOG_WARN(fmt::format("[F] *** src_folder file[{}] is empty***", src_folder));
  394. return -1;
  395. }
  396. rtp_listfile(&list_backup_rtpfiles, backup_folder);
  397. if (list_backup_rtpfiles.empty()) {
  398. BLOG_WARN(fmt::format("[F] *** backup_folder file[{}] is empty ***", backup_folder));
  399. return -1;
  400. }
  401. return 1;
  402. }
  403. int ClearRtpFiles::Get_Disk_Free(std::string serial)
  404. {
  405. int pSize = MultiByteToWideChar(CP_OEMCP, 0, serial.c_str(), serial.size() + 1, NULL, 0);
  406. TCHAR* buf = new wchar_t[pSize];
  407. MultiByteToWideChar(CP_OEMCP, 0, serial.c_str(), serial.size() + 1, buf, pSize);
  408. ULARGE_INTEGER available, total, free; //ULARGE_INTEGER 一个64位的无符号整型值
  409. /*if (GetDiskFreeSpaceEx(TEXT("D:"), (ULARGE_INTEGER*)&available, (ULARGE_INTEGER*)&total, (ULARGE_INTEGER*)&free)) {*/
  410. if (GetDiskFreeSpaceEx(buf, (ULARGE_INTEGER*)&available, (ULARGE_INTEGER*)&total, (ULARGE_INTEGER*)&free)) {
  411. //printf(" | 总容量 = %.2f GB,可用空间 = %.2f GB,空闲空间 = %.2f GB\n",GB(total), GB(available), GB(free));
  412. }
  413. else {
  414. BLOG_ERROR(fmt::format("[F] *** failed to Get_Disk_Free ***"));
  415. //puts("获取容量信息失败");
  416. }
  417. int available_ = GB(available);
  418. return available_;
  419. }
  420. void ClearRtpFiles::init()
  421. {
  422. life_worker = new CAppLifeThread();
  423. life_worker->Start();
  424. Start();
  425. }
  426. void ClearRtpFiles::Action()
  427. {
  428. while (!IsAborted()) {
  429. Get_Channels(backup_path.c_str(), src_path.c_str());
  430. /*Get_List_File(backup_path.c_str(), src_path.c_str());*/
  431. /*Identical_file_check();*/
  432. std::this_thread::sleep_for(std::chrono::minutes(checktime));
  433. }
  434. }