From 6227652bcf2158df7f52be71106e9264b876fa2a Mon Sep 17 00:00:00 2001 From: Sergey Andreenko Date: Fri, 27 Jul 2018 18:44:32 -0700 Subject: spmi: exclude methods using a file with saved md5 hashes. (#18769) * read md5, linear search for each method. * rewrite with HANDLE * fix linux * do not waste time dumping md5 if no methods exluded --- .../superpmi-shared/methodcontextreader.cpp | 107 +++++++++++++++++++++ .../superpmi/superpmi-shared/methodcontextreader.h | 16 ++- 2 files changed, 118 insertions(+), 5 deletions(-) (limited to 'src/ToolBox') diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp b/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp index a978fa2c2e..ad9c126786 100644 --- a/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp +++ b/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp @@ -116,6 +116,8 @@ MethodContextReader::MethodContextReader( { GetFileSizeEx(this->fileHandle, (PLARGE_INTEGER) & this->fileSize); } + + ReadExcludedMethods(mchFileName); } MethodContextReader::~MethodContextReader() @@ -130,6 +132,8 @@ MethodContextReader::~MethodContextReader() } CloseHandle(this->mutex); + + CleanExcludedMethods(); } bool MethodContextReader::AcquireLock() @@ -477,3 +481,106 @@ MethodContextBuffer MethodContextReader::GetSpecificMethodContext(unsigned int m return MethodContextBuffer(-4); } } + +// Read the file with excluded methods hashes and save them. +void MethodContextReader::ReadExcludedMethods(std::string mchFileName) +{ + excludedMethodsList = nullptr; + + size_t suffix_offset = mchFileName.find_last_of('.'); + if (suffix_offset == std::string::npos) + { + LogError("Failed to get file extension from %s", mchFileName.c_str()); + return; + } + std::string suffix = mchFileName.substr(suffix_offset); + std::string excludeFileName = MethodContextReader::CheckForPairedFile(mchFileName, suffix.c_str(), ".exc"); + + if (excludeFileName.empty()) + { + return; + } + HANDLE excludeFileHandle = OpenFile(excludeFileName.c_str()); + if (excludeFileHandle != INVALID_HANDLE_VALUE) + { + __int64 excludeFileSizeLong; + GetFileSizeEx(excludeFileHandle, (PLARGE_INTEGER)&excludeFileSizeLong); + unsigned excludeFileSize = (unsigned)excludeFileSizeLong; + + char* buffer = new char[excludeFileSize + 1]; + DWORD bytesRead; + bool success = (ReadFile(excludeFileHandle, buffer, excludeFileSize, &bytesRead, NULL) == TRUE); + CloseHandle(excludeFileHandle); + + if (!success || excludeFileSize != bytesRead) + { + LogError("Failed to read the exclude file."); + delete[] buffer; + return; + } + + buffer[excludeFileSize] = 0; + + int counter = 0; + + char* curr = buffer; + while (*curr != 0) + { + while (isspace(*curr)) + { + curr++; + } + + std::string hash; + while (*curr != 0 && !isspace(*curr)) + { + hash += *curr; + curr++; + } + + if (hash.length() == MD5_HASH_BUFFER_SIZE - 1) + { + StringList* node = new StringList(); + node->hash = hash; + node->next = excludedMethodsList; + excludedMethodsList = node; + counter++; + } + else + { + LogInfo("The exclude file contains wrong values: %s.", hash.c_str()); + } + } + delete[] buffer; + LogInfo("Exclude file %s contains %d methods.", excludeFileName.c_str(), counter); + } +} + +// Free memory used for excluded methods. +void MethodContextReader::CleanExcludedMethods() +{ + while (excludedMethodsList != nullptr) + { + StringList* next = excludedMethodsList->next; + delete excludedMethodsList; + excludedMethodsList = next; + } +} + +// Return should this method context be excluded from the replay or not. +bool MethodContextReader::IsMethodExcluded(MethodContext* mc) +{ + if (excludedMethodsList != nullptr) + { + char md5HashBuf[MD5_HASH_BUFFER_SIZE] = {0}; + mc->dumpMethodMD5HashToBuffer(md5HashBuf, MD5_HASH_BUFFER_SIZE); + for (StringList* node = excludedMethodsList; node != nullptr; node = node->next) + { + if (strcmp(node->hash.c_str(), md5HashBuf) == 0) + { + return true; + } + } + } + return false; +} diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.h b/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.h index ab1c693219..41c77d2445 100644 --- a/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.h +++ b/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.h @@ -83,6 +83,13 @@ private: int Offset; int Increment; + struct StringList + { + StringList* next; + std::string hash; + }; + StringList* excludedMethodsList; + // Binary search to get this method number from the index // Returns -1 for not found, or -2 for not indexed __int64 GetOffset(unsigned int methodNumber); @@ -114,6 +121,9 @@ private: // Do we have a valid index? bool hasIndex(); + void ReadExcludedMethods(std::string mchFileName); + void CleanExcludedMethods(); + public: MethodContextReader(const char* inputFileName, const int* indexes = nullptr, @@ -137,11 +147,7 @@ public: } // Return should this method context be excluded from the replay or not. - bool IsMethodExcluded(MethodContext* mc) - { - // Right now it is just a stub. - return false; - } + bool IsMethodExcluded(MethodContext* mc); }; #pragma pack(pop) -- cgit v1.2.3