Skip to content

Commit

Permalink
added rubis
Browse files Browse the repository at this point in the history
  • Loading branch information
javadsaberlatibari authored Mar 20, 2024
1 parent 7fd863e commit e074150
Show file tree
Hide file tree
Showing 2 changed files with 342 additions and 0 deletions.
183 changes: 183 additions & 0 deletions wellcoordination/benchmark/rubis-benchmark.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
#include <cstdio>
#include <fstream>
#include <iostream>
#include <string>
#include <thread>

#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<int>(std::atoi(argv[1]));
int num_ops = static_cast<int>(std::atoi(argv[2]));
double write_percentage = static_cast<double>(std::atoi(argv[3]));

loc += std::to_string(nr_procs) + "-" + std::to_string(num_ops) + "-" +
std::to_string(static_cast<int>(write_percentage));
loc += "/rubis/";

std::ofstream* outfile = new std::ofstream[nr_procs];
std::vector<std::string>* calls = new std::vector<std::string>[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<std::string>();
}

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;
}
159 changes: 159 additions & 0 deletions wellcoordination/benchmark/rubis.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <cstdarg>
#include <cstring>
#include <unordered_set>

#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<int> auction [100][3]={{0}}; //auctionid-quantity-user propsed max value-max value
bool registeredusers [100]={false};
int userscounter=0;
//std::set<std::string> movies;
//std::set<std::string> customers;


Rubis() {
read_methods.push_back(static_cast<int>(MethodType::QUERY));

update_methods.push_back(static_cast<int>(MethodType::SELL_ITEM));
update_methods.push_back(static_cast<int>(MethodType::STORE_BUY_NOW));
update_methods.push_back(static_cast<int>(MethodType::REGISTER_USER));
update_methods.push_back(static_cast<int>(MethodType::PLACE_BID));

method_args.insert(std::make_pair(static_cast<int>(MethodType::SELL_ITEM), 2));
method_args.insert(std::make_pair(static_cast<int>(MethodType::STORE_BUY_NOW), 2));
method_args.insert(std::make_pair(static_cast<int>(MethodType::REGISTER_USER), 1));
method_args.insert(std::make_pair(static_cast<int>(MethodType::PLACE_BID), 3));
method_args.insert(std::make_pair(static_cast<int>(MethodType::QUERY), 0));

// conflicts
std::vector<int> g1;
g1.push_back(static_cast<int>(MethodType::STORE_BUY_NOW));
//g1.push_back(static_cast<int>(MethodType::REMOVE_MOVIE));
synch_groups.push_back(g1);
std::vector<int> g2;
g2.push_back(static_cast<int>(MethodType::REGISTER_USER));
//g2.push_back(static_cast<int>(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]<value){
auction[a_id][1]=u_id;
auction[a_id][2]=value;
}
}
}

Rubis query() { return *this; }


virtual ReplicatedObject* execute(MethodCall call)
{
switch (static_cast<MethodType>(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;
}
};

0 comments on commit e074150

Please sign in to comment.