summaryrefslogtreecommitdiff
path: root/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.h
blob: e9ee45111546d16c24e930636fe07ae31eff9cbe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

//----------------------------------------------------------
// MethodContextReader.h - Abstraction for reading MethodContexts
//                         Should eventually support multithreading
//----------------------------------------------------------
#ifndef _MethodContextReader
#define _MethodContextReader

#include "methodcontext.h"
#include "tocfile.h"

struct MethodContextBuffer
{
private:
    static const int Completed = 0x1234abcd;

public:
    unsigned char* buff;
    DWORD          size;

    MethodContextBuffer() : buff(nullptr), size(Completed)
    {
    }
    MethodContextBuffer(DWORD error) : buff(nullptr), size(error)
    {
    }
    MethodContextBuffer(unsigned char* b, DWORD e) : buff(b), size(e)
    {
    }

    bool allDone()
    {
        return size == Completed && buff == nullptr;
    }
    bool Error()
    {
        return size != 0 && size != Completed && buff == nullptr;
    }
};

// The pack(4) directive is so that each entry is 12 bytes, intead of 16
#pragma pack(push)
#pragma pack(4)
class MethodContextReader
{
private:
    // The MC/MCH file
    HANDLE fileHandle;

    // The size of the MC/MCH file
    __int64 fileSize;

    // Current MC index in the input MC/MCH file
    int curMCIndex;

    // The synchronization mutex
    HANDLE mutex;
    bool   AcquireLock();
    void   ReleaseLock();

    TOCFile tocFile;

    // Method ranges to process
    // If you have an index file, these things get processed
    // much faster, now
    const int* Indexes;
    int        IndexCount;
    int        curIndexPos;

    // Method hash to process
    // If you have an index file, these things get processed
    // much faster, now
    char* Hash;
    int   curTOCIndex;

    // Offset/increment if running in parallel mode
    // If you have an index file, these things get processed
    // much faster, now
    int Offset;
    int Increment;

    // 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);

    // Just a helper...
    static HANDLE OpenFile(const char* inputFile, DWORD flags = FILE_ATTRIBUTE_NORMAL);

    MethodContextBuffer ReadMethodContextNoLock(bool justSkip = false);
    MethodContextBuffer ReadMethodContext(bool acquireLock, bool justSkip = false);
    MethodContextBuffer GetSpecificMethodContext(unsigned int methodNumber);

    MethodContextBuffer GetNextMethodContextFromIndexes();
    MethodContextBuffer GetNextMethodContextFromHash();
    MethodContextBuffer GetNextMethodContextFromOffsetIncrement();
    MethodContextBuffer GetNextMethodContextHelper();

    // Looks for a file named foo.origSuffix.newSuffix or foo.newSuffix
    // but only if foo.origSuffix exists
    static std::string CheckForPairedFile(const std::string& fileName,
                                          const std::string& origSuffix,
                                          const std::string& newSuffix);

    // are we're at the end of the file...
    bool atEof();

    // Do we have a valid TOC?
    bool hasTOC();

    // Do we have a valid index?
    bool hasIndex();

public:
    MethodContextReader(const char* inputFileName,
                        const int*  indexes    = nullptr,
                        int         indexCount = -1,
                        char*       hash       = nullptr,
                        int         offset     = -1,
                        int         increment  = -1);
    ~MethodContextReader();

    // Read a method context buffer from the ContextCollection
    // (either a hive [single] or an index)
    MethodContextBuffer GetNextMethodContext();
    // No C++ exceptions, so the constructor has to always succeed...
    bool   isValid();
    double PercentComplete();

    // Returns the index of the last MethodContext read by GetNextMethodContext
    inline int GetMethodContextIndex()
    {
        return curMCIndex;
    }
};
#pragma pack(pop)

#endif