edit
[c11concurrency-benchmarks.git] / silo / stats_client.cc
1 /**
2  * stats_client.cc
3  *
4  * stand-alone client to poll a stats server
5  *
6  */
7
8 #include <iostream>
9 #include <string>
10 #include <system_error>
11 #include <thread>
12
13 #include <unistd.h>
14 #include <sys/socket.h>
15 #include <sys/un.h>
16
17 #include "counter.h"
18 #include "stats_common.h"
19 #include "util.h"
20
21 using namespace std;
22 using namespace util;
23
24 int
25 main(int argc, char **argv)
26 {
27   if (argc != 3) {
28     cerr << "[usage] " << argv[0] << " sockfile counterspec" << endl;
29     return 1;
30   }
31
32   const string sockfile(argv[1]);
33   const vector<string> counter_names = split(argv[2], ':');
34
35   int fd = socket(AF_UNIX, SOCK_STREAM, 0);
36   if (fd < 0)
37     throw system_error(errno, system_category(),
38         "creating UNIX domain socket");
39   struct sockaddr_un addr;
40   memset(&addr, 0, sizeof addr);
41   addr.sun_family = AF_UNIX;
42   if (sockfile.length() + 1 >= sizeof addr.sun_path)
43     throw range_error("UNIX domain socket path too long");
44   strcpy(addr.sun_path, sockfile.c_str());
45   size_t len = strlen(addr.sun_path) + sizeof(addr.sun_family);
46   if (connect(fd, (struct sockaddr *) &addr, len) < 0)
47     throw system_error(errno, system_category(),
48         "connecting to socket");
49
50   packet pkt;
51   int r;
52   timer loop_timer;
53   for (;;) {
54     for (auto &name : counter_names) {
55       uint8_t buf[1 + name.size()];
56       buf[0] = (uint8_t) stats_command::GET_COUNTER_VALUE;
57       memcpy(&buf[1], name.data(), name.size());
58       pkt.assign((const char *) &buf[0], sizeof(buf));
59       if ((r = pkt.sendpkt(fd))) {
60         perror("send - disconnecting");
61         return 1;
62       }
63       if ((r = pkt.recvpkt(fd))) {
64         if (r == EOF)
65           return 0;
66         perror("recv - disconnecting");
67         return 1;
68       }
69       const get_counter_value_t *resp = (const get_counter_value_t *) pkt.data();
70       cout << name                << " "
71            << resp->timestamp_us_ << " "
72            << resp->d_.count_     << " "
73            << resp->d_.sum_       << " "
74            << resp->d_.max_       << endl;
75     }
76
77     const uint64_t last_loop_usec  = loop_timer.lap();
78     //const uint64_t delay_time_usec = 1000000;
79     const uint64_t delay_time_usec = 1000000/1000;
80     if (last_loop_usec < delay_time_usec) {
81       const uint64_t sleep_ns = (delay_time_usec - last_loop_usec) * 1000;
82       struct timespec t;
83       t.tv_sec  = sleep_ns / ONE_SECOND_NS;
84       t.tv_nsec = sleep_ns % ONE_SECOND_NS;
85       nanosleep(&t, nullptr);
86     }
87   }
88
89   return 0;
90 }