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#include "standardpch.h"
7#include "methodcontext.h"
8#include "methodcontextiterator.h"
9
10bool MethodContextIterator::Initialize(const char* fileName)
11{
12 m_hFile = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
13 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
14 if (m_hFile == INVALID_HANDLE_VALUE)
15 {
16 LogError("Failed to open file '%s'. GetLastError()=%u", fileName, GetLastError());
17 return false;
18 }
19
20 LARGE_INTEGER DataTemp;
21 if (GetFileSizeEx(m_hFile, &DataTemp) == 0)
22 {
23 LogError("GetFileSizeEx failed. GetLastError()=%u", GetLastError());
24 CloseHandle(m_hFile);
25 m_hFile = INVALID_HANDLE_VALUE;
26 return false;
27 }
28
29 m_fileSize = DataTemp.QuadPart;
30
31 if (m_progressReport)
32 {
33 m_timer->Start();
34 }
35
36 return true;
37}
38
39bool MethodContextIterator::Destroy()
40{
41 bool ret = true; // assume success
42 if (m_hFile != INVALID_HANDLE_VALUE)
43 {
44 if (!CloseHandle(m_hFile))
45 {
46 LogError("CloseHandle failed. GetLastError()=%u", GetLastError());
47 ret = false;
48 }
49 m_hFile = INVALID_HANDLE_VALUE;
50 }
51 delete m_mc;
52 m_mc = nullptr;
53
54 if (m_index < m_indexCount)
55 {
56 LogWarning("Didn't use all of index count input: %d < %d (i.e., didn't see MC #%d)", m_index, m_indexCount,
57 m_indexes[m_index]);
58 }
59
60 delete m_timer;
61 m_timer = nullptr;
62
63 return ret;
64}
65
66bool MethodContextIterator::MoveNext()
67{
68 if (m_mc != nullptr)
69 {
70 delete m_mc;
71 m_mc = nullptr;
72 }
73
74 while (true)
75 {
76 // Figure out where the pointer is currently.
77 LARGE_INTEGER pos;
78 pos.QuadPart = 0;
79 if (SetFilePointerEx(m_hFile, pos, &m_pos, FILE_CURRENT) == 0)
80 {
81 LogError("SetFilePointerEx failed. GetLastError()=%u", GetLastError());
82 return false; // any failure causes us to bail out.
83 }
84
85 if (m_pos.QuadPart >= m_fileSize)
86 {
87 return false;
88 }
89
90 // Load the current method context.
91 m_methodContextNumber++;
92
93 if (m_progressReport)
94 {
95 if (m_methodContextNumber % 500 == 0)
96 {
97 m_timer->Stop();
98 LogVerbose("Loaded %d at %d per second", m_methodContextNumber,
99 (int)((double)500 / m_timer->GetSeconds()));
100 m_timer->Start();
101 }
102 }
103
104 if (!MethodContext::Initialize(m_methodContextNumber, m_hFile, &m_mc))
105 return false;
106
107 // If we have an array of indexes, skip the loaded indexes that have not been specified.
108
109 if (m_indexCount == -1)
110 {
111 break;
112 }
113 else if (m_index == m_indexCount)
114 {
115 return false; // we're beyond the array of indexes
116 }
117 else if (m_index < m_indexCount)
118 {
119 if (m_indexes[m_index] == m_methodContextNumber)
120 {
121 m_index++;
122 break;
123 }
124 }
125 }
126
127 return true;
128}
129