-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathclasses.h
319 lines (297 loc) · 10.4 KB
/
classes.h
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
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <sstream>
#include <math.h>
#include <bitset>
#include <algorithm>
#include <tuple>
using namespace std;
const int PAGE_SIZE = 4096;
const float FILL_FACT = 0.70;//fill till 70%
int* p = NULL;
class Record {
public:
int id, manager_id;
std::string bio, name;
Record(vector<std::string> fields) {
id = stoi(fields[0]);
name = fields[1];
bio = fields[2];
manager_id = stoi(fields[3]);
}
void print() {
cout << "\tID: " << id << "\n";
cout << "\tNAME: " << name << "\n";
cout << "\tBIO: " << bio << "\n";
cout << "\tMANAGER_ID: " << manager_id << "\n";
}
};
class LinearHashIndex {
private:
vector<int> pageDirectory;
int overFlow = 0;
int array[2];
// int Thisline = 0; // current line in the file
string fName;
// indexfile
fstream files;
int watch=0;
//Do the hashing
void hash(Record record, bool isRearrange){
bool bitflip = false;
string line,word;
files.open(fName);
int cont;
int iBlock;//hash number with or without bitflip
int posBlock, posWrite; //posotion of the block, position of the (block +size of line)
bool isBitFlip = false;
bool ban=true;
int hashNumber = record.id % 16; //hash index
int pos; // to get the position were the record will be storage
bitset<16> number(hashNumber); //transform it to bits
if(!isRearrange){
if (!(std::find(pageDirectory.begin(), pageDirectory.end(), hashNumber) != pageDirectory.end())) {
number.flip(1); //if the index is not in the hash, change the 2nd bit
int mybit_int = (int)(number.to_ulong()); //transform that bit to number
if (!(std::find(pageDirectory.begin(), pageDirectory.end(), mybit_int) != pageDirectory.end())) {
pageDirectory.push_back(hashNumber);//check if this new number is in the intex, if it is not, create new index
iBlock = hashNumber; //get the position for that new index
}
else{
iBlock = mybit_int; // if when the flipping happends it found it, then the position will be hte one with the bit flip
isBitFlip = true;
}
}else{
iBlock= hashNumber; // if it found it the position will be in the hash number
}
}else{// if isRearrange == true. (Redoing hashing, don't even consider overflip)
iBlock= hashNumber;
cout<<"DoingBFcase / rearrange \n";
}
string rec = std::to_string(record.id) + "," + record.name + "," +record.bio + "," +std::to_string(record.manager_id) + "$#";
while(ban){
//files.seekg(pos*PAGE_SIZE);
posBlock = (iBlock+cont*16)*PAGE_SIZE;
files.seekg(posBlock);
files.tellg();
if(files.peek() == std::ifstream::traits_type::eof() ||files.peek() == '\0'){//if the line is empty
files.seekg(posBlock);//look at the position
posWrite=posBlock;
//cout<<"entro aqui cuando no hay nada en la linea\n";
ban=false;
}else{//if it's not empty
if(getline(files, line,'#')){//get the line at that position of the block
stringstream s(line);
int found = line.find_first_not_of('\0');//cutting the nulls
string newLine = line.substr(found,line.size());//trim the line without the nulls
files.seekg(posBlock+newLine.size());//get the position were the new record would be storage
files.tellg();//positioned in that position
if((newLine.size()+rec.size()) <= FILL_FACT*PAGE_SIZE){//checking if the new record can fit in the block
//files <<rec;
posWrite=posBlock+newLine.size();
// cout<<"position: "<<files.tellg()<<"record: "<<rec<<endl;
ban=false;
}
else{
// may vary if there are 2 or more blocks per index
if (line.size() > PAGE_SIZE|| line.size()==0){ //, if size from beggining to end charachter is greater than PAGE_SIZE, then the block was empty
//if the page is still not empty
posWrite = posBlock;
//cout<<"page was empty: "<<cont<<endl;
ban=false;
}
else{
// if it was a real overflow (not from bitflip)
if (isBitFlip == false){
// do overflow. Repeat process for iBlock+cont*16
cout << "overflow (no bitflip). try next page. Curr page count: "<<cont << endl;
cont++;
//cout<< line<<endl;
posWrite = -1;
}
// if it was an overflow due to bitflip
else{
bitset<16> change(iBlock);
change.flip(1);
int changy = (int)(change.to_ulong());
pageDirectory.push_back(changy);//now the numbers have to be put on the index
cout << cont << "*overflow due to bitflip*. First do new hash. Then send to rearrange in a loop. "<<endl;
// sent it to do hash again but with out option to due bitflip.
files.close();
hash(record, true);
posWrite = -1; // do not write anything extra for this run. It was written.
cout << "\n\n \t\t*****Start overflow with bitflip. -> rearrange \n";
// take line records from all the pages for the given hash
for (int sheet = 0; sheet <= cont; sheet++) {
// get line for the sheet
files.open(fName, ios::out|ios::in);
posBlock = (iBlock+sheet*16)*PAGE_SIZE; // may vary if there are 2 or more blocks per index. FIX LATER
files.seekp(posBlock);
getline(files, line,'#');
//cout<< line<<endl;
// clean the line
files.seekp(posBlock);
for (int xc = 0; xc <=line.size(); xc++) {files.put('\0');}
//cout << "page cleaned" <<endl;
stringstream line_str(line);
// split line into records
string subline;
vector<std::string> data;
files.close();
//cout << "curr line_str"<< line << endl;
while (getline(line_str, subline, '$')) {
vector<std::string> data;
//cout << "subline: "<< subline <<endl;
// turn line into a stream
stringstream s(subline);
// gets everything in stream up to comma
getline(s, word,',');
data.push_back(word);
getline(s, word, ',');
data.push_back(word);
getline(s, word, ',');
data.push_back(word);
getline(s, word, ',');
data.push_back(word);
//create new record
Record emp(data);
//put record in the hash table
cout << "reorder: "<<emp.id<<endl;
hash(emp, true);
//emp.print();
}
}
cout << "\n\n \t\t*****End overflow with bitflip. -> rearrange \n";
ban=false;
}
}
// the are things written already
}
}
}
if (posWrite != -1){
files.seekg(posWrite);
files.tellg();
cout<< "was wrote: "<<record.id<<" "<<record.name<< "in position: "<< posWrite<<endl;
files << rec;
files.close();
}
}
}
bool getRecord(int key, int nlockForLook){
fstream files2;//EmployeeIndex
string nLine,li,wo,wo2,eidlook;
bool ban=true;
int posOfPage;
int count2=0;
vector<std::string> data2;
int pos=0;
while(ban){
posOfPage = (nlockForLook+count2*16)*PAGE_SIZE; ;
files2.open(fName, ios::out|ios::in);
files2.seekg(posOfPage);
files2.tellg();
if(getline(files2, li,'#')){//get the line at that position of the block
int found2 = li.find_first_not_of('\0');//cutting the nulls
string nLine = li.substr(found2,li.size());
stringstream wo(nLine);
while (getline(wo, wo2, '$')) {
// turn line into a stream
stringstream s(wo2);
// gets everything in stream up to comma
getline(s, eidlook,',');
if(stoi(eidlook) == key){
data2.push_back(eidlook);
getline(s, eidlook,',');
data2.push_back(eidlook);
getline(s, eidlook,',');
data2.push_back(eidlook);
getline(s, eidlook,',');
data2.push_back(eidlook);
Record emp2(data2);
cout << "The employee is: "<<endl;
emp2.print();
return true;
}
}
}else{
files2.close();
return false;
}
count2++;
files2.close();
}
return false;
}
//searching for key
bool doesExist(int key){
int hashForlook = key % 16;
int nlockForLook;
bitset<16> num(hashForlook);
if (!(std::find(pageDirectory.begin(), pageDirectory.end(), hashForlook) != pageDirectory.end())) {
num.flip(1);
int bitflipy = (int)(num.to_ulong());
if (!(std::find(pageDirectory.begin(), pageDirectory.end(), bitflipy) != pageDirectory.end())) {
//cout <<"no hay ni id ni flip"<<endl;
return false;
}else{
nlockForLook = bitflipy;
}
}else{
nlockForLook = hashForlook;
}
return getRecord(key,nlockForLook);
}
public:
LinearHashIndex(string indexFileName) {
//NEXT FREE PAGE TO GO TO THE NEXT AVAILABLE POSITION IN MEMORY IF NEEDED
//TWO BITS FOR THE PAGE NUMBER --- BUCKET AND UPDATE THIS AS NEEDED
fName = indexFileName+".txt"; //indexfile
}
// Read csv file and add records to the index
void createFromFile(string csvFName) {
ifstream file;
string line,word;
file.open(csvFName);
while(!file.eof()){
//Record emp;
vector<std::string> data;
if (getline(file, line, '\n')) {
// turn line into a stream
stringstream s(line);
// gets everything in stream up to comma
getline(s, word,',');
data.push_back(word);
getline(s, word, ',');
data.push_back(word);
getline(s, word, ',');
data.push_back(word);
getline(s, word, ',');
data.push_back(word);
//create record
Record emp(data);
//put record in the hash table
hash(emp, false);
//emp.print();
}
}
cout<< "the directory indexes are: \n";
for(int i=0; i < pageDirectory.size(); i++)
std::cout << pageDirectory.at(i) << ' ';
// cout<<"overflow: " << overFlow;
cout<<"\n\n";
file.close();
}
// Given an ID, find the relevant record and print it
void findRecordById(int emid) {
bool lookup = doesExist(emid);
if (!lookup){
cout << "there is not employee with that id" << endl << endl;
}
}
};