-
Notifications
You must be signed in to change notification settings - Fork 0
/
sstable.cc
232 lines (190 loc) · 7.42 KB
/
sstable.cc
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
#include "sstable.h"
#include "config.h"
#include "utils.h"
#include <cstdint>
#include <sys/types.h>
// Default Constructor
SStable::SStable(){};
// Constructor from file
SStable::SStable(std::string path){
this->path = path;
// Init the pointers
this->header = new SSTheader(path, 0);
this->bloomFliter = new BloomFilter<uint64_t, sstable_bfSize>(path, sstable_headerSize);
this->index = new SSTIndex(path, sstable_headerSize + sstable_bfSize, header->keyValNum);
// Read the file
std::ifstream inFile(path, std::ios::binary | std::ios::in);
// Get the size
if(inFile){
inFile.seekg(0, std::ios::end);
this->fileSize = inFile.tellg();
inFile.close();
}
}
// Constructor from list
SStable::SStable(
uint64_t setTimeStamp,
std::list <std::pair<uint64_t, std::string> > &list,
std::string setPath, uint64_t curvLogOffset){
this->path = setPath;
this->header = new SSTheader();
this->bloomFliter = new BloomFilter<uint64_t, sstable_bfSize>();
this->index = new SSTIndex();
// Init the offset in vlog
uint64_t vLogOffset = curvLogOffset;
// Set the header and bloom filter
this->header->timeStamp = setTimeStamp;
uint64_t MinKey = UINT64_MAX;
uint64_t MaxKey = 0;
for(auto iter = list.begin(); iter != list.end(); iter++){
// Update the MinKey and MaxKey
MinKey = std::min(MinKey, iter->first);
MaxKey = std::max(MaxKey, iter->first);
// Insert the key and value
this->bloomFliter->insert(iter->first);
this->index->insert(iter->first, vLogOffset, iter->second.size());
// Update the vLogOffset: Magic(1Byte) + Checksum(2Byte) + Key(8Byte) + vlen(4Byte) + Value
vLogOffset += 15 + iter->second.size();
}
this->header->minKey = MinKey;
this->header->maxKey = MaxKey;
this->header->keyValNum = list.size();
// Write the sstable to the file
this->header->writeToFile(setPath, 0);
this->bloomFliter->writeToFile(setPath, sstable_headerSize);
this->index->writeToFile(setPath, sstable_headerSize + sstable_bfSize);
// Read the file again
std::ifstream inFile(setPath, std::ios::binary | std::ios::in);
// Refresh the size
if(inFile){
inFile.seekg(0, std::ios::end);
this->fileSize = inFile.tellg();
inFile.close();
}
}
// Constructor from entries
SStable::SStable(
uint64_t setTimeStamp,
std::map<uint64_t, std::map<uint64_t, uint32_t> > &entriyMap,
std::string setPath, uint64_t curvLogOffset){
this->path = setPath;
this->header = new SSTheader();
this->bloomFliter = new BloomFilter<uint64_t, sstable_bfSize>();
this->index = new SSTIndex();
// Init the offset in vlog
uint64_t vLogOffset = curvLogOffset;
// Set the header and bloom filter
this->header->timeStamp = setTimeStamp;
uint64_t MinKey = UINT64_MAX;
uint64_t MaxKey = 0;
for(auto iter = entriyMap.begin(); iter != entriyMap.end(); iter++){
// Update the MinKey and MaxKey
MinKey = std::min(MinKey, iter->first);
MaxKey = std::max(MaxKey, iter->first);
// Insert the key and value
this->bloomFliter->insert(iter->first);
this->index->insert(iter->first, entriyMap[iter->first].begin()->first, entriyMap[iter->first].begin()->second);
// Update the vLogOffset: Magic(1Byte) + Checksum(2Byte) + Key(8Byte) + vlen(4Byte) + Value
vLogOffset += 15 + iter->second.begin()->second;
}
this->header->minKey = MinKey;
this->header->maxKey = MaxKey;
this->header->keyValNum = entriyMap.size();
// Write the sstable to the file
this->header->writeToFile(setPath, 0);
this->bloomFliter->writeToFile(setPath, sstable_headerSize);
this->index->writeToFile(setPath, sstable_headerSize + sstable_bfSize);
// Read the file again
std::ifstream inFile(setPath, std::ios::binary | std::ios::in);
if(inFile){
inFile.seekg(0, std::ios::end);
this->fileSize = inFile.tellg();
inFile.close();
}
}
// Destructor
SStable::~SStable(){
delete this->header;
delete this->bloomFliter;
delete this->index;
}
// Clear all the data
void SStable::clear(){
utils::rmfile(this->path.c_str());
}
// Get the target from the sstable
uint64_t SStable::getSStableTimeStamp(){
return this->header->timeStamp;
}
uint64_t SStable::getSStableMinKey(){
return this->header->minKey;
}
uint64_t SStable::getSStableMaxKey(){
return this->header->maxKey;
}
uint64_t SStable::getSStableKeyValNum(){
return this->header->keyValNum;
}
uint32_t SStable::getSStableKeyVlen(uint64_t index){
return this->index->getVlen(index);
}
uint64_t SStable::getSStableKeyOffset(uint64_t index){
return this->index->getOffset(index);
}
uint64_t SStable::getSStableKey(uint64_t index){
return this->index->getKey(index);
}
uint64_t SStable::getKeyIndexByKey(uint64_t key){
return this->index->getIndex(key);
}
// Check if the key exists
bool SStable::checkIfKeyExist(uint64_t targetKey){
// Check if the key is within the range
if(targetKey < this->header->minKey || targetKey > this->header->maxKey)
return false;
// Check if the key exists in the bloom filter
return this->bloomFliter->find(targetKey);
}
// Scan the sstable
void SStable::scan(uint64_t key1, uint64_t key2, std::map<uint64_t, std::map<uint64_t, std::string> > &scanMap, vLog vlog){
uint32_t startKeyIndex = this->getKeyIndexByKey(key1);
// Check if the key exists
if(startKeyIndex == UINT32_MAX)
return;
// Get the current timestamp
uint64_t curSStabelTimeStamp = this->getSStableTimeStamp();
for (size_t i = startKeyIndex; i < this->getSStableKeyValNum(); i++)
{
uint64_t curKey = this->index->getKey(i);
if(curKey > key2)
break;
// If the key does not exist in the scanMap, insert it
if(scanMap.count(curKey) == 0 || scanMap[curKey].size() == 0){
uint64_t targetOffset = this->getSStableKeyOffset(i);
uint32_t targetLength = this->getSStableKeyVlen(i);
std::string val = vlog.getValFromFile(vlog.getPath(), targetOffset, targetLength);
if(val != delete_tag)
scanMap[curKey][curSStabelTimeStamp] = val;
}
else{
// If the key exists in the scanMap, check the timestamp
auto iterLatestKV = scanMap[curKey].end();
iterLatestKV--;
// Cover the old value if the timestamp is larger
uint64_t targetOffset = this->getSStableKeyOffset(i);
uint32_t targetLength = this->getSStableKeyVlen(i);
std::string val = vlog.getValFromFile(vlog.getPath(), targetOffset, targetLength);
if(curSStabelTimeStamp >= iterLatestKV->first){
if(val != delete_tag){
// Delete the old value to save space
scanMap[curKey].clear();
scanMap[curKey][curSStabelTimeStamp] = val;
}
// Clear all the old values if the new value is deleted
else
scanMap[curKey].clear();
}
// Do nothing if the timestamp is smaller
}
}
}