//------------------------------------------------------------------------------ // Author: Vitali Adamenka // Description: Source for UserGui. // Copyright (c) 2015 EPAM Systems. All Rights Reserved. //------------------------------------------------------------------------------ /* This file is part of Nfstrace. Nfstrace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2 of the License. Nfstrace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Nfstrace. If not, see . */ //------------------------------------------------------------------------------ #include #include #include #include #include #include #include "nc_windows/header_window.h" #include "nc_windows/main_window.h" #include "nc_windows/statistics_window.h" #include "user_gui.h" //----------------------------------------------------------------------------- namespace { const int SCROLL_UP = 1; const int SCROLL_DOWN = -1; const int MSEC = 1000000; } //------------------------------------------------------------------------------ void UserGUI::run() { try { // prepare for select fd_set rfds; MainWindow mainWindow; HeaderWindow headerWindow(mainWindow); StatisticsWindow statisticsWindow(mainWindow, _statisticsContainers); /* Watch stdin (fd 0) to see when it has input. */ FD_ZERO(&rfds); FD_SET(STDIN_FILENO, &rfds); /* Set wait time. */ struct timeval tv = getTimeval(); uint16_t key = 0; std::vector tmp; statisticsWindow.updateProtocol(_activeProtocol); while (_running.test_and_set()) { if (_shouldResize) { mainWindow.resize(); headerWindow.resize(mainWindow); statisticsWindow.resize(mainWindow); statisticsWindow.updateProtocol(_activeProtocol); _shouldResize = false; } if (_running.test_and_set()) { std::unique_locklck(_statisticsDeltaMutex); tmp = _statisticsContainers.at(_activeProtocol); } headerWindow.update(); statisticsWindow.update(tmp); mainWindow.update(); if( select(STDIN_FILENO + 1, &rfds, nullptr, nullptr, &tv) == -1) { break; } else { key = mainWindow.inputKeys(); if (key == KEY_LEFT || key == KEY_RIGHT) { auto it = find_if (_allProtocols.begin(), _allProtocols.end(), [&](std::string s) { return !(s.compare(_activeProtocol->getProtocolName())); }); if (it != _allProtocols.end()) { if (key == KEY_LEFT) { if (it + 1 == _allProtocols.end()) it = _allProtocols.begin(); else ++it; } else if (key == KEY_RIGHT) { if (it == _allProtocols.begin()) it = _allProtocols.end() - 1; else --it; } auto a = find_if ( _statisticsContainers.begin(), _statisticsContainers.end(),[&](std::pair > p) { return !(p.first->getProtocolName().compare(*it)); }); if (a != _statisticsContainers.end()) { _activeProtocol = a->first; statisticsWindow.setProtocol(_activeProtocol); statisticsWindow.resize(mainWindow); { std::unique_locklck(_statisticsDeltaMutex); tmp = a->second; } statisticsWindow.update(tmp); } } } else if (key == KEY_UP) { statisticsWindow.scrollContent(SCROLL_UP); statisticsWindow.update(tmp); } else if (key == KEY_DOWN) { statisticsWindow.scrollContent(SCROLL_DOWN); statisticsWindow.update(tmp); } } tv = getTimeval(); } } catch (std::runtime_error& e) { std::cerr << "Watch plugin error: " << e.what(); } } timeval UserGUI::getTimeval() const { struct timeval tv; tv.tv_sec = _refresh_delta / MSEC; tv.tv_usec = _refresh_delta % MSEC; return tv; } UserGUI::UserGUI(const char* opts, std::vector& data) : _refresh_delta {900000} , _shouldResize {false} , _running {ATOMIC_FLAG_INIT} , _activeProtocol(nullptr) { try { if (opts != nullptr && *opts != '\0' ) { _refresh_delta = std::stoul(opts); } for (auto it = data.begin(); it != data.end(); ++it) { _allProtocols.push_back((*it)->getProtocolName()); _statisticsContainers.insert(std::make_pair >((AbstractProtocol*&&)(*it), std::vector((*it)->getAmount(), 0))); } if (_activeProtocol == nullptr && ! data.empty()) { _activeProtocol = data.back(); } } catch (std::exception& e) { throw std::runtime_error {std::string{"Error in plugin options processing. OPTS: "} + opts + std::string(" Error: ") + e.what()}; } _running.test_and_set(); _guiThread = std::thread(&UserGUI::run, this); } UserGUI::~UserGUI() { _running.clear(); _guiThread.join(); } void UserGUI::update(AbstractProtocol* p, std::vector& d) { std::vector::iterator it; std::vector::iterator st; std::unique_locklck(_statisticsDeltaMutex); for (it = (_statisticsContainers.at(p)).begin(), st = d.begin(); it != (_statisticsContainers.at(p)).end() && st != d.end(); ++it, ++st) { (*it) += (*st); } } void UserGUI::enableUpdate() { _shouldResize = true; } //------------------------------------------------------------------------------