From e0741501634292b578d0276397350eba174c1077 Mon Sep 17 00:00:00 2001 From: Javad Saberlatibari <76922325+javadsaberlatibari@users.noreply.github.com> Date: Wed, 20 Mar 2024 12:19:20 -0700 Subject: [PATCH] added rubis --- .../benchmark/rubis-benchmark.cpp | 183 ++++++++++++++++++ wellcoordination/benchmark/rubis.hpp | 159 +++++++++++++++ 2 files changed, 342 insertions(+) create mode 100644 wellcoordination/benchmark/rubis-benchmark.cpp create mode 100644 wellcoordination/benchmark/rubis.hpp diff --git a/wellcoordination/benchmark/rubis-benchmark.cpp b/wellcoordination/benchmark/rubis-benchmark.cpp new file mode 100644 index 0000000..6abaef7 --- /dev/null +++ b/wellcoordination/benchmark/rubis-benchmark.cpp @@ -0,0 +1,183 @@ +#include +#include +#include +#include +#include + +#include "rubis.hpp" +//------------opcode------- number of parameters + +//sellItem 0 2(id+value) +//storeBuyNow 1 2(id+value) by leader +//registerUser 2 1(id) by leader +//openAuction 1(id) by default consider 100 auctions are open. +//placeBid 3 3(auctionid+userid+value) +//query 4 like movie does not consider read. + +int main(int argc, char* argv[]) { + std::string loc = + "/users/jsaber/binHamband/workload/"; + + int nr_procs = static_cast(std::atoi(argv[1])); + int num_ops = static_cast(std::atoi(argv[2])); + double write_percentage = static_cast(std::atoi(argv[3])); + + loc += std::to_string(nr_procs) + "-" + std::to_string(num_ops) + "-" + + std::to_string(static_cast(write_percentage)); + loc += "/rubis/"; + + std::ofstream* outfile = new std::ofstream[nr_procs]; + std::vector* calls = new std::vector[nr_procs]; + for (int i = 0; i < nr_procs; i++) { + remove((loc + std::to_string(i + 1) + ".txt").c_str()); + outfile[i].open(loc + std::to_string(i + 1) + ".txt", std::ios_base::app); + calls[i] = std::vector(); + } + + Rubis* test = new Rubis(); + + // MethodCallFactory factory = MethodCallFactory(test, nr_procs); + + write_percentage /= 100; + int num_replicas = nr_procs; + double total_writes = num_ops * write_percentage; + int queries = num_ops - total_writes; + + int num_conflicting_write_methods = 2; + int num_nonconflicting_write_methods = 2; + int num_read_methods = 0; + + std::cout << "ops: " << num_ops << std::endl; + std::cout << "write_perc: " << write_percentage << std::endl; + std::cout << "writes: " << total_writes << std::endl; + std::cout << "reads: " << queries << std::endl; + + int expected_calls_per_update_method = + total_writes / + (num_conflicting_write_methods + num_nonconflicting_write_methods); + std::cout << "expected #calls per update method " + << expected_calls_per_update_method << std::endl; + + std::cout << "expected #calls per conflicting writes in leader " + << expected_calls_per_update_method << std::endl; + std::cout << "total conflicting #calls in leader " + << expected_calls_per_update_method * num_conflicting_write_methods + << std::endl; + + int expected_nonconflicting_write_calls_per_follower = + (total_writes - + expected_calls_per_update_method * num_conflicting_write_methods) / + (nr_procs - 1); + + std::cout << "expected #calls per nonconflicting writes in followers " + << expected_nonconflicting_write_calls_per_follower << std::endl; + std::cout << "total nonconflicting #calls in followers " + << expected_nonconflicting_write_calls_per_follower * + num_nonconflicting_write_methods * (nr_procs - 1) + << std::endl; + + int write_calls = + expected_calls_per_update_method * num_conflicting_write_methods + + expected_nonconflicting_write_calls_per_follower * + num_nonconflicting_write_methods * (nr_procs - 1); + + // first allocating writes operations to the nodes + for (int i = 1; i <= num_replicas; i++) { + // first leader + if (i == 1) { + for (int type = 0; type <= 0; type++) { + int count = 0; + for (; count < expected_calls_per_update_method;) { + // storeBuyNow + std::string callStr; + if (type == 0) { + std::string b_id = std::to_string(1 + std::rand() % 100); + std::string value = std::to_string(std::rand() % 1000); + callStr = "1 " + b_id + "-" + value; + } + MethodCall call = ReplicatedObject::createCall("id", callStr); + if (test->isPermissible(call)) { + test->execute(call); + calls[i - 1].push_back(callStr); + count++; + } + } + } + } + // second leader + else if (i == 2) { + for (int type = 0; type <= 0; type++) { + int count = 0; + for (; count < expected_calls_per_update_method;) { + // registerUser + std::string callStr; + if (type == 0) { + std::string u_id = std::to_string(1+ std::rand() % 100); + callStr = "2 " + u_id; + } + MethodCall call = ReplicatedObject::createCall("id", callStr); + if (test->isPermissible(call)) { + test->execute(call); + calls[i - 1].push_back(callStr); + count++; + } + } + } + } + // follower + else { + // non-conflicting write method + for (int type = 0; type <= 1; type++) { + for (int count = 0; count < + expected_nonconflicting_write_calls_per_follower; count++) { + std::string callStr; + if (type == 0) { + // sellitem + std::string s_id = std::to_string(1+ std::rand() % 100); + std::string value = std::to_string(std::rand() % 1000); + callStr = "0 " + s_id+ "-"+ value; + } + if (type == 1) { + // placeBid + std::string a_id = std::to_string(1+ std::rand() % 100); //auction id + std::string u_id = std::to_string(1+ std::rand() % 100); //user id + std::string value = std::to_string(std::rand() % 1000); //bid value + + callStr = "3 " + a_id + "-" + u_id + "-" + value; + } + + MethodCall call = ReplicatedObject::createCall("id", callStr); + test->execute(call); + calls[i - 1].push_back(callStr); + } + } + } + } + + // allocate reads to the nodes + int q = num_ops - write_calls; + std::cout << "q: " << q << std::endl; + + // if(calls[0].size() > calls[1].size()) + int read_calls = q; + int index = 0; + + std::cout << "after adding writes nodes" << std::endl; + for (int i = 0; i < nr_procs; i++) + std::cout << i + 1 << " size: " << calls[i].size() << std::endl; + + for (int i = 0; i < nr_procs; i++) { + calls[i].insert(calls[i].begin(), + std::string("#" + std::to_string(write_calls))); + std::random_shuffle(calls[i].begin() + 1, calls[i].end()); + } + + for (int i = 0; i < nr_procs; i++) { + for (int x = 0; x < calls[i].size(); x++) + outfile[i] << calls[i][x] << std::endl; + outfile[i].close(); + } + + std::cout << "expected calls to receive: " << write_calls << std::endl; + return 0; +} diff --git a/wellcoordination/benchmark/rubis.hpp b/wellcoordination/benchmark/rubis.hpp new file mode 100644 index 0000000..1dd0a9d --- /dev/null +++ b/wellcoordination/benchmark/rubis.hpp @@ -0,0 +1,159 @@ + +#include +#include +#include +#include +#include +#include +#include + +#include "../src/replicated_object.hpp" + + +typedef unsigned char uint8_t; + +class Rubis : public ReplicatedObject +{ + +//sellItem 0 2(id+value) +//storeBuyNow 1 2(id+value) by leader +//registerUser 2 1(id) by leader +//openAuction 1(id) by default consider 100 auctions are open. +//placeBid 3 3(auctionid+userid+value) +//query 4 like movie does not consider read. +private: + +public: + + enum MethodType{ + SELL_ITEM = 0, + STORE_BUY_NOW = 1, + REGISTER_USER = 2, + PLACE_BID = 3, + QUERY = 4 + }; + std::atomic auction [100][3]={{0}}; //auctionid-quantity-user propsed max value-max value + bool registeredusers [100]={false}; + int userscounter=0; + //std::set movies; + //std::set customers; + + + Rubis() { + read_methods.push_back(static_cast(MethodType::QUERY)); + + update_methods.push_back(static_cast(MethodType::SELL_ITEM)); + update_methods.push_back(static_cast(MethodType::STORE_BUY_NOW)); + update_methods.push_back(static_cast(MethodType::REGISTER_USER)); + update_methods.push_back(static_cast(MethodType::PLACE_BID)); + + method_args.insert(std::make_pair(static_cast(MethodType::SELL_ITEM), 2)); + method_args.insert(std::make_pair(static_cast(MethodType::STORE_BUY_NOW), 2)); + method_args.insert(std::make_pair(static_cast(MethodType::REGISTER_USER), 1)); + method_args.insert(std::make_pair(static_cast(MethodType::PLACE_BID), 3)); + method_args.insert(std::make_pair(static_cast(MethodType::QUERY), 0)); + + // conflicts + std::vector g1; + g1.push_back(static_cast(MethodType::STORE_BUY_NOW)); + //g1.push_back(static_cast(MethodType::REMOVE_MOVIE)); + synch_groups.push_back(g1); + std::vector g2; + g2.push_back(static_cast(MethodType::REGISTER_USER)); + //g2.push_back(static_cast(MethodType::REMOVE_CUSTOMER)); + synch_groups.push_back(g2); + } + + Rubis(Rubis &obj) : ReplicatedObject(obj) + { + //state + std::memcpy(auction, obj.auction, sizeof(auction)); + std::memcpy(registeredusers, obj.registeredusers, sizeof(registeredusers)); + userscounter =obj.userscounter; + //auction = obj.auction; + //registeredusers = obj.registeredusers; + } + + virtual void toString() + { + std::cout << "#users_counter: " << userscounter << std::endl; + //std::cout << "#customer_elements: " << customers.size() << std::endl; + } + + + // 0 + void sellItem(int s_id, int value) + { + auction[s_id][0]=value; + } + // 1 + void storeBuyNow(int s_id, int value) + { + if (auction[s_id][0]>value) + auction[s_id][0]=auction[s_id][0]-value; + } + // 2 + void registeruser(int u_id) + { + registeredusers[u_id]=true; + userscounter++; + } + // 3 + void placeBid(int a_id, int u_id, int value) + { + if(registeredusers[u_id]){ + if(auction[a_id][2](call.method_type)) + { + case MethodType::SELL_ITEM: + size_t index = call.arg.find_first_of('-'); + int s_id = std::stoi(call.arg.substr(0, index)); + int value = std::stoi(call.arg.substr(index + 1, call.arg.length())); + sellItem(int s_id, int value); + break; + case MethodType::STORE_BUY_NOW: + size_t index = call.arg.find_first_of('-'); + int s_id = std::stoi(call.arg.substr(0, index)); + int value = std::stoi(call.arg.substr(index + 1, call.arg.length())); + storeBuyNow(int s_id, int value); + break; + case MethodType::REGISTER_USER: + registeruser(std::stoi(call.arg)); + break; + case MethodType::PLACE_BID: + size_t index = call.arg.find_first_of('-'); + int a_id = std::stoi(call.arg.substr(0, index)); + std::string sub_arg = call.arg.substr(index + 1, call.arg.length()); + index = sub_arg.find_first_of('-'); + int u_id = std::stoi(sub_arg.substr(0, index)); + int value = std::stoi(sub_arg.substr(index + 1, sub_arg.length())); + placeBid(a_id, u_id, value) + break; + case MethodType::QUERY: + return this; + break; + default: + std::cout << "wrong method name" << std::endl; + break; + } + return this; + } + + + + virtual bool isPermissible(MethodCall call) + { + return true; + } +}; \ No newline at end of file