-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBufferManager.cpp
More file actions
270 lines (263 loc) · 5.63 KB
/
BufferManager.cpp
File metadata and controls
270 lines (263 loc) · 5.63 KB
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
#include "extmem.h"
#include "BufferManager.h"
#include <unordered_map>
#include <list>
#include <iostream>
BufferManager::BufferManager(size_t bufSize, size_t blkSize)
{
initBuffer(bufSize, blkSize, &buffer);
}
BufferManager::~BufferManager()
{
for (auto p : LUT)
if (p.second.second)
writeBlockToDisk(p.second.first, p.first, &buffer);
freeBuffer(&buffer);
}
bool BufferManager::full()
{
return buffer.bufSize < (1+LUT.size())*(1 + buffer.blkSize);
}
bool BufferManager::write(unsigned addr)
{
if (LUT.find(addr) == LUT.end())
{
std::cerr << "ERROR: " << addr << " has been swapped\n" << std::endl;
return false;
}
return LUT[addr].second = true;
}
int BufferManager::getNumIO()
{
return buffer.numIO;
}
unsigned BufferManager::getBlkSize()
{
return buffer.blkSize;
}
FIFOBufMgr::FIFOBufMgr(size_t bufSize, size_t blkSize) :BufferManager(bufSize, blkSize) {}
unsigned char* FIFOBufMgr::get(unsigned addr)
{
return doGetBlk(false, addr);
}
int FIFOBufMgr::drop(unsigned addr)
{
if (LUT.find(addr) != LUT.end())
{
q.erase(pos[addr]);
pos.erase(addr);
freeBlockInBuffer(LUT[addr].first, &buffer);
LUT.erase(addr);
}
return dropBlockOnDisk(addr);
}
unsigned char* FIFOBufMgr::read(unsigned addr)
{
return doGetBlk(true, addr);
}
void FIFOBufMgr::swap()
{
if (q.empty()) return;
unsigned out = q.front();
//移除队首
q.pop_front();
//写回磁盘
if (LUT[out].second)
{
writeBlockToDisk(LUT[out].first, out, &buffer);
}
//释放空间
freeBlockInBuffer(LUT[out].first, &buffer);
//删去记录
LUT.erase(out);
pos.erase(out);
}
unsigned char* FIFOBufMgr::doGetBlk(bool type, unsigned addr)
{
//在缓存中
if (LUT.find(addr) != LUT.end())
{
q.erase(pos[addr]);
q.push_back(addr);
pos[addr] = --q.end();
return LUT[addr].first;
}
//不在缓存中,缓存满,进行替换
if (full())
{
swap();
}
//更新调度队列
q.push_back(addr);
pos[addr] = --q.end();
//从磁盘读入缓存或者申请一新磁盘块
unsigned char* blk = type ? readBlockFromDisk(addr, &buffer) : getNewBlockInBuffer(&buffer);
//新增一条记录
LUT[addr] = { blk, false };
return blk;
}
LRUBufMgr::LRUBufMgr(size_t bufSize, size_t blkSize) :BufferManager(bufSize, blkSize) {}
unsigned char * LRUBufMgr::read(unsigned addr)
{
return doGetBlk(true, addr);
}
unsigned char* LRUBufMgr::get(unsigned addr)
{
return doGetBlk(false, addr);
}
int LRUBufMgr::drop(unsigned addr)
{
if (LUT.find(addr) != LUT.end())
{
//minFreq,freq,pos,queue,LUT
int fr = freq[addr];
freq.erase(addr);
queue[fr].erase(pos[addr]);
if (queue[fr].empty() && fr == minFreq)
{
if (LUT.size() == 1)
{
minFreq = 0;
}
else
{
for (minFreq = fr + 1; queue[minFreq].empty(); ++minFreq);
}
}
pos.erase(addr);
freeBlockInBuffer(LUT[addr].first, &buffer);
LUT.erase(addr);
}
return dropBlockOnDisk(addr);
}
void LRUBufMgr::swap()
{
unsigned out = queue[minFreq].front();
//写回磁盘
if (LUT[out].second)
{
writeBlockToDisk(LUT[out].first, out, &buffer);
}
//释放缓冲区
freeBlockInBuffer(LUT[out].first, &buffer);
//删去LUT中的记录
LUT.erase(out);
//删去freq/pos/queue中的记录
freq.erase(out);
pos.erase(out);
queue[minFreq].pop_front(); //minFreq将由后续程序更新(=1)
//std::cout << "**************swap " << out << std::endl;
}
unsigned char* LRUBufMgr::doGetBlk(bool type, unsigned addr)
{
//缓存命中
if (LUT.find(addr) != LUT.end())
{
//更新调度数据结构
int fr = freq[addr]++;
queue[fr].erase(pos[addr]);
queue[fr + 1].push_back(addr);
pos[addr] = --queue[fr + 1].end();
if (queue[fr].empty() && fr == minFreq)
{
minFreq = fr + 1;
}
return LUT[addr].first;
}
//不在缓冲区中
if (full()) //需要进行替换
{
swap();
}
freq[addr] = 1;
minFreq = 1;
queue[1].push_back(addr);
pos[addr] = --queue[1].end();
unsigned char *blk = type ? readBlockFromDisk(addr, &buffer) : getNewBlockInBuffer(&buffer);
LUT[addr] = { blk, false };
return blk;
}
MRUBufMgr::MRUBufMgr(size_t bufSize, size_t blkSize) :BufferManager(bufSize, blkSize) {}
unsigned char * MRUBufMgr::read(unsigned addr)
{
return doGetBlk(true, addr);
}
unsigned char * MRUBufMgr::get(unsigned addr)
{
return doGetBlk(false, addr);
}
int MRUBufMgr::drop(unsigned addr)
{
if (LUT.find(addr) != LUT.end())
{
//minFreq,freq,pos,queue,LUT
int fr = freq[addr];
freq.erase(addr);
queue[fr].erase(pos[addr]);
if (queue[fr].empty() && fr == maxFreq)
{
if (LUT.size() == 1)
{
maxFreq = 0;
}
else
{
for (maxFreq = fr - 1; maxFreq > 0 && queue[maxFreq].empty(); --maxFreq);
}
}
pos.erase(addr);
freeBlockInBuffer(LUT[addr].first, &buffer);
LUT.erase(addr);
}
return dropBlockOnDisk(addr);
}
void MRUBufMgr::swap()
{
unsigned out = queue[maxFreq].front();
//写回磁盘
if (LUT[out].second)
{
writeBlockToDisk(LUT[out].first, out, &buffer);
}
//释放缓冲区
freeBlockInBuffer(LUT[out].first, &buffer);
//删去LUT中的记录
LUT.erase(out);
//删去freq/pos/queue中的记录
freq.erase(out);
pos.erase(out);
queue[maxFreq].pop_front();
//更新maxFreq
for (; maxFreq > 0 && queue[maxFreq].empty(); --maxFreq);
//std::cout << "**************swap " << out << std::endl;
}
unsigned char * MRUBufMgr::doGetBlk(bool type, unsigned addr)
{
//缓存命中
if (LUT.find(addr) != LUT.end())
{
//更新调度数据结构
int fr = freq[addr]++;
queue[fr].erase(pos[addr]);
queue[fr + 1].push_back(addr);
pos[addr] = --queue[fr + 1].end();
if (fr == maxFreq)
{
++maxFreq;
}
return LUT[addr].first;
}
//不在缓冲区中
if (full()) //需要进行替换
{
swap();
}
freq[addr] = 1;
if (!maxFreq)
maxFreq = 1;
queue[1].push_back(addr);
pos[addr] = --queue[1].end();
unsigned char *blk = type ? readBlockFromDisk(addr, &buffer) : getNewBlockInBuffer(&buffer);
LUT[addr] = { blk, false };
return blk;
}