OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <windows.h> |
| 6 |
| 7 #include <shlwapi.h> |
| 8 #include <stdio.h> |
| 9 #include <tchar.h> |
| 10 |
| 11 #include <algorithm> |
| 12 #include <iostream> |
| 13 #include <sstream> |
| 14 #include <string> |
| 15 |
| 16 #pragma warning(disable : 4996) |
| 17 |
| 18 // Create |count| number of temp files at |folder_path| using GUID based method. |
| 19 // The time cost in millisecond of creating every 500 temp files or all the |
| 20 // files if |count| < 500 is printed to the console. |
| 21 bool CreateFilesUsingGuid(UINT count, const char* folder_path); |
| 22 |
| 23 // Create |count| number of temp files at |folder_path| using GetTempFileName() |
| 24 // API. The time cost in millisecond of creating every 500 temp files or all the |
| 25 // files if |count| < 500 is printed to the console. |
| 26 bool CreateFilesUsingGetTempFileName(UINT count, const char* folder_path); |
| 27 |
| 28 // This method converts GUID to a string. |
| 29 char* ConvertGuidToString(const GUID* id, char* out); |
| 30 |
| 31 // If |folder_path| doesn't exist, creat it, otherwise check if it is empty. |
| 32 bool CreateOrValidateTempDirectory(const char* folder_path); |
| 33 |
| 34 // Deletes all the content in |folder_path|. |
| 35 void DeleteDirectoryContent(const char* folder_path); |
| 36 |
| 37 // Deletes |folder_path| including its contents and the raw directory. |
| 38 bool DeleteDirectory(const char* folder_path); |
| 39 |
| 40 // Deletes |folder_path| including its contents and the raw directory, and print |
| 41 // the delete status to the console. |
| 42 void DeleteDirectoryAndPrintMsg(const char* folder_path); |
| 43 |
| 44 // Prints the elapsed time at current step for the latest cycle. |
| 45 void FormatPrintElapsedTime(UINT cur_step, |
| 46 UINT total_step, |
| 47 const LARGE_INTEGER& elapsed_ms); |
| 48 |
| 49 // Maximum number of temp files allowed to create. This is limited by the |
| 50 // implementation of GetTempFileName(). |
| 51 // "This limits GetTempFileName to a maximum of 65,535 unique file names if the |
| 52 // lpPathName and lpPrefixString parameters remain the same." |
| 53 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364991(v=vs.85).as
px |
| 54 UINT kMaxFileCreate = 65535; |
| 55 |
| 56 // Query the time cost each time when this amount of temp files are created. |
| 57 UINT kFileCountPerMetric = 500; |
| 58 |
| 59 int main() { |
| 60 // Gets the temp path env string. |
| 61 DWORD temp_path_ret = 0; |
| 62 CHAR temp_folder_path[MAX_PATH]; |
| 63 temp_path_ret = ::GetTempPathA(MAX_PATH, temp_folder_path); |
| 64 if (temp_path_ret > MAX_PATH || temp_path_ret == 0) { |
| 65 std::cout << "GetTempPath failed" << std::endl; |
| 66 return 0; |
| 67 } |
| 68 |
| 69 // A temporary directory where the new temp files created by GetTempFileName() |
| 70 // are written. |
| 71 std::string temp_dir_gettempfilename( |
| 72 std::string(temp_folder_path).append("TempDirGetTempFileName\\")); |
| 73 |
| 74 // A temporary directory where the new temp files created by Guid-based method |
| 75 // are written. |
| 76 std::string temp_dir_guid( |
| 77 std::string(temp_folder_path).append("TempDirGuid\\")); |
| 78 |
| 79 UINT file_create_count; |
| 80 std::string user_input; |
| 81 |
| 82 while (true) { |
| 83 std::cout << "\nPlease enter # of files to create (maximum " |
| 84 << kMaxFileCreate << "), or \"quit\" to end the program : "; |
| 85 std::getline(std::cin, user_input); |
| 86 |
| 87 std::transform(user_input.begin(), user_input.end(), user_input.begin(), |
| 88 ::tolower); |
| 89 if (user_input == "quit") |
| 90 break; |
| 91 |
| 92 std::cout << std::endl; |
| 93 std::stringstream ss(user_input); |
| 94 |
| 95 if (ss >> file_create_count && file_create_count <= kMaxFileCreate) { |
| 96 std::cout << "\nPlease select method to create temp file names,\n" |
| 97 << "\"t\" for GetTempFileName \n" |
| 98 << "\"g\" for GUID-based \n" |
| 99 << "\"b\" for both \n" |
| 100 << "or \"quit\" to end the program : "; |
| 101 std::getline(std::cin, user_input); |
| 102 |
| 103 std::transform(user_input.begin(), user_input.end(), user_input.begin(), |
| 104 ::tolower); |
| 105 if (user_input == "quit") |
| 106 break; |
| 107 |
| 108 if (user_input == "t" || user_input == "b") { |
| 109 std::cout << "\nGetTempFileName Performance:\n [start - end] / total " |
| 110 "--- time " |
| 111 "cost in ms" |
| 112 << std::endl; |
| 113 if (CreateFilesUsingGetTempFileName(file_create_count, |
| 114 temp_dir_gettempfilename.c_str())) { |
| 115 std::cout << "File creation succeeds at " << temp_dir_gettempfilename |
| 116 << ", now clean all of them!" << std::endl; |
| 117 } |
| 118 DeleteDirectoryAndPrintMsg(temp_dir_gettempfilename.c_str()); |
| 119 } |
| 120 |
| 121 if (user_input == "g" || user_input == "b") { |
| 122 std::cout << "\nGUID-based Performance:\n [start - end] / total --- " |
| 123 "time cost in ms" |
| 124 << std::endl; |
| 125 if (CreateFilesUsingGuid(file_create_count, temp_dir_guid.c_str())) { |
| 126 std::cout << "File creation succeeds at " << temp_dir_guid |
| 127 << ", now clean all of them!" << std::endl; |
| 128 } |
| 129 DeleteDirectoryAndPrintMsg(temp_dir_guid.c_str()); |
| 130 } |
| 131 } else { |
| 132 std::cout << "Input number is invalid, please enter # of files to create " |
| 133 "(maximum " |
| 134 << kMaxFileCreate << "), or \"quit\" to end the program : "; |
| 135 } |
| 136 std::cout << std::endl; |
| 137 } |
| 138 return 0; |
| 139 } |
| 140 |
| 141 bool CreateFilesUsingGuid(UINT count, const char* dir_path) { |
| 142 if (!CreateOrValidateTempDirectory(dir_path)) |
| 143 return false; |
| 144 |
| 145 LARGE_INTEGER starting_time, ending_time, elapsed_ms; |
| 146 ::QueryPerformanceCounter(&starting_time); |
| 147 LARGE_INTEGER frequency; |
| 148 ::QueryPerformanceFrequency(&frequency); |
| 149 |
| 150 for (UINT i = 1; i <= count; ++i) { |
| 151 GUID guid; |
| 152 ::CoCreateGuid(&guid); |
| 153 char buffer[37]; |
| 154 ConvertGuidToString(&guid, buffer); |
| 155 std::string temp_name = std::string(dir_path).append(buffer).append(".tmp"); |
| 156 |
| 157 HANDLE file_handle = |
| 158 ::CreateFileA(temp_name.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, |
| 159 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
| 160 ::CloseHandle(file_handle); |
| 161 |
| 162 if (i % kFileCountPerMetric == 0 || i == count) { |
| 163 ::QueryPerformanceCounter(&ending_time); |
| 164 // Convert the elapsed number of ticks to milliseconds. |
| 165 elapsed_ms.QuadPart = (ending_time.QuadPart - starting_time.QuadPart) * |
| 166 1000 / frequency.QuadPart; |
| 167 |
| 168 FormatPrintElapsedTime(i, count, elapsed_ms); |
| 169 |
| 170 ::QueryPerformanceCounter(&starting_time); |
| 171 } |
| 172 } |
| 173 return true; |
| 174 } |
| 175 |
| 176 bool CreateFilesUsingGetTempFileName(UINT count, const char* dir_path) { |
| 177 if (!CreateOrValidateTempDirectory(dir_path)) |
| 178 return false; |
| 179 |
| 180 CHAR temp_name[MAX_PATH]; |
| 181 LARGE_INTEGER starting_time, ending_time, elapsed_ms; |
| 182 ::QueryPerformanceCounter(&starting_time); |
| 183 LARGE_INTEGER frequency; |
| 184 ::QueryPerformanceFrequency(&frequency); |
| 185 |
| 186 for (UINT i = 1; i <= count; ++i) { |
| 187 ::GetTempFileNameA(dir_path, "", 0, temp_name); |
| 188 if (i % kFileCountPerMetric == 0 || i == count) { |
| 189 ::QueryPerformanceCounter(&ending_time); |
| 190 // Convert the elapsed number of ticks to milliseconds. |
| 191 elapsed_ms.QuadPart = (ending_time.QuadPart - starting_time.QuadPart) * |
| 192 1000 / frequency.QuadPart; |
| 193 |
| 194 FormatPrintElapsedTime(i, count, elapsed_ms); |
| 195 |
| 196 ::QueryPerformanceCounter(&starting_time); |
| 197 } |
| 198 } |
| 199 return true; |
| 200 } |
| 201 |
| 202 char* ConvertGuidToString(const GUID* id, char* out) { |
| 203 int i; |
| 204 char* ret = out; |
| 205 out += sprintf(out, "%.8lX-%.4hX-%.4hX-", id->Data1, id->Data2, id->Data3); |
| 206 for (i = 0; i < sizeof(id->Data4); ++i) { |
| 207 out += sprintf(out, "%.2hhX", id->Data4[i]); |
| 208 if (i == 1) |
| 209 *(out++) = '-'; |
| 210 } |
| 211 return ret; |
| 212 } |
| 213 |
| 214 bool CreateOrValidateTempDirectory(const char* folder_path) { |
| 215 if (::PathFileExistsA(folder_path)) { |
| 216 if (!::PathIsDirectoryEmptyA(folder_path)) { |
| 217 std::cout << folder_path |
| 218 << " directory is not empty, please remove all its content."; |
| 219 return false; |
| 220 } |
| 221 return true; |
| 222 } else if (::CreateDirectoryA(folder_path, NULL) == 0) { |
| 223 std::cout << folder_path << "directory creation fails."; |
| 224 return false; |
| 225 } else { |
| 226 return true; |
| 227 } |
| 228 } |
| 229 |
| 230 void DeleteDirectoryContent(const char* folder_path) { |
| 231 char file_found[MAX_PATH]; |
| 232 WIN32_FIND_DATAA info; |
| 233 HANDLE hp; |
| 234 sprintf(file_found, "%s\\*.*", folder_path); |
| 235 hp = ::FindFirstFileA(file_found, &info); |
| 236 do { |
| 237 if ((strcmp(info.cFileName, ".") == 0) || |
| 238 (strcmp(info.cFileName, "..") == 0)) { |
| 239 continue; |
| 240 } |
| 241 sprintf(file_found, "%s\\%s", folder_path, info.cFileName); |
| 242 ::DeleteFileA(file_found); |
| 243 } while (::FindNextFileA(hp, &info)); |
| 244 ::FindClose(hp); |
| 245 } |
| 246 |
| 247 bool DeleteDirectory(const char* folder_path) { |
| 248 DeleteDirectoryContent(folder_path); |
| 249 return ::RemoveDirectoryA(folder_path) != 0; |
| 250 } |
| 251 |
| 252 void DeleteDirectoryAndPrintMsg(const char* folder_path) { |
| 253 if (DeleteDirectory(folder_path)) { |
| 254 std::cout << folder_path << " directory is deleted!" << std::endl; |
| 255 } else { |
| 256 std::cout << "[Attention] " << folder_path |
| 257 << " directory's deletion fails, please take a look by yourself!" |
| 258 << std::endl; |
| 259 } |
| 260 } |
| 261 |
| 262 void FormatPrintElapsedTime(UINT cur_step, |
| 263 UINT total_step, |
| 264 const LARGE_INTEGER& elapsed_ms) { |
| 265 UINT count_prev = 0; |
| 266 if (cur_step % kFileCountPerMetric == 0) |
| 267 count_prev = cur_step + 1 - kFileCountPerMetric; |
| 268 else if (cur_step > kFileCountPerMetric) |
| 269 count_prev = cur_step / kFileCountPerMetric * kFileCountPerMetric + 1; |
| 270 printf(" [%5d - %5d] / %d --- %lld\n", count_prev, cur_step, total_step, |
| 271 elapsed_ms.QuadPart); |
| 272 } |
OLD | NEW |