// RPC test and pseudo-documentation.
// generates print statements on failures, but eventually says "rpctest OK"
-#include "types.h"
-#include "rpc.h"
+#include "include/types.h"
+#include "include/rpc/rpc.h"
#include <arpa/inet.h>
#include <getopt.h>
#include <unistd.h>
#include <string.h>
-#include "threaded_log.h"
+#include "include/debug.h"
#define NUM_CL 2
static rpcs *server; // server rpc object
static rpcc *clients[NUM_CL]; // client rpc object
-static string dst; //server's ip address
+static string * dst; //server's ip address
static in_port_t port;
using std::cout;
using namespace std::chrono;
using std::vector;
-// server-side handlers. they must be methods of some class
-// to simplify rpcs::reg(). a server process can have handlers
-// from multiple classes.
-class srv {
- public:
- int handle_22(string & r, const string a, const string b);
- int handle_fast(int & r, const int a);
- int handle_slow(int & r, const int a);
- int handle_bigrep(string & r, const size_t a);
-};
-
namespace srv_protocol {
- using status = rpc_protocol::status;
+ enum status : rpc_protocol::status {OK};
REMOTE_PROCEDURE_BASE(0);
REMOTE_PROCEDURE(22, _22, (string &, string, string));
REMOTE_PROCEDURE(23, fast, (int &, int));
REMOTE_PROCEDURE(25, bigrep, (string &, size_t));
}
+// server-side handlers. they must be methods of some class
+// to simplify rpcs::reg(). a server process can have handlers
+// from multiple classes.
+class srv {
+ public:
+ srv_protocol::status handle_22(string & r, const string a, const string b);
+ srv_protocol::status handle_fast(int & r, const int a);
+ srv_protocol::status handle_slow(int & r, const int a);
+ srv_protocol::status handle_bigrep(string & r, const size_t a);
+};
+
// a handler. a and b are arguments, r is the result.
// there can be multiple arguments but only one result.
// the caller also gets to see the int return value
// rpcs::reg() decides how to unmarshall by looking
// at these argument types, so this function definition
// does what a .x file does in SunRPC.
-int srv::handle_22(string & r, const string a, string b) {
+srv_protocol::status srv::handle_22(string & r, const string a, string b) {
r = a + b;
- return 0;
+ return srv_protocol::OK;
}
-int srv::handle_fast(int & r, const int a) {
+srv_protocol::status srv::handle_fast(int & r, const int a) {
r = a + 1;
- return 0;
+ return srv_protocol::OK;
}
-int srv::handle_slow(int & r, const int a) {
- usleep(random() % 500);
+srv_protocol::status srv::handle_slow(int & r, const int a) {
+ auto duration = std::uniform_int_distribution<>(0,500)(global->random_generator) * 1us;
+ std::this_thread::sleep_for(duration);
r = a + 2;
- return 0;
+ return srv_protocol::OK;
}
-int srv::handle_bigrep(string & r, const size_t len) {
+srv_protocol::status srv::handle_bigrep(string & r, const size_t len) {
r = string(len, 'x');
- return 0;
+ return srv_protocol::OK;
}
static srv service;
static void testmarshall() {
marshall m;
rpc_protocol::request_header rh{1,2,3,4,5};
- m.write_header(rh);
- VERIFY(((string)m).size()==rpc_protocol::RPC_HEADER_SZ);
+ VERIFY(marshall::datagram(rh, m).size()==rpc_protocol::RPC_HEADER_SZ);
int i = 12345;
unsigned long long l = 1223344455L;
size_t sz = 101010101;
m << sz;
m << bin;
- string b = m;
- VERIFY(b.size() == rpc_protocol::RPC_HEADER_SZ+sizeof(i)+sizeof(l)+sizeof(uint32_t)+s.size()+sizeof(uint32_t)+sizeof(uint32_t)+bin.size());
+ string b = marshall::datagram(rh, m);
+ VERIFY(b.size() == rpc_protocol::RPC_HEADER_SZ+sizeof(i)+sizeof(l)+sizeof(uint32_t)+s.size()+sizeof(uint64_t)+sizeof(uint32_t)+bin.size());
- unmarshall un(b, true);
rpc_protocol::request_header rh1;
- un.read_header(rh1);
+ auto un = unmarshall::datagram(b, rh1);
VERIFY(memcmp(&rh,&rh1,sizeof(rh))==0);
int i1;
unsigned long long l1;
size_t which_cl = cl % NUM_CL;
for(int i = 0; i < 100; i++){
- unsigned long arg = (random() % 2000);
+ auto arg = std::uniform_int_distribution<unsigned long>(0,2000)(global->random_generator);
string rep;
int ret = clients[which_cl]->call(srv_protocol::bigrep, rep, arg);
VERIFY(ret == 0);
// test rpc replies coming back not in the order of
// the original calls -- i.e. does xid reply dispatch work.
for(int i = 0; i < 100; i++){
- int which = (random() % 2);
- int arg = (random() % 1000);
+ bool which = std::bernoulli_distribution()(global->random_generator);
+ int arg = std::uniform_int_distribution<>(0,1000)(global->random_generator);
int rep = -1;
auto start = steady_clock::now();
int ret = clients[which_cl]->call(which ? srv_protocol::fast : srv_protocol::slow, rep, arg);
auto end = steady_clock::now();
- auto diff = duration_cast<milliseconds>(end - start).count();
+ auto diff = (end - start) / 1ms;
if (ret != 0)
cout << diff << " ms have elapsed!!!" << endl;
VERIFY(ret == 0);
time(&t1);
while(time(0) - t1 < 10){
- unsigned long arg = (random() % 2000);
+ auto arg = std::uniform_int_distribution<unsigned long>(0,2000)(global->random_generator);
string rep;
int ret = clients[which_cl]->call(srv_protocol::bigrep, rep, arg);
if ((unsigned long)rep.size()!=arg)
for(int i = 0; i < 4; i++){
int rep = 0;
- int ret = c->call_timeout(srv_protocol::slow, milliseconds(300), rep, i);
+ int ret = c->call_timeout(srv_protocol::slow, 300ms, rep, i);
VERIFY(ret == rpc_protocol::timeout_failure || rep == i+2);
}
}
cout << " -- string concat RPC .. ok" << endl;
// small request, big reply (perhaps req via UDP, reply via TCP)
- intret = c->call_timeout(srv_protocol::bigrep, milliseconds(20000), rep, 70000ul);
+ intret = c->call_timeout(srv_protocol::bigrep, 20000ms, rep, 70000ul);
VERIFY(intret == 0);
VERIFY(rep.size() == 70000);
cout << " -- small request, big reply .. ok" << endl;
// specify a timeout value to an RPC that should succeed (udp)
int xx = 0;
- intret = c->call_timeout(srv_protocol::fast, milliseconds(300), xx, 77);
+ intret = c->call_timeout(srv_protocol::fast, 300ms, xx, 77);
VERIFY(intret == 0 && xx == 78);
cout << " -- no spurious timeout .. ok" << endl;
{
string arg(1000, 'x');
string rep2;
- c->call_timeout(srv_protocol::_22, milliseconds(300), rep2, arg, (string)"x");
+ c->call_timeout(srv_protocol::_22, 300ms, rep2, arg, (string)"x");
VERIFY(rep2.size() == 1001);
cout << " -- no spurious timeout .. ok" << endl;
}
string non_existent = "127.0.0.1:7661";
rpcc *c1 = new rpcc(non_existent);
time_t t0 = time(0);
- intret = c1->bind(milliseconds(300));
+ intret = c1->bind(300ms);
time_t t1 = time(0);
VERIFY(intret < 0 && (t1 - t0) <= 4);
cout << " -- rpc timeout .. ok" << endl;
for (int i = 0; i < NUM_CL; i++) {
delete clients[i];
- clients[i] = new rpcc(dst);
+ clients[i] = new rpcc(*dst);
VERIFY(clients[i]->bind()==0);
}
delete server;
- client1 = new rpcc(dst);
- VERIFY (client1->bind(milliseconds(3000)) < 0);
+ client1 = new rpcc(*dst);
+ VERIFY (client1->bind(3000ms) < 0);
cout << " -- create new client and try to bind to failed server .. failed ok" << endl;
delete client1;
delete client;
- clients[0] = client = new rpcc(dst);
+ clients[0] = client = new rpcc(*dst);
VERIFY (client->bind() >= 0);
VERIFY (client->bind() < 0);
delete client;
startserver();
- clients[0] = client = new rpcc(dst);
+ clients[0] = client = new rpcc(*dst);
VERIFY (client->bind() >= 0);
cout << " -- delete existing rpc client and server, create replacements.. ok" << endl;
bool isclient = false;
bool isserver = false;
- srandom((uint32_t)getpid());
port = 20000 + (getpid() % 10000);
int ch = 0;
}
if (debug_level > 0) {
- DEBUG_LEVEL = debug_level;
+ global->DEBUG_LEVEL = debug_level;
IF_LEVEL(1) LOG_NONMEMBER << "DEBUG LEVEL: " << debug_level;
}
if (isclient) {
// server's address.
- dst = "127.0.0.1:" + std::to_string(port);
+ dst = new string("127.0.0.1:" + std::to_string(port));
// start the client. bind it to the server.
// be only one rpcc per process. you probably need one
// rpcc per server.
for (int i = 0; i < NUM_CL; i++) {
- clients[i] = new rpcc(dst);
+ clients[i] = new rpcc(*dst);
VERIFY (clients[i]->bind() == 0);
}
}
while (1)
- usleep(100000);
+ std::this_thread::sleep_for(100ms);
}