oliverthered

zipio.cpp

Nov 9th, 2020
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.32 KB | None | 0 0
  1. #include <iostream>
  2. #include <fstream>
  3. #include <vector>
  4. #include <map>
  5. #include <string>
  6. #include <string_view>
  7. #include <boost/algorithm/string/classification.hpp> // Include boost::for is_any_of
  8. #include <boost/algorithm/string/split.hpp> // Include for boost::split
  9. #include <boost/algorithm/string/trim.hpp>
  10. #include <unistd.h>
  11.  
  12. #define LOADTHREADHOLD 2.0
  13. #define IOPROCTHREASHOLD 40.0
  14. #define IOPROCTHRESET 5.00
  15. #define CPUPROCTHREASHOLD 20.0
  16. #define CPUPROCRESET 5.0
  17. #define RENICETO 10
  18. #define SLEEP 2
  19.  
  20. //#define DEBUG true
  21.  
  22. std::vector<std::string> read_array(std::string delimiter, std::string input);
  23. auto read_file(std::string_view path) -> std::string;
  24. std::string exec(std::string cmd);
  25.  
  26. int main(int argc, char** argv)
  27. {
  28.     auto ionicedprocesses = std::map<int, int>{};
  29.     auto renicedprocesses = std::vector<int>{};
  30.    
  31.     while(true)
  32.     {
  33.         auto loadavg = std::vector<std::string>{read_array(" ", read_file("/proc/loadavg"))}; // "cat /proc/loadavg"
  34.         if (std::stod(loadavg[2]) >= LOADTHREADHOLD)
  35.         {
  36.             std::cout <<  "Load of " << std::stod(loadavg[2]) << " exceeds load threshold of " << LOADTHREADHOLD << std::endl;
  37.             auto iotoplines = std::vector<std::string>{read_array("\n", exec("./iotop -P -b -q -o -n 2 -d 0.1"))};
  38.             for(auto &iotopline: iotoplines)
  39.             {
  40. #ifdef DEBUG
  41.                 std::cout << "iotop line '"<< iotopline << "'" << std::endl;
  42. #endif
  43.                 auto columns = std::vector<std::string>{};
  44.                 boost::trim_if(iotopline, boost::is_any_of(" "));
  45.                 boost::split(columns, iotopline, boost::is_any_of(" "), boost::token_compress_on);
  46.                 std::remove(columns[0].begin(), columns[0].end(), ' ');
  47.                 if (columns[0][0] - '0' >= 0 && columns[0][0] - '0' <= 9)
  48.                 {
  49.                     if (std::stod(columns[9]) >= IOPROCTHREASHOLD && columns[1][0] == 'b')
  50.                     {
  51.                         exec("ionice -c 3 -t -p " + columns[0]);
  52.                         ionicedprocesses[std::stoi(columns[0])] = columns[1][3]  - '0';
  53.                         std::cout << "process " << columns[0] << "\"" << columns[9] << "\" reniced to idle as it was hogging io" << std::endl;
  54.                     } else {
  55.                         if (std::stod(columns[9]) <= IOPROCTHRESET && ionicedprocesses.contains(std::stoi(columns[0])))
  56.                         {
  57.                             exec("ionice -c 2 -n " + std::to_string(ionicedprocesses[std::stoi(columns[0])]) + " -t -p " +columns[0]);
  58.                             std::cout <<  "process " << columns[0] << "\"" << columns[0] << "\" reniced to be/4 as it stopped hogging io" << std::endl;
  59.                             ionicedprocesses.erase(std::stoi(columns[0]));
  60.                         }
  61.                     }
  62.                 }
  63.             }
  64.             auto toplines = std::vector<std::string>{read_array("\n", exec("top -b -d 0.1 -n 1"))};
  65.             for(auto &topline: toplines)
  66.             {
  67. #ifdef DEBUG
  68.                 std::cout << "topline: '" << topline << "'" << std::endl;
  69. #endif
  70.                 auto columns = std::vector<std::string>{};
  71.                 boost::trim_if(topline, boost::is_any_of(" "));
  72.                 boost::split(columns, topline, boost::is_any_of(" "), boost::token_compress_on);
  73.                 std::remove(columns[0].begin(), columns[0].end(), ' ');
  74.                 if (columns[0][0] - '0' >= 0 && columns[0][0] - '0' <= 9)
  75.                 {
  76.                     if (std::stod(columns[8]) >= CPUPROCTHREASHOLD && columns[3] == "0")
  77.                     {
  78.                         exec("renice -n " + std::to_string(RENICETO) + " -p " + columns[0]);
  79.                         std::cout << "process " << columns[0] << " reniced to " << RENICETO << " as it was hogging cpu"  << std::endl;
  80.                         renicedprocesses.push_back(std::stoi(columns[0]));
  81.                     } else {
  82.                         if (std::stod(columns[8]) <= CPUPROCRESET && renicedprocesses.end() != std::find(renicedprocesses.begin(), renicedprocesses.end(), std::stoi(columns[0]))) // need an ittirator for contans
  83.                         {
  84.                             exec("renice -n 0 -p " + columns[0]);
  85.                             std::cout << "process " << columns[0] << " reniced to 0 as it stopped hogging cpu" << std::endl;
  86.                             //use std::remove algorythm to erase should work, but for some reason it isn't
  87.                             auto new_renicedprocesses = std::vector<int>{0};
  88.                             std::remove_copy(renicedprocesses.begin(), renicedprocesses.end(), new_renicedprocesses.begin(), std::stoi(columns[0]));                            
  89.                             renicedprocesses = new_renicedprocesses;
  90. #ifdef DEBUG
  91.                             for(auto &rnprocess: renicedprocesses)
  92.                                 std::cout << std::to_string(rnprocess) << std::endl;
  93. #endif
  94.                         }
  95.                     }
  96.                 }
  97.             }
  98.         }
  99.         sleep(SLEEP);
  100.     }
  101.     return 0;
  102. }
  103.  
  104. auto read_file(std::string_view path) -> std::string {
  105.     constexpr auto read_size = std::size_t{4096};
  106.     auto stream = std::ifstream{path.data()};
  107.     stream.exceptions(std::ios_base::badbit);
  108.  
  109.     auto out = std::string{};
  110.     auto buf = std::string(read_size, '\0');
  111.     while (stream.read(& buf[0], read_size)) {
  112.         out.append(buf, 0, stream.gcount());
  113.     }
  114.     out.append(buf, 0, stream.gcount());
  115.     return out;
  116. }
  117.  
  118. std::string exec(std::string cmd)
  119. {
  120.     std::array<char, 128> buffer;
  121.     std::string result;
  122.  
  123.     auto pipe = popen(cmd.data(), "r"); // get rid of shared_ptr
  124.  
  125.     if (!pipe) throw std::runtime_error("popen() failed!");
  126.  
  127.     while (!feof(pipe)) {
  128.         if (fgets(buffer.data(), 128, pipe) != nullptr)
  129.             result += buffer.data();
  130.     }
  131.  
  132.     auto rc = pclose(pipe);
  133.  
  134.     if (rc == EXIT_SUCCESS) { // == 0
  135.  
  136.     } else if (rc == EXIT_FAILURE) {  // EXIT_FAILURE is not used by all programs, maybe needs some adaptation.
  137.  
  138.     }
  139.     return result;
  140. }
  141.  
  142. std::vector<std::string> read_array(std::string delimiter, std::string input)
  143. {
  144.     std::vector<std::string> output;
  145.                 boost::split(output, input, boost::is_any_of(delimiter), boost::token_compress_on);
  146.     return output;
  147. }
  148.  
Advertisement
Add Comment
Please, Sign In to add comment