pranavsindura

Consistent Hashing

Jan 15th, 2024
757
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.50 KB | None | 0 0
  1. #include <cassert>
  2. #include <iostream>
  3. #include <map>
  4. #include <string>
  5. #include <tuple>
  6. #include <vector>
  7. using namespace std;
  8. typedef long long ll;
  9. int MAXN = 1024;
  10.  
  11. ll create_hash(string k) {
  12.   ll rolling = 0;
  13.   const ll MOD = 1e9 + 9;
  14.   const ll P = 263;
  15.   ll p_pow = 1;
  16.   for (char x : k) {
  17.     rolling = rolling + x * p_pow;
  18.     rolling %= MOD;
  19.     p_pow *= P;
  20.     p_pow %= MOD;
  21.   }
  22.  
  23.   return rolling;
  24. }
  25.  
  26. class Database {
  27.   map<string, string> table;
  28.  
  29. public:
  30.   Database() {}
  31.  
  32.   void add_entry(string key, string value) { table[key] = value; }
  33.   string get_entry(string key) { return table[key]; }
  34. } db;
  35.  
  36. class Server {
  37.   string machine_id;
  38.   int replication_count;
  39.  
  40.   map<string, string> table;
  41.  
  42. public:
  43.   Server(string id, int count) {
  44.     machine_id = id;
  45.     replication_count = count;
  46.     cout << "Created Server " << id << ", " << count << endl;
  47.   }
  48.  
  49.   string get_machine_id() { return machine_id; }
  50.   int get_replication_count() { return replication_count; }
  51.  
  52.   void add_entry(string key, string value) { table[key] = value; }
  53.   tuple<bool, string> get_entry(string key) {
  54.     if (table.count(key) == 0) {
  55.       string value = db.get_entry(key);
  56.       add_entry(key, value);
  57.       return {false, table[key]};
  58.     }
  59.  
  60.     return {true, table[key]};
  61.   }
  62. };
  63.  
  64. class VirtualServer {
  65.   Server *server;
  66.   int index;
  67.  
  68.   string key;
  69.   int key_hash;
  70.  
  71.   bool operator<(VirtualServer b) { return key_hash < b.key_hash; }
  72.  
  73. public:
  74.   VirtualServer(Server *s, int i) {
  75.     server = s;
  76.     index = i;
  77.     key = s->get_machine_id() + '/' + to_string(i);
  78.     key_hash = create_hash(key);
  79.     cout << "Created VirtualServer " << key << ", " << key_hash << ", " << endl;
  80.   }
  81.  
  82.   int get_key_hash() { return key_hash; }
  83.   Server *get_server() { return server; }
  84. };
  85.  
  86. class HashRing {
  87.   map<int, VirtualServer *> ring;
  88.   map<string, vector<VirtualServer *>> virtualServerMapList;
  89.   map<string, Server *> serverMap;
  90.  
  91. public:
  92.   void add_server(string machine_id, int replication_count) {
  93.     Server *s = new Server(machine_id, replication_count);
  94.     for (int i = 0; i < s->get_replication_count(); i++) {
  95.       VirtualServer *vs = new VirtualServer(s, i);
  96.  
  97.       assert(ring.count(vs->get_key_hash()) == 0);
  98.  
  99.       ring[vs->get_key_hash()] = vs;
  100.       virtualServerMapList[s->get_machine_id()].push_back(vs);
  101.     }
  102.     serverMap[s->get_machine_id()] = s;
  103.   }
  104.  
  105.   void remove_server(string machine_id) {
  106.     for (VirtualServer *vs : virtualServerMapList[machine_id]) {
  107.       ring.erase(vs->get_key_hash());
  108.       delete vs;
  109.     }
  110.     virtualServerMapList.erase(machine_id);
  111.     delete serverMap[machine_id];
  112.     serverMap.erase(machine_id);
  113.   }
  114.  
  115.   tuple<bool, string, Server *> get_entry(string key) {
  116.     int key_hash = create_hash(key);
  117.     auto it = ring.lower_bound(key_hash);
  118.     if (it == ring.end()) {
  119.       it = ring.begin();
  120.     }
  121.     auto result = it->second->get_server()->get_entry(key);
  122.     bool cache_hit;
  123.     string value;
  124.     tie(cache_hit, value) = result;
  125.     return {cache_hit, value, it->second->get_server()};
  126.   }
  127. };
  128.  
  129. int main() {
  130.   /*
  131.    * Queries
  132.    * 1 <machineId> <replicationCount> -> Add machine to the group of servers, no
  133.    * repeat
  134.    *
  135.    * 2 <machineId> -> Remove machine from the group of servers, machine
  136.    * will exist
  137.    *
  138.    * 3 <key> <value> -> Set data for <key> = <value>
  139.    *
  140.    * 4 <key> -> Get <value> <machineId> <cache hit/miss> for key
  141.    */
  142.  
  143.   HashRing *ring = new HashRing();
  144.  
  145.   int queries = 0;
  146.   cin >> queries;
  147.   while (queries--) {
  148.     int q;
  149.     cin >> q;
  150.     switch (q) {
  151.     case 1: {
  152.       string machine_id;
  153.       int replication_count;
  154.       cin >> machine_id >> replication_count;
  155.       ring->add_server(machine_id, replication_count);
  156.       break;
  157.     }
  158.     case 2: {
  159.       string machine_id;
  160.       cin >> machine_id;
  161.       ring->remove_server(machine_id);
  162.       cout << "Removed Server: " << machine_id << endl;
  163.       break;
  164.     }
  165.     case 3: {
  166.       string key, value;
  167.       cin >> key >> value;
  168.       db.add_entry(key, value);
  169.       cout << "Added: " << key << " -> " << value << endl;
  170.       break;
  171.     }
  172.     case 4: {
  173.       string key;
  174.       cin >> key;
  175.       bool cache_hit;
  176.       string result;
  177.       Server *s;
  178.       tie(cache_hit, result, s) = ring->get_entry(key);
  179.       cout << (cache_hit ? "Cache Hit: " : "Cache Miss: ") << key << " -> "
  180.            << result << ", on Server " << s->get_machine_id() << endl;
  181.       break;
  182.     }
  183.     default:
  184.       break;
  185.     }
  186.   }
  187. }
  188.  
Advertisement
Add Comment
Please, Sign In to add comment