Commit 622c0a03 authored by Vishal Saha's avatar Vishal Saha

implementation of sharing keys on server join

parent 5e582cf1
......@@ -77,7 +77,7 @@ public:
string getKeyValuePairs(int id)
{
return "keyvaluepairs";
return mycache.getKeyValuePairs(id);
}
};
......@@ -123,7 +123,9 @@ public:
mycache.pushAll();
}
// key1;key2;key3;;value1;value2;value3;
string getKeyValuePairs(int id)
{
return mycache.getKeyValuePairs(id);
}
};
\ No newline at end of file
......@@ -10,7 +10,8 @@
using namespace std;
class LFUCache {
class LFUCache
{
private:
int capacity;
LFUNode **cacheHeap;
......@@ -18,29 +19,34 @@ private:
std::mutex mtx;
string deleted;
int parent(int i) {
int parent(int i)
{
if (i % 2 == 0)
return (i / 2) - 1;
else
return (i - 1) / 2;
}
int left_child(int i) {
int left_child(int i)
{
return (2 * i) + 1;
}
int right_child(int i) {
int right_child(int i)
{
return (2 * i) + 2;
}
int exists(string key) {
int exists(string key)
{
for (int i = curr_pos; i >= 0; i--)
if (key.compare(cacheHeap[i]->key) == 0)
return i;
return -1;
}
void swap(int i, int j) {
void swap(int i, int j)
{
cacheHeap[i]->frequency = cacheHeap[i]->frequency + cacheHeap[j]->frequency;
cacheHeap[j]->frequency = cacheHeap[i]->frequency - cacheHeap[j]->frequency;
cacheHeap[i]->frequency = cacheHeap[i]->frequency - cacheHeap[j]->frequency;
......@@ -52,8 +58,10 @@ private:
cacheHeap[j]->value = temp;
}
void heapify_up(int i) {
while (true) {
void heapify_up(int i)
{
while (true)
{
if (i == 0)
break;
if (cacheHeap[parent(i)]->frequency <= cacheHeap[i]->frequency)
......@@ -64,17 +72,21 @@ private:
}
}
void heapify_down(int i) {
while (true) {
void heapify_down(int i)
{
while (true)
{
if (left_child(i) > curr_pos)
break;
if (right_child(i) > curr_pos && cacheHeap[left_child(i)]->frequency >= cacheHeap[i]->frequency)
break;
if (right_child(i) <= curr_pos) {
if (right_child(i) <= curr_pos)
{
if (cacheHeap[left_child(i)]->frequency >= cacheHeap[i]->frequency && cacheHeap[right_child(i)]->frequency >= cacheHeap[i]->frequency)
break;
}
if (right_child(i) <= curr_pos) {
if (right_child(i) <= curr_pos)
{
if (cacheHeap[left_child(i)]->frequency < cacheHeap[right_child(i)]->frequency)
swap(i, left_child(i));
else
......@@ -85,16 +97,19 @@ private:
}
}
string insert(string key, string value) {
string insert(string key, string value)
{
int i = exists(key);
if (i != -1) {
if (i != -1)
{
cacheHeap[i]->frequency++;
cacheHeap[i]->value = value;
heapify_down(i);
return INSERT_SUCCESS;
}
curr_pos++;
if (curr_pos == capacity) {
if (curr_pos == capacity)
{
curr_pos--;
delete_min(true);
insert(key, value);
......@@ -107,14 +122,16 @@ private:
return INSERT_SUCCESS;
}
string delete_min(bool keep) {
string delete_min(bool keep)
{
if (curr_pos == -1)
return CACHE_EMPTY;
swap(0, curr_pos);
curr_pos--;
if (curr_pos >= 0)
heapify_down(0);
if (keep) {
if (keep)
{
string filename = getFilename(cacheHeap[curr_pos + 1]->key);
ofstream fout;
fout.open(filename, ios::app);
......@@ -125,7 +142,8 @@ private:
return DELETE_SUCCESS;
}
void insertAll(unordered_map<string, string> flush) {
void insertAll(unordered_map<string, string> flush)
{
int to_empty = flush.size() - capacity + curr_pos + 1;
for (int i = 0; i < to_empty; i++)
delete_min(true);
......@@ -134,12 +152,14 @@ private:
insert(itr->first, itr->second);
}
string getNodeByKey(string key) {
string getNodeByKey(string key)
{
string value;
int i = exists(key);
if (i == -1)
return KEY_NOT_FOUND;
else {
else
{
cacheHeap[i]->frequency++;
value = cacheHeap[i]->value;
heapify_down(i);
......@@ -147,11 +167,13 @@ private:
}
}
string deleteNodeByKey(string key) {
string deleteNodeByKey(string key)
{
int i = exists(key);
if (i == -1)
return KEY_NOT_FOUND;
else {
else
{
cacheHeap[i]->frequency = 0;
heapify_up(i);
delete_min(false);
......@@ -165,7 +187,8 @@ private:
}
}
string getFilename(string key) {
string getFilename(string key)
{
string filename = ".";
int length = key.size();
if (length == 1)
......@@ -177,34 +200,40 @@ private:
return filename;
}
bool fileExists(string filename) {
bool fileExists(string filename)
{
ifstream f(filename.c_str());
return f.good();
}
public:
LFUCache() {
LFUCache()
{
curr_pos = -1;
deleted = "";
deleted += char(0);
}
void setCap(int capacity) {
void setCap(int capacity)
{
this->capacity = capacity;
cacheHeap = (LFUNode **)malloc(sizeof(LFUNode *) * capacity);
for(int i = 0; i < capacity; i++)
for (int i = 0; i < capacity; i++)
cacheHeap[i] = new LFUNode(deleted, deleted);
}
string GET(string key, int *status) {
string GET(string key, int *status)
{
//std::lock_guard<std::mutex> guard(mtx);
string value = getNodeByKey(key);
if (value.compare(KEY_NOT_FOUND) != 0) {
if (value.compare(KEY_NOT_FOUND) != 0)
{
*status = 200;
return value;
}
string filename = getFilename(key);
if (!fileExists(filename)) {
if (!fileExists(filename))
{
*status = 400;
return KEY_NOT_FOUND;
}
......@@ -212,7 +241,8 @@ public:
ifstream fin;
unordered_map<string, string> flush;
fin.open(filename);
do {
do
{
getline(fin, key1);
if (key1.size() == 0)
break;
......@@ -237,33 +267,39 @@ public:
return value;
}
void PUT(string key, string value) {
void PUT(string key, string value)
{
//mtx.lock();
insert(key, value);
//mtx.unlock();
}
void DEL(string key, int *status) {
void DEL(string key, int *status)
{
int status1;
string value = GET(key, &status1);
if (status1 == 400) {
if (status1 == 400)
{
*status = 400;
return;
}
deleteNodeByKey(key);
}
void pushAll() {
void pushAll()
{
while (curr_pos >= 0)
delete_min(true);
}
void reformat(string filename) {
void reformat(string filename)
{
ifstream fin;
fin.open(filename);
unordered_map<string, string> flush;
string key, value;
do {
do
{
getline(fin, key);
if (key.size() == 0)
break;
......@@ -279,15 +315,87 @@ public:
ofstream fout;
fout.open(filename);
unordered_map<string, string>::iterator itr;
for (itr = flush.begin(); itr != flush.end(); itr++) {
for (itr = flush.begin(); itr != flush.end(); itr++)
{
fout << itr->first << "\n";
fout << itr->second << "\n";
}
}
void traverse() {
void traverse()
{
for (int i = 0; i <= curr_pos; i++)
cout << cacheHeap[i]->key << endl;
cout << endl;
}
string getKeyValuePairs(int id)
{
unordered_map<string, string> flush;
string keyValPairs = "";
DIR *dirFile = opendir(".");
if (dirFile)
{
struct dirent *hFile;
while ((hFile = readdir(dirFile)) != NULL)
{
string fName(hFile->d_name);
string fileName(hFile->d_name);
int n;
if ((n = fileName.size()) < 8)
continue;
if (fileName[n - 3] == 'k' && fileName[n - 2] == 'v' && fileName[n - 1] == 'm')
{
fileName.erase(n - 4);
fileName = fileName.substr(2);
if (hash(fileName) <= id)
{
ifstream fin;
fin.open(fName);
string _key, val;
do
{
getline(fin, _key);
if (_key.size() == 0)
break;
getline(fin, val);
if (val != deleted)
flush[_key] = val;
else
flush.erase(_key);
if (fin.eof())
break;
} while (fin);
fin.close();
const char *c = fName.c_str();
remove(c);
}
}
}
closedir(dirFile);
}
Node *temp = head->next;
while (temp->next)
{
if (hash(temp->key) <= id)
{
flush[temp->key] = temp->payload;
}
temp = temp->next;
}
unordered_map<string, string>::iterator itr;
for (itr = flush.begin(); itr != flush.end(); itr++)
keyValPairs += itr->first + ";";
keyValPairs += ";";
for (itr = flush.begin(); itr != flush.end(); itr++)
keyValPairs += itr->second + ";";
return keyValPairs;
}
};
......@@ -6,15 +6,18 @@
using namespace std;
inline bool fileExists(const std::string &name) {
inline bool fileExists(const std::string &name)
{
struct stat buffer;
return (stat(name.c_str(), &buffer) == 0);
}
string getFilename(string key) {
string getFilename(string key)
{
string filename = ".";
int length = key.size();
if (length == 1) {
if (length == 1)
{
return "_.kvm";
}
filename += char(length - 1);
......@@ -24,7 +27,8 @@ string getFilename(string key) {
return filename;
}
class LRUcache {
class LRUcache
{
private:
int capacity;
string deleted;
......@@ -34,7 +38,8 @@ private:
unordered_map<string, Node *> cache;
public:
LRUcache() {
LRUcache()
{
head = new Node("HEAD", "HEAD");
tail = new Node("TAIL", "TAIL");
head->next = tail;
......@@ -43,11 +48,13 @@ public:
deleted += char(0);
}
void setCap(int capacity) {
void setCap(int capacity)
{
this->capacity = capacity;
}
LRUcache(int capacity) {
LRUcache(int capacity)
{
this->capacity = capacity;
head = new Node("HEAD", "HEAD");
tail = new Node("TAIL", "TAIL");
......@@ -57,7 +64,8 @@ public:
deleted += char(0);
}
Node *getUtil(string key) {
Node *getUtil(string key)
{
if (cache.find(key) == cache.end())
return NULL;
Node *x = cache[key];
......@@ -73,11 +81,14 @@ public:
return x;
}
string get(string key, int *status) {
string get(string key, int *status)
{
//std::lock_guard<std::mutex> guard(mtx);
Node *x = getUtil(key);
if (x) {
if (x->payload == deleted) {
if (x)
{
if (x->payload == deleted)
{
*status = 400;
return NOT_EXIST;
}
......@@ -86,7 +97,8 @@ public:
string fileName = getFilename(key);
if (!fileExists(fileName)) {
if (!fileExists(fileName))
{
*status = 400;
return NOT_EXIST;
}
......@@ -97,7 +109,8 @@ public:
string _key, val;
unordered_map<string, string> flush;
do {
do
{
getline(fin, _key);
if (_key.size() == 0)
break;
......@@ -113,12 +126,14 @@ public:
fin.close();
unordered_map<string, string>::iterator itr;
for (itr = flush.begin(); itr != flush.end() && cache.size() < capacity - 1; itr++) {
for (itr = flush.begin(); itr != flush.end() && cache.size() < capacity - 1; itr++)
{
this->put(itr->first, itr->second);
flush[itr->first] = deleted;
}
if (flush.find(key) != flush.end()) {
if (flush.find(key) != flush.end())
{
this->put(key, flush[key]);
flush[key] = deleted;
}
......@@ -128,7 +143,8 @@ public:
ofstream fout;
fout.open(fileName);
for (itr = flush.begin(); itr != flush.end(); itr++) {
for (itr = flush.begin(); itr != flush.end(); itr++)
{
if (itr->second == deleted)
continue;
fout << itr->first << "\n";
......@@ -136,7 +152,8 @@ public:
}
fout.close();
x = getUtil(key);
if (x) {
if (x)
{
return x->payload;
}
*status = 400;
......@@ -144,12 +161,14 @@ public:
return NOT_EXIST;
}
void del(string key, int *status) {
void del(string key, int *status)
{
int status2 = 200;
string result = get(key, &status2);
// mtx.lock();
if (status2 == 400) {
if (status2 == 400)
{
*status = 400;
// mtx.unlock();
return;
......@@ -159,9 +178,11 @@ public:
// mtx.unlock();
}
void pushAll() {
void pushAll()
{
unordered_map<string, Node *>::iterator itr;
for (itr = cache.begin(); itr != cache.end(); itr++) {
for (itr = cache.begin(); itr != cache.end(); itr++)
{
string fileName = getFilename(itr->first);
ofstream fout;
......@@ -177,12 +198,15 @@ public:
tail->prev = head;
}
void put(string key, string payload) {
void put(string key, string payload)
{
//mtx.lock();
if (getUtil(key) != NULL)
cache[key]->payload = payload;
else {
if (cache.size() == capacity) {
else
{
if (cache.size() == capacity)
{
Node *x = tail->prev;
string keyToBeFlushed = x->key;
cache.erase(keyToBeFlushed);
......@@ -206,7 +230,9 @@ public:
head->next = x;
x->prev = head;
} else {
}
else
{
Node *x = new Node(key, payload);
cache[key] = x;
x->next = head->next;
......@@ -219,12 +245,90 @@ public:
//mtx.unlock();
}
void traverse() {
void traverse()
{
Node *temp = head->next;
while (temp->next) {
while (temp->next)
{
cout << temp->key << "\n";
temp = temp->next;
}
cout << "\n";
}
int hash(string s)
{
return (((int)s.at(0)) << 8) + ((int)s.at(1));
}
// key1;key2;key3;;value1;value2;value3;
string getKeyValuePairs(int id)
{
unordered_map<string, string> flush;
string keyValPairs = "";
DIR *dirFile = opendir(".");
if (dirFile)
{
struct dirent *hFile;
while ((hFile = readdir(dirFile)) != NULL)
{
string fName(hFile->d_name);
string fileName(hFile->d_name);
int n;
if ((n = fileName.size()) < 8)
continue;
if (fileName[n - 3] == 'k' && fileName[n - 2] == 'v' && fileName[n - 1] == 'm')
{
fileName.erase(n - 4);
fileName = fileName.substr(2);
if (hash(fileName) <= id)
{
ifstream fin;
fin.open(fName);
string _key, val;
do
{
getline(fin, _key);
if (_key.size() == 0)
break;
getline(fin, val);
if (val != deleted)
flush[_key] = val;
else
flush.erase(_key);
if (fin.eof())
break;
} while (fin);
fin.close();
const char *c = fName.c_str();
remove(c);
}
}
}
closedir(dirFile);
}
Node *temp = head->next;
while (temp->next)
{
if (hash(temp->key) <= id)
{
flush[temp->key] = temp->payload;
}
temp = temp->next;
}
unordered_map<string, string>::iterator itr;
for (itr = flush.begin(); itr != flush.end(); itr++)
keyValPairs += itr->first + ";";
keyValPairs += ";";
for (itr = flush.begin(); itr != flush.end(); itr++)
keyValPairs += itr->second + ";";
return keyValPairs;
}
};
LISTENING_PORT=50051
LISTENING_PORT=50055
CACHE_REPLACEMENT_TYPE=LRU
CACHE_SIZE=256
NUM_SERVER_THREADS=4
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment