/tests/scripts/mesh_test.cpp

https://github.com/vkhoroshko/voltdb · C++ · 733 lines · 651 code · 49 blank · 33 comment · 96 complexity · eb855bd411bfeeebd20bda9c0ff5b543 MD5 · raw file

  1. /* This file is part of VoltDB.
  2. * Copyright (C) 2008-2014 VoltDB Inc.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining
  5. * a copy of this software and associated documentation files (the
  6. * "Software"), to deal in the Software without restriction, including
  7. * without limitation the rights to use, copy, modify, merge, publish,
  8. * distribute, sublicense, and/or sell copies of the Software, and to
  9. * permit persons to whom the Software is furnished to do so, subject to
  10. * the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  18. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  19. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  20. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  21. * OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #include <iostream>
  24. #include <string>
  25. #include <vector>
  26. #include <boost/unordered_map.hpp>
  27. #include <boost/unordered_set.hpp>
  28. #include <set>
  29. #include <deque>
  30. #include <boost/bind.hpp>
  31. #include <boost/asio.hpp>
  32. #include <queue>
  33. #include <limits>
  34. using namespace std;
  35. using boost::asio::ip::tcp;
  36. class QueueEntry {
  37. public:
  38. QueueEntry(tcp::socket *nsocket, int64_t nrequestId) : socket(nsocket), requestId(nrequestId) {}
  39. tcp::socket *socket;
  40. int64_t requestId;
  41. };
  42. class CompareQueueEntry {
  43. public:
  44. bool operator()(const QueueEntry& lhs, const QueueEntry& rhs) const {
  45. if (lhs.requestId > rhs.requestId) {
  46. return true;
  47. }
  48. return false;
  49. }
  50. };
  51. class WriteStuff {
  52. public:
  53. WriteStuff(size_t nlength, size_t noffset, int64_t *ncounter) : length(nlength), offset(noffset), counter(ncounter) {}
  54. size_t length;
  55. size_t offset;
  56. int64_t *counter;
  57. };
  58. class Server
  59. {
  60. public:
  61. Server(boost::asio::io_service &io_service, std::vector<std::string> servers) :
  62. nextRequestId(0),
  63. requestsReceived(0),
  64. responsesSent(0),
  65. meshRequestsReceived(0),
  66. meshRequestsSent(0),
  67. meshResponsesSent(0),
  68. meshResponsesReceived(0),
  69. bytesWritten(0),
  70. bytesRead(0),
  71. bytesWrittenLastTime(0),
  72. bytesReadLastTime(0),
  73. serverAcceptor(io_service, tcp::endpoint(tcp::v4(), 21413)),
  74. clientAcceptor(io_service, tcp::endpoint(tcp::v4(), 21412)) {
  75. tcp::socket *socket = new tcp::socket(io_service);
  76. serverAcceptor.async_accept( *socket,
  77. boost::bind(
  78. &Server::handleServerAccept,
  79. this,
  80. boost::asio::placeholders::error,
  81. &serverAcceptor,
  82. socket));
  83. socket = new tcp::socket(io_service);
  84. clientAcceptor.async_accept( *socket,
  85. boost::bind(
  86. &Server::handleClientAccept,
  87. this,
  88. boost::asio::placeholders::error,
  89. &clientAcceptor,
  90. socket));
  91. tcp::resolver resolver(io_service);
  92. for (std::size_t ii = 0; ii < servers.size(); ii++) {
  93. tcp::resolver::query query(servers[ii], "21413");
  94. tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
  95. tcp::socket* socket = new tcp::socket(io_service);
  96. tcp::endpoint endpoint = *endpoint_iterator;
  97. socket->async_connect( endpoint,
  98. boost::bind( &Server::handleConnect, this, boost::asio::placeholders::error, endpoint_iterator, socket));
  99. }
  100. boost::asio::deadline_timer *timer = new boost::asio::deadline_timer(io_service);
  101. timer->expires_from_now(boost::posix_time::seconds(10));
  102. timer->async_wait(boost::bind(&Server::timerCallback, this, boost::asio::placeholders::error, timer));
  103. }
  104. void timerCallback(const boost::system::error_code& error, boost::asio::deadline_timer *timer) {
  105. if (error) {
  106. std::cout << error.message() << std::endl;
  107. }
  108. int64_t bytesReadThisTime = bytesRead - bytesReadLastTime;
  109. bytesReadLastTime = bytesRead;
  110. int64_t bytesWrittenThisTime = bytesWritten - bytesWrittenLastTime;
  111. bytesWrittenLastTime = bytesWritten;
  112. int64_t mbReadThisTime = bytesReadThisTime / (1024 * 1024);
  113. int64_t mbWrittenThisTime = bytesWrittenThisTime / (1024 * 1024);
  114. double mbReadPerSec = mbReadThisTime / 10.0;
  115. double mbWrittenPerSec = mbWrittenThisTime / 10.0;
  116. std::cout << "Megabytes/sec In/Out " << mbReadPerSec << "/" << mbWrittenPerSec << std::endl;
  117. std::cout << "Requests received " << requestsReceived << " Responses sent " << responsesSent << " MRequests received "
  118. << meshRequestsReceived << " MRequests sent " << meshRequestsSent << " MResponses sent " << meshResponsesSent <<
  119. " MResponses received " << meshResponsesReceived << " Outstanding requests " << (requestsReceived - responsesSent) << std::endl;
  120. timer->expires_from_now(boost::posix_time::seconds(10));
  121. timer->async_wait(boost::bind(&Server::timerCallback, this, boost::asio::placeholders::error, timer));
  122. }
  123. void handleConnect(const boost::system::error_code& error,
  124. tcp::resolver::iterator endpoint_iterator, tcp::socket* socket) {
  125. if (error) {
  126. std::cout << error.message() << std::endl;
  127. socket->close();
  128. ++endpoint_iterator;
  129. if (endpoint_iterator != tcp::resolver::iterator()) {
  130. tcp::endpoint endpoint = *endpoint_iterator;
  131. socket->async_connect(endpoint,
  132. boost::bind( &Server::handleConnect, this, boost::asio::placeholders::error, endpoint_iterator, socket));
  133. }
  134. } else {
  135. std::cout << "Connected to server " << socket->remote_endpoint().address().to_string() << std::endl;
  136. boost::asio::ip::tcp::no_delay option(true);
  137. socket->set_option(option);
  138. boost::asio::ip::tcp::socket::non_blocking_io nonblocking(true);
  139. socket->io_control(nonblocking);
  140. serverSockets.push_back(socket);
  141. socketAsyncWritePending[socket] = false;
  142. char *buffer = acquireBuffer();
  143. requestIdsResponded[socket] = new boost::unordered_set<int64_t>();
  144. requestIdsRequested[socket] = new boost::unordered_set<int64_t>();
  145. socketAsyncWrites[socket] = new std::deque<std::pair<char*, WriteStuff> >();
  146. boost::asio::async_read( *socket, boost::asio::buffer( buffer, 4), boost::bind(&Server::handleServerRead, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, socket, buffer, true));
  147. }
  148. }
  149. void handleServerAccept(
  150. const boost::system::error_code& error,
  151. tcp::acceptor *acceptor,
  152. tcp::socket* socket) {
  153. if (error) {
  154. std::cout << error.message() << std::endl;
  155. return;
  156. }
  157. if (!error) {
  158. std::cout << "Accepted from server " << socket->remote_endpoint().address().to_string() << std::endl;
  159. socketAsyncWritePending[socket] = false;
  160. serverSockets.push_back(socket);
  161. tcp::socket *newsocket = new tcp::socket(acceptor->io_service());
  162. acceptor->async_accept(*newsocket, boost::bind(&Server::handleServerAccept, this, boost::asio::placeholders::error, acceptor, newsocket));
  163. boost::asio::ip::tcp::no_delay option(true);
  164. socket->set_option(option);
  165. boost::asio::ip::tcp::socket::receive_buffer_size receiveSize(262144);
  166. boost::asio::ip::tcp::socket::send_buffer_size sendSize(262144);
  167. socket->set_option(receiveSize);
  168. socket->set_option(sendSize);
  169. char *buffer = acquireBuffer();
  170. boost::asio::ip::tcp::socket::non_blocking_io nonblocking(true);
  171. socket->io_control(nonblocking);
  172. requestIdsResponded[socket] = new boost::unordered_set<int64_t>();
  173. requestIdsRequested[socket] = new boost::unordered_set<int64_t>();
  174. socketAsyncWrites[socket] = new std::deque<std::pair<char*, WriteStuff> >();
  175. boost::asio::async_read( *socket, boost::asio::buffer( buffer, 4), boost::bind(&Server::handleServerRead, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, socket, buffer, true));
  176. }
  177. }
  178. void handleServerRead(const boost::system::error_code& error,
  179. size_t bytes_transferred, tcp::socket* socket, char *buffer, bool lengthOrMessage) {
  180. if (error) {
  181. std::cout << error.message() << std::endl;
  182. releaseBuffer(buffer);
  183. return;
  184. }
  185. bytesRead += bytes_transferred;
  186. size_t nextLength = 0;
  187. size_t nextBufferOffset;
  188. while (true) {
  189. nextBufferOffset = 0;
  190. if (lengthOrMessage) {
  191. nextLength = *reinterpret_cast<int32_t*>(buffer);
  192. nextBufferOffset = 4;
  193. lengthOrMessage = false;
  194. if (nextLength <= 0 || nextLength > 1500) {
  195. std::cout << "Next length from server was " << nextLength << std::endl;
  196. exit(-1);
  197. }
  198. } else {
  199. nextLength = 4;
  200. lengthOrMessage = true;
  201. if (buffer[4] == 0) {
  202. //request
  203. meshRequestsReceived++;
  204. int64_t requestId = *reinterpret_cast<int64_t*>(&buffer[5]);
  205. addQueueEntry(socket, requestId);
  206. } else if (buffer[4] == 1) {
  207. //response
  208. meshResponsesReceived++;
  209. int32_t responseLength = *reinterpret_cast<int32_t*>(buffer);
  210. int64_t requestId = *reinterpret_cast<int64_t*>(&buffer[5]);
  211. char *copy = acquireBuffer();
  212. ::memcpy( copy, buffer, responseLength + 4);
  213. tcp::socket *clientSocket = requestIdToClient[requestId];
  214. requestIdToClient.erase(requestId);
  215. // if (!requestIdsResponded[socket]->insert(requestId).second) {
  216. // std::cout << "Request ID " << requestId << " has already been responded to" << std::endl;
  217. // }
  218. size_t written = 0;
  219. bool asyncWritePending = socketAsyncWritePending[clientSocket];
  220. try {
  221. if (!asyncWritePending) {
  222. written = clientSocket->write_some(boost::asio::buffer(copy, responseLength + 4));
  223. }
  224. } catch (boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >) {
  225. }
  226. bytesWritten += written;
  227. if (written != static_cast<size_t>(responseLength + 4)) {
  228. size_t length = responseLength + 4 - written;
  229. if (asyncWritePending) {
  230. socketAsyncWrites[clientSocket]->push_back(std::pair<char*, WriteStuff>(copy, WriteStuff(length, written, &responsesSent)));
  231. } else {
  232. boost::asio::async_write( *clientSocket, boost::asio::buffer(&copy[written], length),
  233. boost::bind(&Server::handleWriteCompletion, this, boost::asio::placeholders::error,
  234. boost::asio::placeholders::bytes_transferred, clientSocket, copy, &responsesSent));
  235. socketAsyncWritePending[clientSocket] = true;
  236. }
  237. } else {
  238. releaseBuffer(copy);
  239. responsesSent++;
  240. backpressureCheck();
  241. }
  242. }
  243. }
  244. try {
  245. size_t read = socket->read_some(boost::asio::buffer( &buffer[nextBufferOffset], nextLength));
  246. bytesRead += read;
  247. if (read < nextLength) {
  248. boost::asio::async_read( *socket, boost::asio::buffer(&buffer[nextBufferOffset + read], nextLength - read),
  249. boost::bind(&Server::handleServerRead, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, socket, buffer, lengthOrMessage));
  250. drainPriorityQueue();
  251. return;
  252. }
  253. } catch (boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >) {
  254. boost::asio::async_read( *socket, boost::asio::buffer(&buffer[nextBufferOffset], nextLength),
  255. boost::bind(&Server::handleServerRead, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, socket, buffer, lengthOrMessage));
  256. drainPriorityQueue();
  257. return;
  258. }
  259. }
  260. }
  261. void handleClientRead(const boost::system::error_code& error,
  262. size_t bytes_transferred, tcp::socket* socket, char *buffer, bool lengthOrMessage) {
  263. if (error) {
  264. std::cout << error.message() << std::endl;
  265. releaseBuffer(buffer);
  266. return;
  267. }
  268. bytesRead += bytes_transferred;
  269. const size_t maxRead = 16384;
  270. size_t totalClientRead = 0;
  271. size_t nextLength = 0;
  272. int outstandingRequests = 0;
  273. while (true) {
  274. if (lengthOrMessage) {
  275. nextLength = *reinterpret_cast<int32_t*>(buffer);
  276. lengthOrMessage = false;
  277. if (nextLength <= 0 || nextLength > 1500) {
  278. std::cout << "Next length from client was " << nextLength << std::endl;
  279. exit(-1);
  280. }
  281. } else {
  282. nextLength = 4;
  283. lengthOrMessage = true;
  284. requestsReceived++;
  285. int64_t requestId = nextRequestId++;
  286. char *request = acquireBuffer();
  287. *reinterpret_cast<int32_t*>(request) = 60;
  288. *reinterpret_cast<int8_t*>(&request[4]) = 0;//request
  289. *reinterpret_cast<int64_t*>(&request[5]) = requestId;
  290. requestIdToClient[requestId] = socket;
  291. size_t serverIndex = rand() % serverSockets.size();
  292. tcp::socket *serverSocket = serverSockets[serverIndex];
  293. size_t written = 0;
  294. bool asyncWritePending = socketAsyncWritePending[serverSocket];
  295. try {
  296. if ( !asyncWritePending ) {
  297. written = serverSocket->write_some(boost::asio::buffer(request, 64));
  298. }
  299. } catch (boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >) {
  300. }
  301. bytesWritten += written;
  302. if (written < 64) {
  303. size_t length = 64 - written;
  304. if (asyncWritePending) {
  305. socketAsyncWrites[serverSocket]->push_back(std::pair<char*, WriteStuff>(request, WriteStuff(length, written, &meshRequestsSent)));
  306. } else {
  307. boost::asio::async_write( *serverSocket, boost::asio::buffer(&request[written], length),
  308. boost::bind(&Server::handleWriteCompletion, this, boost::asio::placeholders::error,
  309. boost::asio::placeholders::bytes_transferred, serverSocket, request, &meshRequestsSent));
  310. socketAsyncWritePending[serverSocket] = true;
  311. }
  312. } else {
  313. releaseBuffer(request);
  314. meshRequestsSent++;
  315. }
  316. }
  317. outstandingRequests = requestsReceived - responsesSent;
  318. if (outstandingRequests > 15000 && lengthOrMessage) {
  319. releaseBuffer(buffer);
  320. backpressureSockets.insert(socket);
  321. return;
  322. } else {
  323. try {
  324. size_t read = 0;
  325. if (lengthOrMessage || totalClientRead < maxRead) {
  326. read = socket->read_some(boost::asio::buffer(buffer, nextLength));
  327. bytesRead += read;
  328. totalClientRead += read;
  329. }
  330. if (read < nextLength) {
  331. boost::asio::async_read( *socket, boost::asio::buffer(&buffer[read], nextLength - read),
  332. boost::bind(&Server::handleClientRead, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, socket, buffer, lengthOrMessage));
  333. return;
  334. }
  335. } catch (boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >) {
  336. boost::asio::async_read( *socket, boost::asio::buffer(buffer, nextLength),
  337. boost::bind(&Server::handleClientRead, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, socket, buffer, lengthOrMessage));
  338. return;
  339. }
  340. }
  341. }
  342. }
  343. void handleWriteCompletion(const boost::system::error_code& error,
  344. size_t bytes_transferred, tcp::socket* socket, char *buffer, int64_t *counter) {
  345. if (error) {
  346. std::cout << error.message() << std::endl;
  347. releaseBuffer(buffer);
  348. return;
  349. }
  350. bytesWritten += bytes_transferred;
  351. *counter = *counter + 1;
  352. releaseBuffer(buffer);
  353. socketAsyncWritePending[socket] = false;
  354. backpressureCheck();
  355. std::deque<std::pair<char*, WriteStuff> > *pendingWrites = socketAsyncWrites[socket];
  356. while (!pendingWrites->empty()) {
  357. std::pair<char*, WriteStuff> pendingWrite = pendingWrites->front();
  358. pendingWrites->pop_front();
  359. char * pendingBuffer = pendingWrite.first;
  360. size_t writeLength = pendingWrite.second.length;
  361. size_t writeOffset = pendingWrite.second.offset;
  362. int64_t *counter = pendingWrite.second.counter;
  363. size_t written = 0;
  364. try {
  365. written = socket->write_some(boost::asio::buffer( &pendingBuffer[writeOffset], writeLength));
  366. } catch (boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >) {
  367. }
  368. if (written < writeLength) {
  369. size_t length = writeLength - written;
  370. boost::asio::async_write( *socket, boost::asio::buffer(&pendingBuffer[writeOffset + written], length),
  371. boost::bind(&Server::handleWriteCompletion, this, boost::asio::placeholders::error,
  372. boost::asio::placeholders::bytes_transferred, socket, pendingBuffer, counter));
  373. socketAsyncWritePending[socket] = true;
  374. break;
  375. } else {
  376. releaseBuffer(pendingBuffer);
  377. *counter = *counter + 1;
  378. }
  379. }
  380. }
  381. /*
  382. * Check if there is no more backpressure and reactivate reads for client sockets.
  383. */
  384. void backpressureCheck() {
  385. int outstandingRequests = requestsReceived - responsesSent;
  386. if (outstandingRequests < 10000) {
  387. if (backpressureSockets.size() > 0) {
  388. for (boost::unordered_set<tcp::socket*>::iterator i = backpressureSockets.begin();
  389. i != backpressureSockets.end(); i++) {
  390. tcp::socket *clientSocket = *i;
  391. char *newbuffer = acquireBuffer();
  392. boost::asio::async_read( *clientSocket, boost::asio::buffer( newbuffer, 4), boost::bind(&Server::handleClientRead, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, clientSocket, newbuffer, true));
  393. }
  394. backpressureSockets.clear();
  395. }
  396. }
  397. }
  398. void handleClientAccept(
  399. const boost::system::error_code& error,
  400. tcp::acceptor *acceptor,
  401. tcp::socket* socket) {
  402. if (error) {
  403. std::cout << error.message() << std::endl;
  404. return;
  405. }
  406. if (!error) {
  407. std::cout << "Accepted from client " << socket->remote_endpoint().address().to_string() << std::endl;
  408. clientSockets.push_back(socket);
  409. tcp::socket *newsocket = new tcp::socket(acceptor->io_service());
  410. acceptor->async_accept(*newsocket, boost::bind(&Server::handleClientAccept, this, boost::asio::placeholders::error, acceptor, newsocket));
  411. char *buffer = acquireBuffer();
  412. boost::asio::ip::tcp::socket::receive_buffer_size receiveSize(262144);
  413. boost::asio::ip::tcp::socket::send_buffer_size sendSize(262144);
  414. boost::asio::ip::tcp::socket::non_blocking_io nonblocking(true);
  415. socket->io_control(nonblocking);
  416. socket->set_option(receiveSize);
  417. socket->set_option(sendSize);
  418. socketAsyncWritePending[socket] = false;
  419. socketAsyncWrites[socket] = new std::deque<std::pair<char*, WriteStuff> >();
  420. boost::asio::async_read( *socket, boost::asio::buffer( buffer, 4), boost::bind(&Server::handleClientRead, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, socket, buffer, true));
  421. }
  422. }
  423. char* acquireBuffer() {
  424. if (buffers.empty()) {
  425. char * buffer = new char[1500];
  426. ::memset(buffer, 0, 1500);
  427. return buffer;
  428. } else {
  429. char *buffer = buffers.back();
  430. buffers.pop_back();
  431. return buffer;
  432. }
  433. }
  434. void releaseBuffer(char *buffer) {
  435. buffers.push_back(buffer);
  436. }
  437. void addQueueEntry(tcp::socket *socket, int64_t requestId) {
  438. std::map<tcp::socket*, int64_t>::iterator iter = lastSafeRequestId.find(socket);
  439. if (iter == lastSafeRequestId.end()) {
  440. lastSafeRequestId[socket] = requestId;
  441. } else if (iter->second < requestId) {
  442. iter->second = requestId;
  443. }
  444. queue.push(QueueEntry(socket, requestId));
  445. }
  446. void sendResponse(QueueEntry entry) {
  447. tcp::socket *socket = entry.socket;
  448. char *response = acquireBuffer();
  449. int responseLength = 256 + (rand() % 600);
  450. ::memset(response, 0, responseLength + 4);
  451. *reinterpret_cast<int32_t*>(response) = responseLength;
  452. *reinterpret_cast<int8_t*>(&response[4]) = 1;//response
  453. *reinterpret_cast<int64_t*>(&response[5]) = entry.requestId;
  454. // if (!requestIdsRequested[socket]->insert(*reinterpret_cast<int64_t*>(&response[5])).second) {
  455. // std::cout << "Request ID " << *reinterpret_cast<int64_t*>(&response[5]) << " has already been requested" << std::endl;
  456. // }
  457. size_t written = 0;
  458. bool asyncWritePending = socketAsyncWritePending[socket];
  459. try {
  460. if (!asyncWritePending) {
  461. written = socket->write_some(boost::asio::buffer(response, responseLength + 4));
  462. }
  463. } catch (boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >) {
  464. }
  465. bytesWritten += written;
  466. if (written != static_cast<size_t>(responseLength + 4)) {
  467. size_t length = responseLength + 4 - written;
  468. if (asyncWritePending) {
  469. socketAsyncWrites[socket]->push_back(std::pair<char*, WriteStuff>(response, WriteStuff(length, written, &meshResponsesSent)));
  470. } else {
  471. boost::asio::async_write( *socket, boost::asio::buffer(&response[written], length),
  472. boost::bind(&Server::handleWriteCompletion, this, boost::asio::placeholders::error,
  473. boost::asio::placeholders::bytes_transferred, socket, response, &meshResponsesSent));
  474. socketAsyncWritePending[socket] = true;
  475. }
  476. } else {
  477. releaseBuffer(response);
  478. meshResponsesSent++;
  479. }
  480. }
  481. void drainPriorityQueue() {
  482. int64_t minRequestId = std::numeric_limits<int64_t>::max();
  483. for (std::map<tcp::socket*, int64_t>::iterator iter = lastSafeRequestId.begin();
  484. iter != lastSafeRequestId.end();
  485. iter++) {
  486. if (iter->second < minRequestId) {
  487. minRequestId = iter->second;
  488. }
  489. }
  490. while (!queue.empty() && queue.top().requestId <= minRequestId) {
  491. QueueEntry entry = queue.top();
  492. queue.pop();
  493. sendResponse(entry);
  494. }
  495. }
  496. std::deque<char*> buffers;
  497. int64_t nextRequestId;
  498. int64_t requestsReceived;
  499. int64_t responsesSent;
  500. int64_t meshRequestsReceived;
  501. int64_t meshRequestsSent;
  502. int64_t meshResponsesSent;
  503. int64_t meshResponsesReceived;
  504. int64_t bytesWritten;
  505. int64_t bytesRead;
  506. int64_t bytesWrittenLastTime;
  507. int64_t bytesReadLastTime;
  508. boost::unordered_set<tcp::socket*> backpressureSockets;
  509. tcp::acceptor serverAcceptor;
  510. tcp::acceptor clientAcceptor;
  511. std::vector<tcp::socket*> serverSockets;
  512. std::vector<tcp::socket*> clientSockets;
  513. boost::unordered_map<tcp::socket*, boost::unordered_set<int64_t>*> requestIdsResponded;
  514. boost::unordered_map<tcp::socket*, boost::unordered_set<int64_t>*> requestIdsRequested;
  515. boost::unordered_map<int64_t, tcp::socket*> requestIdToClient;
  516. boost::unordered_map<tcp::socket*, bool> socketAsyncWritePending;
  517. boost::unordered_map<tcp::socket*, std::deque<std::pair<char*, WriteStuff> >* > socketAsyncWrites;
  518. std::map<tcp::socket*, int64_t> lastSafeRequestId;
  519. std::priority_queue< QueueEntry, std::vector<QueueEntry>, CompareQueueEntry> queue;
  520. };
  521. class Client {
  522. public:
  523. Client( boost::asio::io_service &io_service, std::vector<std::string> servers) :
  524. requestsSent(0),
  525. responsesReceived(0),
  526. responsesReceivedLastTime(0),
  527. bytesWritten(0),
  528. bytesRead(0),
  529. bytesWrittenLastTime(0),
  530. bytesReadLastTime(0) {
  531. tcp::resolver resolver(io_service);
  532. for (std::size_t ii = 0; ii < servers.size(); ii++) {
  533. tcp::resolver::query query(servers[ii], "21412");
  534. tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
  535. tcp::socket* socket = new tcp::socket(io_service);
  536. tcp::endpoint endpoint = *endpoint_iterator;
  537. socket->async_connect( endpoint,
  538. boost::bind( &Client::handleConnect, this, boost::asio::placeholders::error, endpoint_iterator, socket));
  539. }
  540. boost::asio::deadline_timer *timer = new boost::asio::deadline_timer(io_service);
  541. timer->expires_from_now(boost::posix_time::seconds(10));
  542. timer->async_wait(boost::bind(&Client::timerCallback, this, boost::asio::placeholders::error, timer));
  543. }
  544. void timerCallback(const boost::system::error_code& error, boost::asio::deadline_timer *timer) {
  545. if (error) {
  546. std::cout << error.message() << std::endl;
  547. }
  548. int64_t bytesReadThisTime = bytesRead - bytesReadLastTime;
  549. bytesReadLastTime = bytesRead;
  550. int64_t bytesWrittenThisTime = bytesWritten - bytesWrittenLastTime;
  551. bytesWrittenLastTime = bytesWritten;
  552. int64_t mbReadThisTime = bytesReadThisTime / (1024 * 1024);
  553. int64_t mbWrittenThisTime = bytesWrittenThisTime / (1024 * 1024);
  554. double mbReadPerSec = mbReadThisTime / 10.0;
  555. double mbWrittenPerSec = mbWrittenThisTime / 10.0;
  556. int64_t responsesReceivedThisTime = responsesReceived - responsesReceivedLastTime;
  557. responsesReceivedLastTime = responsesReceived;
  558. double requestsPerSec = responsesReceivedThisTime / 10.0;
  559. std::cout << "Requests/sec " << requestsPerSec << " Requests sent " << requestsSent << " Responses received " << responsesReceived << " Megabytes/sec In/Out " << mbReadPerSec << "/" << mbWrittenPerSec << std::endl;
  560. timer->expires_from_now(boost::posix_time::seconds(10));
  561. timer->async_wait(boost::bind(&Client::timerCallback, this, boost::asio::placeholders::error, timer));
  562. }
  563. void handleConnect(const boost::system::error_code& error,
  564. tcp::resolver::iterator endpoint_iterator, tcp::socket* socket) {
  565. if (error) {
  566. std::cout << error.message() << std::endl;
  567. socket->close();
  568. ++endpoint_iterator;
  569. if (endpoint_iterator != tcp::resolver::iterator()) {
  570. tcp::endpoint endpoint = *endpoint_iterator;
  571. socket->async_connect(endpoint,
  572. boost::bind( &Client::handleConnect, this, boost::asio::placeholders::error, endpoint_iterator, socket));
  573. }
  574. } else {
  575. std::cout << "Connected to " << socket->remote_endpoint().address().to_string() << std::endl;
  576. char *recBuffer = new char[1500];
  577. ::memset(recBuffer, 0, 1500);
  578. char *sendBuffer = new char[1500];
  579. ::memset(sendBuffer, 0, 1500);
  580. *reinterpret_cast<int32_t*>(sendBuffer) = 60;
  581. boost::asio::ip::tcp::socket::receive_buffer_size receiveSize(262144);
  582. boost::asio::ip::tcp::socket::send_buffer_size sendSize(262144);
  583. socket->set_option(receiveSize);
  584. socket->set_option(sendSize);
  585. boost::asio::ip::tcp::socket::non_blocking_io nonblocking(true);
  586. socket->io_control(nonblocking);
  587. boost::asio::async_write( *socket, boost::asio::buffer(sendBuffer, 64),
  588. boost::bind(&Client::handleWriteCompletion, this, boost::asio::placeholders::error,
  589. boost::asio::placeholders::bytes_transferred, socket, sendBuffer, 64));
  590. boost::asio::async_read( *socket, boost::asio::buffer(recBuffer, 4),
  591. boost::bind(&Client::handleReadCompletion, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, socket, recBuffer, true));
  592. }
  593. }
  594. void handleWriteCompletion(const boost::system::error_code& error,
  595. size_t bytes_transferred, tcp::socket* socket, char *buffer, size_t expectedWrite) {
  596. if(error) {
  597. std::cout << error.message() << std::endl;
  598. return;
  599. }
  600. if (bytes_transferred != expectedWrite) {
  601. std::cout << "Bytes transferred was not equal to expected write in client" << std::endl;
  602. }
  603. bytesWritten += bytes_transferred;
  604. requestsSent++;
  605. size_t written;
  606. while (true) {
  607. written = 0;
  608. try {
  609. written = socket->write_some(boost::asio::buffer(buffer, 64));
  610. } catch (boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >) {
  611. }
  612. bytesWritten += written;
  613. if (written < 64) {
  614. break;
  615. }
  616. requestsSent++;
  617. }
  618. boost::asio::async_write( *socket, boost::asio::buffer(&buffer[written], 64 - written),
  619. boost::bind(&Client::handleWriteCompletion, this, boost::asio::placeholders::error,
  620. boost::asio::placeholders::bytes_transferred, socket, buffer, 64 - written));
  621. }
  622. void handleReadCompletion(const boost::system::error_code& error,
  623. size_t bytes_transferred, tcp::socket* socket, char *buffer, bool lengthOrMessage) {
  624. if (error) {
  625. std::cout << error.message() << std::endl;
  626. return;
  627. }
  628. bytesRead += bytes_transferred;
  629. size_t currentLength = 0;
  630. while (true) {
  631. if (lengthOrMessage) {
  632. currentLength = *reinterpret_cast<int32_t*>(buffer);
  633. lengthOrMessage = false;
  634. if (currentLength <= 0 || currentLength > 1500) {
  635. std::cout << "Next length at client was " << currentLength << std::endl;
  636. exit(-1);
  637. }
  638. } else {
  639. responsesReceived++;
  640. currentLength = 4;
  641. lengthOrMessage = true;
  642. }
  643. try {
  644. size_t read = socket->read_some(boost::asio::buffer(buffer, currentLength));
  645. bytesRead += read;
  646. if (read < currentLength) {
  647. boost::asio::async_read( *socket, boost::asio::buffer(&buffer[read], currentLength - read),
  648. boost::bind(&Client::handleReadCompletion, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, socket, buffer, lengthOrMessage));
  649. return;
  650. }
  651. } catch (boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >) {
  652. boost::asio::async_read( *socket, boost::asio::buffer(buffer, currentLength),
  653. boost::bind(&Client::handleReadCompletion, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, socket, buffer, lengthOrMessage));
  654. return;
  655. }
  656. }
  657. }
  658. int64_t requestsSent;
  659. int64_t responsesReceived;
  660. int64_t responsesReceivedLastTime;
  661. int64_t bytesWritten;
  662. int64_t bytesRead;
  663. int64_t bytesWrittenLastTime;
  664. int64_t bytesReadLastTime;
  665. };
  666. int main(int argc, char **argv) {
  667. boost::asio::io_service io_service;
  668. if (std::string(argv[1]) == "server") {
  669. std::vector<std::string> machines;
  670. for (int ii = 2; ii < argc; ii++) {
  671. machines.push_back(std::string(argv[ii]));
  672. }
  673. Server server( io_service, machines);
  674. io_service.run();
  675. } else if (std::string(argv[1]) == "client") {
  676. std::vector<std::string> machines;
  677. for (int ii = 2; ii < argc; ii++) {
  678. machines.push_back( std::string(argv[ii]));
  679. }
  680. Client client( io_service, machines);
  681. io_service.run();
  682. }
  683. return 0;
  684. }