1//
2// Copyright (c) Microsoft. All rights reserved.
3// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4//
5
6//----------------------------------------------------------
7// MethodContextReader.h - Abstraction for reading MethodContexts
8// Should eventually support multithreading
9//----------------------------------------------------------
10#ifndef _MethodContextReader
11#define _MethodContextReader
12
13#include "methodcontext.h"
14#include "tocfile.h"
15
16struct MethodContextBuffer
17{
18private:
19 static const int Completed = 0x1234abcd;
20
21public:
22 unsigned char* buff;
23 DWORD size;
24
25 MethodContextBuffer() : buff(nullptr), size(Completed)
26 {
27 }
28 MethodContextBuffer(DWORD error) : buff(nullptr), size(error)
29 {
30 }
31 MethodContextBuffer(unsigned char* b, DWORD e) : buff(b), size(e)
32 {
33 }
34
35 bool allDone()
36 {
37 return size == Completed && buff == nullptr;
38 }
39 bool Error()
40 {
41 return size != 0 && size != Completed && buff == nullptr;
42 }
43};
44
45// The pack(4) directive is so that each entry is 12 bytes, intead of 16
46#pragma pack(push)
47#pragma pack(4)
48class MethodContextReader
49{
50private:
51 // The MC/MCH file
52 HANDLE fileHandle;
53
54 // The size of the MC/MCH file
55 __int64 fileSize;
56
57 // Current MC index in the input MC/MCH file
58 int curMCIndex;
59
60 // The synchronization mutex
61 HANDLE mutex;
62 bool AcquireLock();
63 void ReleaseLock();
64
65 TOCFile tocFile;
66
67 // Method ranges to process
68 // If you have an index file, these things get processed
69 // much faster, now
70 const int* Indexes;
71 int IndexCount;
72 int curIndexPos;
73
74 // Method hash to process
75 // If you have an index file, these things get processed
76 // much faster, now
77 char* Hash;
78 int curTOCIndex;
79
80 // Offset/increment if running in parallel mode
81 // If you have an index file, these things get processed
82 // much faster, now
83 int Offset;
84 int Increment;
85
86 struct StringList
87 {
88 StringList* next;
89 std::string hash;
90 };
91 StringList* excludedMethodsList;
92
93 // Binary search to get this method number from the index
94 // Returns -1 for not found, or -2 for not indexed
95 __int64 GetOffset(unsigned int methodNumber);
96
97 // Just a helper...
98 static HANDLE OpenFile(const char* inputFile, DWORD flags = FILE_ATTRIBUTE_NORMAL);
99
100 MethodContextBuffer ReadMethodContextNoLock(bool justSkip = false);
101 MethodContextBuffer ReadMethodContext(bool acquireLock, bool justSkip = false);
102 MethodContextBuffer GetSpecificMethodContext(unsigned int methodNumber);
103
104 MethodContextBuffer GetNextMethodContextFromIndexes();
105 MethodContextBuffer GetNextMethodContextFromHash();
106 MethodContextBuffer GetNextMethodContextFromOffsetIncrement();
107 MethodContextBuffer GetNextMethodContextHelper();
108
109 // Looks for a file named foo.origSuffix.newSuffix or foo.newSuffix
110 // but only if foo.origSuffix exists
111 static std::string CheckForPairedFile(const std::string& fileName,
112 const std::string& origSuffix,
113 const std::string& newSuffix);
114
115 // are we're at the end of the file...
116 bool atEof();
117
118 // Do we have a valid TOC?
119 bool hasTOC();
120
121 // Do we have a valid index?
122 bool hasIndex();
123
124 void ReadExcludedMethods(std::string mchFileName);
125 void CleanExcludedMethods();
126
127public:
128 MethodContextReader(const char* inputFileName,
129 const int* indexes = nullptr,
130 int indexCount = -1,
131 char* hash = nullptr,
132 int offset = -1,
133 int increment = -1);
134 ~MethodContextReader();
135
136 // Read a method context buffer from the ContextCollection
137 // (either a hive [single] or an index)
138 MethodContextBuffer GetNextMethodContext();
139 // No C++ exceptions, so the constructor has to always succeed...
140 bool isValid();
141 double PercentComplete();
142
143 // Returns the index of the last MethodContext read by GetNextMethodContext
144 inline int GetMethodContextIndex()
145 {
146 return curMCIndex;
147 }
148
149 // Return should this method context be excluded from the replay or not.
150 bool IsMethodExcluded(MethodContext* mc);
151};
152#pragma pack(pop)
153
154#endif
155