Commit 5ffd666b authored by Nilesh Jagdish's avatar Nilesh Jagdish

Replaced c-strings with cpp string

parent 3b45c310
#include <iostream> #include <iostream>
#include <list> #include <list>
#include <cstring>
#include <iterator> #include <iterator>
#include <unordered_map> #include <unordered_map>
#include <string>
#include "cache.h" #include "cache.h"
using namespace std; using namespace std;
/* /*
...@@ -14,29 +14,31 @@ using namespace std; ...@@ -14,29 +14,31 @@ using namespace std;
* 1. Search in cache : * 1. Search in cache :
* Use unordered_map to see if a key is present in the cache and if it is present, this operation * Use unordered_map to see if a key is present in the cache and if it is present, this operation
* should return 1 * should return 1
* This operation should also move searched key to start of the cache
* 2. Insert in cache : * 2. Insert in cache :
* If cache is full, call LRU * If cache is full, call LRU
* If cache has is not full, replace the frame with key-value pair to be inserted * If cache is not full, add the key-value pair to start of the cache
* 3. LRU cache : * 3. LRU cache :
* Keep a pointer on a frame after the frame last replaced
* Move the pointer circularly, if a node has referenceBit = '0', then select this key-value for
* replacement
* Use bitmap to identify the file in which key is present
* (Use locality to evict more than one key-value pair?) * (Use locality to evict more than one key-value pair?)
* And read the key-value pair in array element * Delete the last element in cache
* Insert new key-value pair at the start of the cache
* *
* Data Structures : 1. List of cacheNode - 32 keys * Data Structures : 1. List of cacheNode - 32 keys
* 2. Unordered map - <key, array index> * 2. Unordered map - <key, array index>
* *
*/ */
#define MAX_CACHE_SIZE 32 #define MAX_CACHE_SIZE 3
list<cacheNode> cache; list<cacheNode> cache;
unordered_map<char *, list <cacheNode> :: iterator> hashTable; unordered_map<string, list <cacheNode> :: iterator> hashTable;
int search(char* key) { /*
unordered_map<char *, list <cacheNode> :: iterator> :: iterator it = hashTable.find(key); * Returns 1 if key-value pair is present in cache and 0 otherwise
* If key is present, brings correspoding node to front of the cache(To identify recently used element)
*/
int search(string key) {
unordered_map<string, list <cacheNode> :: iterator> :: iterator it = hashTable.find(key);
if(it == hashTable.end()) { if(it == hashTable.end()) {
return 0; return 0;
} }
...@@ -44,31 +46,52 @@ int search(char* key) { ...@@ -44,31 +46,52 @@ int search(char* key) {
list <cacheNode> :: iterator cnode_it = it->second; list <cacheNode> :: iterator cnode_it = it->second;
cache.push_front(*cnode_it); cache.push_front(*cnode_it);
cache.erase(cnode_it); cache.erase(cnode_it);
hashTable[key] = cache.begin();
return 1; return 1;
} }
} }
void lru(char* key, char *value) { void lru(string key, string value) {
list <cacheNode> :: iterator it = prev(cache.end());
if(it->dirtyBit == '1') {
// Write back to persistent storage
}
else {
for (auto p : hashTable) {
cout << p.first << " : ";
cout << p.second->key << " " << p.second->value << " " << p.second->dirtyBit << endl ;
}
int num = hashTable.erase(it->key);
cache.pop_back();
for (auto p : hashTable) {
cout << p.first << " : ";
cout << p.second->key << " " << p.second->value << " " << p.second->dirtyBit << endl;
}
printf("-----------------------------\n");
cacheNode cnode;
cnode.key = key;
cnode.value = value;
cnode.dirtyBit = '0';
cache.push_back(cnode);
hashTable[key] = --cache.end();
}
} }
/* /*
* Assumption here is that before calling insert, key-value pair does not already exist in cache * Assumption here is that before calling insert, key-value pair does not already exist in cache
*/ */
void insert(char* key, char* value) { void insert(string key, string value) {
cacheNode cnode; cacheNode cnode;
if(cache.size() == MAX_CACHE_SIZE) { if(cache.size() == MAX_CACHE_SIZE) {
// printf("LRU called\n");
lru(key, value); lru(key, value);
} }
else { else {
cnode.key = (char *)malloc(strlen(key) + 1); cnode.key = key;
strcpy(cnode.key, key); cnode.value = value;
cnode.value = (char *)malloc(strlen(value) + 1);
strcpy(cnode.value, value);
cnode.dirtyBit = '0'; cnode.dirtyBit = '0';
cache.push_front(cnode); cache.push_front(cnode);
hashTable[key] = cache.begin(); hashTable[key] = cache.begin();
} }
} }
...@@ -76,16 +99,45 @@ void insert(char* key, char* value) { ...@@ -76,16 +99,45 @@ void insert(char* key, char* value) {
* Testing code * Testing code
*/ */
int main() { int main() {
char key1[] = "A"; string key1 = "AB";
char key2[] = "B"; string key2 = "BC";
char key3[] = "C"; string key3 = "CD";
char key4[] = "D"; string key4 = "DE";
char value[] = "1"; string key5 = "EF";
string value = "1";
insert(key1, value); insert(key1, value);
insert(key2, value); insert(key2, value);
for (auto p : hashTable) {
cout << p.first << " : ";
cout << p.second->key << " " << p.second->value << " " << p.second->dirtyBit << endl;
}
printf("-----------------------------\n");
insert(key3, value); insert(key3, value);
printf("%d\n", search(key1)); for (auto p : hashTable) {
printf("%d\n", search(key2)); cout << p.first << " : ";
printf("%d\n", search(key3)); cout << p.second->key << " " << p.second->value << " " << p.second->dirtyBit << endl;
printf("%d\n", search(key4)); }
printf("-----------------------------\n");
insert(key4, value);
for (auto p : hashTable) {
cout << p.first << " : ";
cout << p.second->key << " " << p.second->value << " " << p.second->dirtyBit << endl;
}
printf("-----------------------------\n");
cout << key1 << " " << search(key1) << endl;
cout << key2 << " " << search(key2) << endl;
cout << key3 << " " << search(key3) << endl;
cout << key4 << " " << search(key4) << endl;
printf("-----------------------------\n");
for (auto p : hashTable) {
cout << p.first << " : ";
cout << p.second->key << " " << p.second->value << " " << p.second->dirtyBit << endl;
}
printf("-----------------------------\n");
insert(key5, value);
for (auto p : hashTable) {
cout << p.first << " : ";
cout << p.second->key << " " << p.second->value << " " << p.second->dirtyBit << endl;
}
} }
#include <iostream>
#include <list>
#include <iterator>
#include <string>
#include <unordered_map>
using namespace std;
/* /*
* *
* Cache node structure : * Cache node structure :
* dirtyBit = '1' if value is modified, '0' if not modified * dirtyBit = '1' if value is modified, '0' if not modified
* referenceBit - To implement approximate LRU
* An iterator will iterate through the list to find first page which has referenceBit = '0' * An iterator will iterate through the list to find first page which has referenceBit = '0'
* It replaces that key-value along with 3 following key-value pairs with the new key and its following * It replaces that key-value along with 3 following key-value pairs with the new key and its following
* 3 key-value pairs in persistent storage * 3 key-value pairs in persistent storage
* If referenceBit = '1', set it to '0' and move forward(in circular fashion)
* To implement perfect LRU(which might be costly in terms of performance) - need a global counter for time * To implement perfect LRU(which might be costly in terms of performance) - need a global counter for time
*/ */
typedef struct cacheNode { typedef struct cacheNode {
char* key; string key;
char* value; string value;
char dirtyBit; char dirtyBit;
} cacheNode; } cacheNode;
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