summaryrefslogtreecommitdiff
path: root/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.h
blob: 0068fa231fcbdd8290c168dd7bd0fe7d7ce5974f (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
//
// 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