Home | History | Annotate | Download | only in usdt_sample_app1
      1 // std
      2 #include <algorithm>
      3 #include <cstdlib>
      4 #include <iostream>
      5 #include <mutex>
      6 #include <queue>
      7 #include <random>
      8 #include <sstream>
      9 #include <string>
     10 #include <thread>
     11 
     12 // gnu-c
     13 #include <sys/types.h>
     14 #include <unistd.h>
     15 
     16 // usdt_sample_lib1
     17 #include "usdt_sample_lib1/lib1.h"
     18 
     19 void print_usage(int argc, char** argv)
     20 {
     21     std::cout << "Usage:" << std::endl;
     22     std::cout << argv[0]
     23               << " <InputPrefix> <InputMinimum (1-50)> <InputMaximum (1-50)> <CallsPerSec (1-50)> <MinimumLatencyMs (1-50)> <MaximumLatencyMs (1-50)>"
     24               << std::endl;
     25     std::cout << "InputPrefix: Prefix of the input string to the operation. Default: dummy" << std::endl;
     26     std::cout << "InputMinimum: Minimum number to make the input string to the operation somewhat unique. Default: 1" << std::endl;
     27     std::cout << "InputMaximum: Maximum number to make the input string to the operation somewhat unique. Default: 50" << std::endl;
     28     std::cout << "CallsPerSec: Rate of calls to the operation. Default: 10" << std::endl;
     29     std::cout << "MinimumLatencyMs: Minimum latency to apply to the operation. Default: 20" << std::endl;
     30     std::cout << "MaximumLatencyMs: Maximum latency to apply to the operation. Default: 40" << std::endl;
     31 }
     32 
     33 int main(int argc, char** argv)
     34 {
     35     std::string inputPrefix("dummy");
     36     std::uint32_t inputMinimum = 1;
     37     std::uint32_t inputMaximum = 50;
     38     std::uint32_t callsPerSec = 10;
     39     std::uint32_t minLatMs = 20;
     40     std::uint32_t maxLatMs = 40;
     41 
     42     try {
     43         if (argc > 1) {
     44             inputPrefix = argv[1];
     45         }
     46 
     47         if (argc > 2) {
     48             inputMinimum = static_cast<std::uint32_t>(std::max(1, std::min(50, std::atoi(argv[2]))));
     49         }
     50 
     51         if (argc > 3) {
     52             inputMaximum = static_cast<std::uint32_t>(std::max(1, std::min(50, std::atoi(argv[3]))));
     53         }
     54 
     55         if (argc > 4) {
     56             callsPerSec = static_cast<std::uint32_t>(std::max(1, std::min(50, std::atoi(argv[4]))));
     57         }
     58 
     59         if (argc > 5) {
     60             minLatMs = static_cast<std::uint32_t>(std::max(1, std::min(50, std::atoi(argv[5]))));
     61         }
     62 
     63         if (argc > 6) {
     64             maxLatMs = static_cast<std::uint32_t>(std::max(1, std::min(50, std::atoi(argv[6]))));
     65         }
     66     }
     67     catch (const std::exception& exc) {
     68         std::cout << "Exception while reading arguments: " << exc.what() << std::endl;
     69         print_usage(argc, argv);
     70         return -1;
     71     }
     72     catch (...) {
     73         std::cout << "Unknown exception while reading arguments." << std::endl;
     74         print_usage(argc, argv);
     75         return -1;
     76     }
     77 
     78     if (inputMinimum > inputMaximum) {
     79         std::cout << "InputMinimum must be smaller than InputMaximum." << std::endl;
     80         print_usage(argc, argv);
     81         return -1;
     82     }
     83 
     84     if (minLatMs > maxLatMs) {
     85         std::cout << "MinimumLatencyMs must be smaller than MaximumLatencyMs." << std::endl;
     86         print_usage(argc, argv);
     87         return -1;
     88     }
     89 
     90     std::cout << "Applying the following parameters:" << std::endl
     91               << "Input prefix: " << inputPrefix << "." << std::endl
     92               << "Input range: [" << inputMinimum << ", " << inputMaximum << "]." << std::endl
     93               << "Calls Per Second: " << callsPerSec << "." << std::endl
     94               << "Latency range: [" << minLatMs << ", " << maxLatMs << "] ms." << std::endl;
     95 
     96     const int sleepTimeMs = 1000 / callsPerSec;
     97     OperationProvider op(minLatMs, maxLatMs);
     98 
     99     std::mutex queueMutex;
    100     std::queue<std::shared_future<OperationResponse>> responseQueue;
    101 
    102     auto dequeueFuture = std::async(std::launch::async, [&]() {
    103         while (true) {
    104             bool empty = false;
    105             {
    106                 std::lock_guard<std::mutex> lg(queueMutex);
    107                 empty = responseQueue.empty();
    108             }
    109 
    110             if (empty) {
    111                 std::this_thread::sleep_for(std::chrono::milliseconds(sleepTimeMs));
    112                 continue;
    113             }
    114 
    115             responseQueue.front().get();
    116 
    117             // std::cout << "Removing item from queue." << std::endl;
    118             std::lock_guard<std::mutex> lg(queueMutex);
    119             responseQueue.pop();
    120         }
    121     });
    122 
    123     std::random_device rd;
    124     std::uniform_int_distribution<> dis(inputMinimum, inputMaximum);
    125 
    126     std::cout << "You can now run the bcc scripts, see usdt_sample.md for examples." << std::endl;
    127     std::cout << "pid: " << ::getpid() << std::endl;
    128     std::cout << "Press ctrl-c to exit." << std::endl;
    129     while (true) {
    130         std::ostringstream inputOss;
    131         inputOss << inputPrefix << "_" << dis(rd);
    132         auto responseFuture = op.executeAsync(OperationRequest(inputOss.str()));
    133 
    134         {
    135             std::lock_guard<std::mutex> lg(queueMutex);
    136             responseQueue.push(responseFuture);
    137         }
    138 
    139         // For a sample application, this is good enough to simulate callsPerSec.
    140         std::this_thread::sleep_for(std::chrono::milliseconds(sleepTimeMs));
    141     }
    142 
    143     dequeueFuture.get();
    144     return 0;
    145 }
    146