-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7fd863e
commit e074150
Showing
2 changed files
with
342 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
}; |