code format
This commit is contained in:
@@ -1,29 +1,30 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Dynamic library
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
PIP - Platform Independent Primitives
|
||||
Dynamic library
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MICRO_PIP
|
||||
|
||||
#include "pilibrary.h"
|
||||
#include "piincludes_p.h"
|
||||
#ifndef WINDOWS
|
||||
# include <dlfcn.h>
|
||||
#endif
|
||||
# include "pilibrary.h"
|
||||
|
||||
# include "piincludes_p.h"
|
||||
# ifndef WINDOWS
|
||||
# include <dlfcn.h>
|
||||
# endif
|
||||
|
||||
|
||||
//! \class PILibrary pilibrary.h
|
||||
@@ -122,12 +123,12 @@
|
||||
|
||||
|
||||
PRIVATE_DEFINITION_START(PILibrary)
|
||||
#ifdef WINDOWS
|
||||
# ifdef WINDOWS
|
||||
HMODULE
|
||||
#else
|
||||
# else
|
||||
void *
|
||||
#endif
|
||||
hLib;
|
||||
# endif
|
||||
hLib;
|
||||
PRIVATE_DEFINITION_END(PILibrary)
|
||||
|
||||
|
||||
@@ -155,11 +156,11 @@ bool PILibrary::load() {
|
||||
|
||||
void PILibrary::unload() {
|
||||
if (PRIVATE->hLib == 0) return;
|
||||
#ifdef WINDOWS
|
||||
# ifdef WINDOWS
|
||||
FreeLibrary(PRIVATE->hLib);
|
||||
#else
|
||||
# else
|
||||
dlclose(PRIVATE->hLib);
|
||||
#endif
|
||||
# endif
|
||||
PRIVATE->hLib = 0;
|
||||
}
|
||||
|
||||
@@ -197,11 +198,11 @@ bool PILibrary::isLoaded() const {
|
||||
void * PILibrary::resolve(const char * symbol) {
|
||||
if (!isLoaded()) return 0;
|
||||
void * ret;
|
||||
#ifdef WINDOWS
|
||||
ret = (void*)GetProcAddress(PRIVATE->hLib, symbol);
|
||||
#else
|
||||
ret = dlsym(PRIVATE->hLib, symbol);
|
||||
#endif
|
||||
# ifdef WINDOWS
|
||||
ret = (void *)GetProcAddress(PRIVATE->hLib, symbol);
|
||||
# else
|
||||
ret = dlsym(PRIVATE->hLib, symbol);
|
||||
# endif
|
||||
getLastError();
|
||||
return ret;
|
||||
}
|
||||
@@ -210,24 +211,26 @@ void * PILibrary::resolve(const char * symbol) {
|
||||
bool PILibrary::loadInternal() {
|
||||
unload();
|
||||
if (libpath.isEmpty()) return false;
|
||||
#ifdef WINDOWS
|
||||
# ifdef WINDOWS
|
||||
PRIVATE->hLib = LoadLibraryA(libpath.data());
|
||||
#else
|
||||
PRIVATE->hLib = dlopen(libpath.data(), RTLD_LAZY);
|
||||
#endif
|
||||
# else
|
||||
PRIVATE->hLib = dlopen(libpath.data(), RTLD_LAZY);
|
||||
# endif
|
||||
getLastError();
|
||||
return PRIVATE->hLib;
|
||||
}
|
||||
|
||||
|
||||
void PILibrary::getLastError() {
|
||||
#ifdef WINDOWS
|
||||
# ifdef WINDOWS
|
||||
liberror = errorString();
|
||||
#else
|
||||
# else
|
||||
const char * e = dlerror();
|
||||
if (e) liberror = e;
|
||||
else liberror.clear();
|
||||
#endif
|
||||
if (e)
|
||||
liberror = e;
|
||||
else
|
||||
liberror.clear();
|
||||
# endif
|
||||
}
|
||||
|
||||
#endif // MICRO_PIP
|
||||
|
||||
@@ -5,30 +5,30 @@
|
||||
* \~russian Run-time библиотека
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Dynamic library
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
PIP - Platform Independent Primitives
|
||||
Dynamic library
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#
|
||||
#ifndef PILIBRARY_H
|
||||
#define PILIBRARY_H
|
||||
# define PILIBRARY_H
|
||||
|
||||
#ifndef MICRO_PIP
|
||||
# ifndef MICRO_PIP
|
||||
|
||||
#include "pistring.h"
|
||||
# include "pistring.h"
|
||||
|
||||
//! \ingroup System
|
||||
//! \~\brief
|
||||
@@ -36,7 +36,6 @@
|
||||
//! \~russian Run-time библиотека.
|
||||
class PIP_EXPORT PILibrary {
|
||||
public:
|
||||
|
||||
//! \~english Constructs %PILibrary and load if "path_" not empty
|
||||
//! \~russian Создает %PILibrary и загружает если "path_" не пустой
|
||||
PILibrary(const PIString & path_ = PIString());
|
||||
@@ -44,7 +43,7 @@ public:
|
||||
//! \~english Destroy %PILibrary, unload if library was loaded
|
||||
//! \~russian Уничтожает %PILibrary и выгружает библиотеку, если она была загружена
|
||||
~PILibrary();
|
||||
|
||||
|
||||
|
||||
//! \~english Load library with relative or absolute path "path_"
|
||||
//! \~russian Загружает библиотеку по относительному или абсолютному пути "path_"
|
||||
@@ -61,7 +60,7 @@ public:
|
||||
//! \~english Obtain exported library method with name "symbol"
|
||||
//! \~russian Получает экспортированный метод библиотеки с именем "symbol"
|
||||
void * resolve(const char * symbol);
|
||||
|
||||
|
||||
|
||||
//! \~english Returns if library successfully loaded
|
||||
//! \~russian Возвращает успешно ли загружена библиотека
|
||||
@@ -69,20 +68,19 @@ public:
|
||||
|
||||
//! \~english Returns library path
|
||||
//! \~russian Возвращает путь к библиотеке
|
||||
PIString path() const {return libpath;}
|
||||
PIString path() const { return libpath; }
|
||||
|
||||
//! \~english Returns last occured error in human-readable format
|
||||
//! \~russian Возвращает последнюю ошибку в читаемом виде
|
||||
PIString lastError() const {return liberror;}
|
||||
|
||||
PIString lastError() const { return liberror; }
|
||||
|
||||
private:
|
||||
bool loadInternal();
|
||||
void getLastError();
|
||||
|
||||
|
||||
PRIVATE_DECLARATION(PIP_EXPORT)
|
||||
PIString libpath, liberror;
|
||||
|
||||
};
|
||||
|
||||
#endif // MICRO_PIP
|
||||
#endif // PILIBRARY_H
|
||||
# endif // MICRO_PIP
|
||||
#endif // PILIBRARY_H
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Plugin helpers
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
PIP - Platform Independent Primitives
|
||||
Plugin helpers
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MICRO_PIP
|
||||
|
||||
#include "piplugin.h"
|
||||
#include "pifile.h"
|
||||
#include "pidir.h"
|
||||
#include "piincludes_p.h"
|
||||
# include "piplugin.h"
|
||||
|
||||
# include "pidir.h"
|
||||
# include "pifile.h"
|
||||
# include "piincludes_p.h"
|
||||
|
||||
//! \class PIPluginLoader piplugin.h
|
||||
//! \~\details
|
||||
@@ -232,12 +233,11 @@
|
||||
//! \endcode
|
||||
//!
|
||||
|
||||
#define STR_WF(s) #s
|
||||
#define STR(s) STR_WF(s)
|
||||
# define STR_WF(s) #s
|
||||
# define STR(s) STR_WF(s)
|
||||
|
||||
|
||||
PIPluginInfo::PIPluginInfo() {
|
||||
}
|
||||
PIPluginInfo::PIPluginInfo() {}
|
||||
|
||||
|
||||
void PIPluginInfo::setUserVersion(const PIString & v) {
|
||||
@@ -260,9 +260,6 @@ PIMap<int, void *> PIPluginInfo::staticSections() const {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
PIPluginInfoStorage::PIPluginInfoStorage() {
|
||||
enterPlugin(0);
|
||||
}
|
||||
@@ -305,16 +302,13 @@ PIPluginInfoStorage * PIPluginInfoStorage::instance() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PIPluginLoader::PIPluginLoader(const PIString & name) {
|
||||
func_loader_version = nullptr;
|
||||
func_static_merge = nullptr;
|
||||
error = Unknown;
|
||||
loaded = false;
|
||||
messages = true;
|
||||
if (!name.isEmpty())
|
||||
load(name);
|
||||
func_static_merge = nullptr;
|
||||
error = Unknown;
|
||||
loaded = false;
|
||||
messages = true;
|
||||
if (!name.isEmpty()) load(name);
|
||||
}
|
||||
|
||||
|
||||
@@ -334,34 +328,35 @@ bool PIPluginLoader::load(const PIString & name) {
|
||||
unload();
|
||||
PIPluginInfo * ai = PIPluginInfoStorage::instance()->applicationInfo();
|
||||
PIPluginInfo * pi = PIPluginInfoStorage::instance()->enterPlugin(this);
|
||||
PIString fname = findLibrary(name);
|
||||
PIString fname = findLibrary(name);
|
||||
if (fname.isEmpty()) {
|
||||
error = NoSuchFile;
|
||||
error = NoSuchFile;
|
||||
error_str = "Load plugin \"" + lib.path() + "\" error: can`t find lib for \"" + name + "\"";
|
||||
if (messages) piCout << error_str;
|
||||
return false;
|
||||
}
|
||||
if (!lib.load(fname)) {
|
||||
unload();
|
||||
error = LibraryLoadError;
|
||||
error = LibraryLoadError;
|
||||
error_str = "Load plugin \"" + lib.path() + "\" error: can`t load lib: " + lib.lastError();
|
||||
if (messages) piCout << error_str;
|
||||
return false;
|
||||
}
|
||||
//piCout << "loading" << lib.path() << "...";
|
||||
// piCout << "loading" << lib.path() << "...";
|
||||
func_loader_version = (FunctionLoaderVersion)lib.resolve(STR(__PIP_PLUGIN_LOADER_VERSION_FUNC__));
|
||||
if (!func_loader_version) {
|
||||
unload();
|
||||
error = MissingSymbols;
|
||||
error = MissingSymbols;
|
||||
error_str = "Load plugin \"" + lib.path() + "\" error: can`t find " + STR(__PIP_PLUGIN_LOADER_VERSION_FUNC__);
|
||||
if (messages) piCout << error_str;
|
||||
return false;
|
||||
}
|
||||
if (__PIP_PLUGIN_LOADER_VERSION__ != func_loader_version()) {
|
||||
unload();
|
||||
error = InvalidLoaderVersion;
|
||||
error_str = "Load plugin \"" + lib.path() + "\" error: invalid loader version: application = " + PIString::fromNumber(func_loader_version())
|
||||
+ ", plugin = " + PIString::fromNumber(__PIP_PLUGIN_LOADER_VERSION__);
|
||||
error = InvalidLoaderVersion;
|
||||
error_str = "Load plugin \"" + lib.path() +
|
||||
"\" error: invalid loader version: application = " + PIString::fromNumber(func_loader_version()) +
|
||||
", plugin = " + PIString::fromNumber(__PIP_PLUGIN_LOADER_VERSION__);
|
||||
if (messages) piCout << error_str;
|
||||
return false;
|
||||
}
|
||||
@@ -370,7 +365,8 @@ bool PIPluginLoader::load(const PIString & name) {
|
||||
if (pversion != lversion) {
|
||||
unload();
|
||||
error = InvalidUserVersion;
|
||||
error_str = "Load plugin \"" + lib.path() + "\" error: invalid user version: application = " + lversion + ", plugin = " + pversion;
|
||||
error_str =
|
||||
"Load plugin \"" + lib.path() + "\" error: invalid user version: application = " + lversion + ", plugin = " + pversion;
|
||||
if (messages) piCout << error_str;
|
||||
return false;
|
||||
}
|
||||
@@ -378,18 +374,16 @@ bool PIPluginLoader::load(const PIString & name) {
|
||||
func_static_merge = (FunctionStaticMerge)lib.resolve(STR(__PIP_PLUGIN_STATIC_MERGE_FUNC__));
|
||||
if (func_static_merge) {
|
||||
auto pss = pi->staticSections(), lss = ai->staticSections();
|
||||
//piCout << lss.keys() << pss.keys();
|
||||
// piCout << lss.keys() << pss.keys();
|
||||
auto it = lss.makeIterator();
|
||||
while (it.next()) {
|
||||
if (!pss.contains(it.key()))
|
||||
continue;
|
||||
void * from = pss.value(it.key()), * to = it.value();
|
||||
if (from != to)
|
||||
func_static_merge(it.key(), from, to);
|
||||
if (!pss.contains(it.key())) continue;
|
||||
void *from = pss.value(it.key()), *to = it.value();
|
||||
if (from != to) func_static_merge(it.key(), from, to);
|
||||
}
|
||||
}
|
||||
loaded = true;
|
||||
error = NoError;
|
||||
error = NoError;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -453,11 +447,9 @@ void PIPluginLoader::mergeStatic() {
|
||||
auto pss = pi->staticSections(), lss = ai->staticSections();
|
||||
auto it = lss.makeIterator();
|
||||
while (it.next()) {
|
||||
if (!pss.contains(it.key()))
|
||||
continue;
|
||||
void * from = it.value(), * to = pss.value(it.key());
|
||||
if (from != to)
|
||||
func_static_merge(it.key(), from, to);
|
||||
if (!pss.contains(it.key())) continue;
|
||||
void *from = it.value(), *to = pss.value(it.key());
|
||||
if (from != to) func_static_merge(it.key(), from, to);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,10 +457,9 @@ void PIPluginLoader::mergeStatic() {
|
||||
PIStringList PIPluginLoader::pluginsDirectories(const PIString & name) {
|
||||
static PIStringList dl({".", "./plugins", "../PlugIns"});
|
||||
PIString ret;
|
||||
piForeachC (PIString d, dl) {
|
||||
piForeachC(PIString d, dl) {
|
||||
PIString dp = d + "/" + name;
|
||||
if (PIDir::isExists(dp))
|
||||
ret += dp;
|
||||
if (PIDir::isExists(dp)) ret += dp;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -479,11 +470,10 @@ PIString PIPluginLoader::findLibrary(const PIString & path) {
|
||||
static const PIStringList suffixes({"", libExtension()});
|
||||
PIFile::FileInfo fi(path);
|
||||
PIString dir = fi.dir(), name = fi.name();
|
||||
piForeachC (PIString & p, prefixes) {
|
||||
piForeachC (PIString & s, suffixes) {
|
||||
piForeachC(PIString & p, prefixes) {
|
||||
piForeachC(PIString & s, suffixes) {
|
||||
PIString fn = dir + p + name + s;
|
||||
if (PIFile::isExists(fn))
|
||||
return fn;
|
||||
if (PIFile::isExists(fn)) return fn;
|
||||
}
|
||||
}
|
||||
return PIString();
|
||||
@@ -492,14 +482,14 @@ PIString PIPluginLoader::findLibrary(const PIString & path) {
|
||||
|
||||
PIString PIPluginLoader::libExtension() {
|
||||
return
|
||||
#ifdef WINDOWS
|
||||
".dll"
|
||||
#elif defined(MAC_OS)
|
||||
".dylib"
|
||||
#else
|
||||
".so"
|
||||
#endif
|
||||
;
|
||||
# ifdef WINDOWS
|
||||
".dll"
|
||||
# elif defined(MAC_OS)
|
||||
".dylib"
|
||||
# else
|
||||
".so"
|
||||
# endif
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,22 +5,22 @@
|
||||
* \~russian Управление плагинами
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Plugin helpers
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
PIP - Platform Independent Primitives
|
||||
Plugin helpers
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PIPLUGIN_H
|
||||
@@ -28,26 +28,26 @@
|
||||
|
||||
#ifndef MICRO_PIP
|
||||
|
||||
#include "pilibrary.h"
|
||||
#include "pistringlist.h"
|
||||
# include "pilibrary.h"
|
||||
# include "pistringlist.h"
|
||||
|
||||
#ifdef DOXYGEN
|
||||
# ifdef DOXYGEN
|
||||
|
||||
|
||||
//! \~english Declare plugin, should be used before other PIP_PLUGIN_* macros
|
||||
//! \~russian Объявляет плагин, должен быть использован перед любыми другими PIP_PLUGIN_* макросами
|
||||
//! \~\relatesalso PIPluginLoader
|
||||
#define PIP_PLUGIN
|
||||
# define PIP_PLUGIN
|
||||
|
||||
//! \~english Set user version to check it while loading, "version" is quoted string
|
||||
//! \~russian Устанавливает пользовательскую версию для проверки во время загрузки, "version" - строка в кавычках
|
||||
//! \~\relatesalso PIPluginLoader
|
||||
#define PIP_PLUGIN_SET_USER_VERSION(version)
|
||||
# define PIP_PLUGIN_SET_USER_VERSION(version)
|
||||
|
||||
//! \~english Add pointer to future merge with plugin. Type is integer
|
||||
//! \~russian Добавляет указатель для будущего слияния. Тип - целое число
|
||||
//! \~\relatesalso PIPluginLoader
|
||||
#define PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr)
|
||||
# define PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr)
|
||||
|
||||
//! \~english Declare function to merge static sections
|
||||
//! \~russian Объявляет метод для слияния статических секций
|
||||
@@ -67,53 +67,54 @@
|
||||
//! "to" - областью плагина. Таким образом, этот макрос позволяет провести
|
||||
//! слияние статических данных приложения и плагина.
|
||||
//! \~\relatesalso PIPluginLoader
|
||||
#define PIP_PLUGIN_STATIC_SECTION_MERGE
|
||||
# define PIP_PLUGIN_STATIC_SECTION_MERGE
|
||||
|
||||
//! \~english Mark method to export
|
||||
//! \~russian Пометить метод на экспорт
|
||||
//! \~\relatesalso PIPluginLoader
|
||||
#define PIP_PLUGIN_EXPORT
|
||||
# define PIP_PLUGIN_EXPORT
|
||||
|
||||
|
||||
#else
|
||||
# else
|
||||
|
||||
|
||||
#ifdef WINDOWS
|
||||
# define PIP_PLUGIN_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
# define PIP_PLUGIN_EXPORT
|
||||
#endif
|
||||
# ifdef WINDOWS
|
||||
# define PIP_PLUGIN_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define PIP_PLUGIN_EXPORT
|
||||
# endif
|
||||
|
||||
#define __PIP_PLUGIN_LOADER_VERSION_FUNC__ pip_loader_version
|
||||
#define __PIP_PLUGIN_STATIC_MERGE_FUNC__ pip_merge_static
|
||||
#define __PIP_PLUGIN_LOADER_VERSION__ 2
|
||||
# define __PIP_PLUGIN_LOADER_VERSION_FUNC__ pip_loader_version
|
||||
# define __PIP_PLUGIN_STATIC_MERGE_FUNC__ pip_merge_static
|
||||
# define __PIP_PLUGIN_LOADER_VERSION__ 2
|
||||
|
||||
#define PIP_PLUGIN_SET_USER_VERSION(v) \
|
||||
STATIC_INITIALIZER_BEGIN \
|
||||
PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \
|
||||
if (pi) pi->setUserVersion(v); \
|
||||
STATIC_INITIALIZER_END
|
||||
# define PIP_PLUGIN_SET_USER_VERSION(v) \
|
||||
STATIC_INITIALIZER_BEGIN \
|
||||
PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \
|
||||
if (pi) pi->setUserVersion(v); \
|
||||
STATIC_INITIALIZER_END
|
||||
|
||||
#define PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr) \
|
||||
STATIC_INITIALIZER_BEGIN \
|
||||
PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \
|
||||
if (pi) pi->setStaticSection(type, ptr); \
|
||||
STATIC_INITIALIZER_END
|
||||
# define PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr) \
|
||||
STATIC_INITIALIZER_BEGIN \
|
||||
PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \
|
||||
if (pi) pi->setStaticSection(type, ptr); \
|
||||
STATIC_INITIALIZER_END
|
||||
|
||||
#define PIP_PLUGIN \
|
||||
extern "C" { \
|
||||
PIP_PLUGIN_EXPORT int __PIP_PLUGIN_LOADER_VERSION_FUNC__() {return __PIP_PLUGIN_LOADER_VERSION__;} \
|
||||
}
|
||||
# define PIP_PLUGIN \
|
||||
extern "C" { \
|
||||
PIP_PLUGIN_EXPORT int __PIP_PLUGIN_LOADER_VERSION_FUNC__() { \
|
||||
return __PIP_PLUGIN_LOADER_VERSION__; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PIP_PLUGIN_STATIC_SECTION_MERGE \
|
||||
extern "C" { \
|
||||
# define PIP_PLUGIN_STATIC_SECTION_MERGE \
|
||||
extern "C" { \
|
||||
PIP_PLUGIN_EXPORT void __PIP_PLUGIN_STATIC_MERGE_FUNC__(int type, void * from, void * to); \
|
||||
} \
|
||||
void __PIP_PLUGIN_STATIC_MERGE_FUNC__(int type, void * from, void * to)
|
||||
} \
|
||||
void __PIP_PLUGIN_STATIC_MERGE_FUNC__(int type, void * from, void * to)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
# endif
|
||||
|
||||
|
||||
class PIP_EXPORT PIPluginInfo {
|
||||
@@ -123,16 +124,14 @@ public:
|
||||
void setUserVersion(const PIString & v);
|
||||
void setStaticSection(int type, void * ptr);
|
||||
PIString userVersion() const;
|
||||
PIMap<int, void*> staticSections() const;
|
||||
PIMap<int, void *> staticSections() const;
|
||||
|
||||
private:
|
||||
PIString user_version;
|
||||
PIMap<int, void*> static_sections;
|
||||
|
||||
PIMap<int, void *> static_sections;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class PIP_EXPORT PIPluginInfoStorage {
|
||||
public:
|
||||
PIPluginInfoStorage();
|
||||
@@ -149,32 +148,29 @@ private:
|
||||
NO_COPY_CLASS(PIPluginInfoStorage);
|
||||
|
||||
void * current;
|
||||
PIMap<void*, PIPluginInfo * > info;
|
||||
|
||||
PIMap<void *, PIPluginInfo *> info;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//! \ingroup System
|
||||
//! \~\brief
|
||||
//! \~english Plugin loader.
|
||||
//! \~russian Загрузчик плагина.
|
||||
class PIP_EXPORT PIPluginLoader {
|
||||
public:
|
||||
typedef int(*FunctionLoaderVersion)();
|
||||
typedef void(*FunctionStaticMerge)(int, void *, void *);
|
||||
typedef int (*FunctionLoaderVersion)();
|
||||
typedef void (*FunctionStaticMerge)(int, void *, void *);
|
||||
|
||||
//! \~english Possible load plugin error
|
||||
//! \~russian Возможные ошибки загрузки плагина
|
||||
enum Error {
|
||||
Unknown /** \~english No \a load() call yet \~russian Не было вызова \a load() */ ,
|
||||
NoError /** \~english No error \~russian Нет ошибки */ ,
|
||||
NoSuchFile /** \~english Can`t find library file \~russian Не найден файл библиотеки */ ,
|
||||
LibraryLoadError /** \~english System can`t load library \~russian Система не смогла загрузить библиотеку */ ,
|
||||
MissingSymbols /** \~english Can`t find necessary symbols \~russian Нет необходимых методов */ ,
|
||||
InvalidLoaderVersion /** \~english Internal version mismatch \~russian Неверная внутренняя версия */ ,
|
||||
InvalidUserVersion /** \~english User version mismatch \~russian Неверная пользовательская версия */ ,
|
||||
Unknown /** \~english No \a load() call yet \~russian Не было вызова \a load() */,
|
||||
NoError /** \~english No error \~russian Нет ошибки */,
|
||||
NoSuchFile /** \~english Can`t find library file \~russian Не найден файл библиотеки */,
|
||||
LibraryLoadError /** \~english System can`t load library \~russian Система не смогла загрузить библиотеку */,
|
||||
MissingSymbols /** \~english Can`t find necessary symbols \~russian Нет необходимых методов */,
|
||||
InvalidLoaderVersion /** \~english Internal version mismatch \~russian Неверная внутренняя версия */,
|
||||
InvalidUserVersion /** \~english User version mismatch \~russian Неверная пользовательская версия */,
|
||||
};
|
||||
|
||||
//! \~english Contruct loader with base filename "name" and call \a load() if "name" not empty
|
||||
@@ -241,7 +237,6 @@ private:
|
||||
PIString error_str;
|
||||
Error error;
|
||||
bool loaded, messages;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,33 +1,34 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Process
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
PIP - Platform Independent Primitives
|
||||
Process
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MICRO_PIP
|
||||
|
||||
#include "piincludes_p.h"
|
||||
#include "piprocess.h"
|
||||
#ifndef WINDOWS
|
||||
# include <sys/wait.h>
|
||||
# include <csignal>
|
||||
#endif
|
||||
#ifdef MAC_OS
|
||||
# include <crt_externs.h>
|
||||
#endif
|
||||
# include "piprocess.h"
|
||||
|
||||
# include "piincludes_p.h"
|
||||
# ifndef WINDOWS
|
||||
# include <csignal>
|
||||
# include <sys/wait.h>
|
||||
# endif
|
||||
# ifdef MAC_OS
|
||||
# include <crt_externs.h>
|
||||
# endif
|
||||
|
||||
|
||||
//! \class PIProcess piprocess.h
|
||||
@@ -61,33 +62,33 @@
|
||||
|
||||
|
||||
PRIVATE_DEFINITION_START(PIProcess)
|
||||
#ifdef WINDOWS
|
||||
# ifdef WINDOWS
|
||||
STARTUPINFOA si;
|
||||
PROCESS_INFORMATION pi;
|
||||
#else
|
||||
# else
|
||||
pid_t pid;
|
||||
#endif
|
||||
FILE * tf_in, * tf_out, * tf_err;
|
||||
# endif
|
||||
FILE *tf_in, *tf_out, *tf_err;
|
||||
PRIVATE_DEFINITION_END(PIProcess)
|
||||
|
||||
|
||||
PIProcess::PIProcess(): PIThread() {
|
||||
exit_code = -1;
|
||||
#ifdef WINDOWS
|
||||
# ifdef WINDOWS
|
||||
PRIVATE->pi.dwProcessId = 0;
|
||||
#else
|
||||
# else
|
||||
PRIVATE->pid = 0;
|
||||
#endif
|
||||
# endif
|
||||
is_exec = false;
|
||||
g_in = g_out = g_err = false;
|
||||
t_in = t_out = t_err = false;
|
||||
PRIVATE->tf_in = PRIVATE->tf_out = PRIVATE->tf_err = 0;
|
||||
env = PIProcess::currentEnvironment();
|
||||
env = PIProcess::currentEnvironment();
|
||||
}
|
||||
|
||||
|
||||
PIProcess::~PIProcess() {
|
||||
if (t_in) f_in.remove();
|
||||
if (t_in) f_in.remove();
|
||||
if (t_out) f_out.remove();
|
||||
if (t_err) f_err.remove();
|
||||
}
|
||||
@@ -96,48 +97,48 @@ PIProcess::~PIProcess() {
|
||||
void PIProcess::exec_() {
|
||||
is_exec = false;
|
||||
startOnce();
|
||||
//cout << "exec wait" << endl;
|
||||
// cout << "exec wait" << endl;
|
||||
while (!is_exec)
|
||||
piMinSleep();
|
||||
//cout << "exec end" << endl;
|
||||
// cout << "exec end" << endl;
|
||||
}
|
||||
|
||||
|
||||
void PIProcess::startProc(bool detached) {
|
||||
//cout << "run" << endl;
|
||||
// cout << "run" << endl;
|
||||
PIString str;
|
||||
/// arguments convertion
|
||||
int as = 0;
|
||||
const char * argscc[args.size()+1];
|
||||
const char * argscc[args.size() + 1];
|
||||
int argsl[args.size()];
|
||||
for (int i = 0; i < args.size_s(); ++i) {
|
||||
argscc[i] = args[i].data();
|
||||
argsl[i] = strlen(argscc[i]);
|
||||
argsl[i] = strlen(argscc[i]);
|
||||
as += argsl[i] + 3;
|
||||
}
|
||||
argscc[args.size()] = 0;
|
||||
#ifdef WINDOWS
|
||||
# ifdef WINDOWS
|
||||
char * a = new char[as];
|
||||
memset(a, ' ', as - 1);
|
||||
as = 0;
|
||||
for (int i = 0; i < args.size_s(); ++i) {
|
||||
str = args[i];
|
||||
str = args[i];
|
||||
a[as] = '"';
|
||||
memcpy(&(a[as + 1]), argscc[i], argsl[i]);
|
||||
a[as + argsl[i] + 1] = '"';
|
||||
as += argsl[i] + 3;
|
||||
}
|
||||
a[as - 1] = 0;
|
||||
//piCout << a;
|
||||
#endif
|
||||
#ifndef WINDOWS
|
||||
// piCout << a;
|
||||
# endif
|
||||
# ifndef WINDOWS
|
||||
/// environment convertion
|
||||
const char * envcc[env.size()+1];
|
||||
const char * envcc[env.size() + 1];
|
||||
envcc[env.size_s()] = 0;
|
||||
for (int i = 0; i < env.size_s(); ++i) {
|
||||
envcc[i] = env[i].data();
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
/// files for stdin/out/err
|
||||
t_in = t_out = t_err = false;
|
||||
if (f_in.path().isEmpty()) {
|
||||
@@ -153,161 +154,158 @@ void PIProcess::startProc(bool detached) {
|
||||
t_err = true;
|
||||
}
|
||||
|
||||
str = args.front();
|
||||
str = args.front();
|
||||
is_exec = true;
|
||||
if (!detached) execStarted(str);
|
||||
#ifndef WINDOWS
|
||||
# ifndef WINDOWS
|
||||
int pid_ = fork();
|
||||
if (!detached) PRIVATE->pid = pid_;
|
||||
if (pid_ == 0) {
|
||||
#endif
|
||||
# endif
|
||||
PRIVATE->tf_in = PRIVATE->tf_out = PRIVATE->tf_err = 0;
|
||||
//cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl;
|
||||
//cout << f_out.path() << endl;
|
||||
if (g_in) PRIVATE->tf_in = freopen(f_in.path().data(), "r", stdin);
|
||||
// cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl;
|
||||
// cout << f_out.path() << endl;
|
||||
if (g_in) PRIVATE->tf_in = freopen(f_in.path().data(), "r", stdin);
|
||||
if (g_out) PRIVATE->tf_out = freopen(f_out.path().data(), "w", stdout);
|
||||
if (g_err) PRIVATE->tf_err = freopen(f_err.path().data(), "w", stderr);
|
||||
#ifndef WINDOWS
|
||||
# ifndef WINDOWS
|
||||
if (!wd.isEmpty())
|
||||
if (!chdir(wd.data()))
|
||||
piCoutObj << "Error while set working directory";
|
||||
#endif
|
||||
#ifdef WINDOWS
|
||||
GetStartupInfoA(&(PRIVATE->si));
|
||||
memset(&(PRIVATE->pi), 0, sizeof(PRIVATE->pi));
|
||||
if(CreateProcessA(0, // No module name (use command line)
|
||||
a, // Command line
|
||||
0, // Process handle not inheritable
|
||||
0, // Thread handle not inheritable
|
||||
false, // Set handle inheritance to FALSE
|
||||
detached ? DETACHED_PROCESS/*CREATE_NEW_CONSOLE*/ : 0, // Creation flags
|
||||
0,//envcc, // Use environment
|
||||
wd.isEmpty() ? 0 : wd.data(), // Use working directory
|
||||
&(PRIVATE->si), // Pointer to STARTUPINFO structure
|
||||
&(PRIVATE->pi))) // Pointer to PROCESS_INFORMATION structure
|
||||
{
|
||||
if (!detached) WaitForSingleObject(PRIVATE->pi.hProcess, INFINITE);
|
||||
CloseHandle(PRIVATE->pi.hThread);
|
||||
CloseHandle(PRIVATE->pi.hProcess);
|
||||
} else
|
||||
piCoutObj << "\"CreateProcess\" error, " << errorString();
|
||||
#else
|
||||
if (!chdir(wd.data())) piCoutObj << "Error while set working directory";
|
||||
# endif
|
||||
# ifdef WINDOWS
|
||||
GetStartupInfoA(&(PRIVATE->si));
|
||||
memset(&(PRIVATE->pi), 0, sizeof(PRIVATE->pi));
|
||||
if (CreateProcessA(0, // No module name (use command line)
|
||||
a, // Command line
|
||||
0, // Process handle not inheritable
|
||||
0, // Thread handle not inheritable
|
||||
false, // Set handle inheritance to FALSE
|
||||
detached ? DETACHED_PROCESS /*CREATE_NEW_CONSOLE*/ : 0, // Creation flags
|
||||
0, // envcc, // Use environment
|
||||
wd.isEmpty() ? 0 : wd.data(), // Use working directory
|
||||
&(PRIVATE->si), // Pointer to STARTUPINFO structure
|
||||
&(PRIVATE->pi))) // Pointer to PROCESS_INFORMATION structure
|
||||
{
|
||||
if (!detached) WaitForSingleObject(PRIVATE->pi.hProcess, INFINITE);
|
||||
CloseHandle(PRIVATE->pi.hThread);
|
||||
CloseHandle(PRIVATE->pi.hProcess);
|
||||
} else
|
||||
piCoutObj << "\"CreateProcess\" error, " << errorString();
|
||||
# else
|
||||
|
||||
//cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl;
|
||||
if (execve(str.data(), (char * const *)argscc, (char * const *)envcc) < 0)
|
||||
piCoutObj << "\"execve" << str << args << "\" error :" << errorString();
|
||||
} else {
|
||||
piMinSleep();
|
||||
//cout << "wait" << endl;
|
||||
if (!detached) {
|
||||
wait(&exit_code);
|
||||
pid_ = 0;
|
||||
if (!detached) PRIVATE->pid = pid_;
|
||||
//cout << "wait done" << endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!detached) execFinished(str, exit_code);
|
||||
is_exec = false;
|
||||
#ifdef WINDOWS
|
||||
delete[] a;
|
||||
#endif
|
||||
// cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl;
|
||||
if (execve(str.data(), (char * const *)argscc, (char * const *)envcc) < 0)
|
||||
piCoutObj << "\"execve" << str << args << "\" error :" << errorString();
|
||||
}
|
||||
else {
|
||||
piMinSleep();
|
||||
// cout << "wait" << endl;
|
||||
if (!detached) {
|
||||
wait(&exit_code);
|
||||
pid_ = 0;
|
||||
if (!detached) PRIVATE->pid = pid_;
|
||||
// cout << "wait done" << endl;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
if (!detached) execFinished(str, exit_code);
|
||||
is_exec = false;
|
||||
# ifdef WINDOWS
|
||||
delete[] a;
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
void PIProcess::terminate() {
|
||||
#ifdef WINDOWS
|
||||
if (is_exec)
|
||||
if (!TerminateProcess(PRIVATE->pi.hProcess, 0))
|
||||
return;
|
||||
PRIVATE->pi.dwProcessId = 0;
|
||||
#else
|
||||
if (is_exec)
|
||||
kill(PRIVATE->pid, SIGKILL);
|
||||
void PIProcess::terminate() {
|
||||
# ifdef WINDOWS
|
||||
if (is_exec)
|
||||
if (!TerminateProcess(PRIVATE->pi.hProcess, 0)) return;
|
||||
PRIVATE->pi.dwProcessId = 0;
|
||||
# else
|
||||
if (is_exec) kill(PRIVATE->pid, SIGKILL);
|
||||
PRIVATE->pid = 0;
|
||||
#endif
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
void PIProcess::execIndependent(const PIString & program, const PIStringList & args_) {
|
||||
PIProcess p;
|
||||
p.args << program << args_;
|
||||
p.startProc(true);
|
||||
}
|
||||
void PIProcess::execIndependent(const PIString & program, const PIStringList & args_) {
|
||||
PIProcess p;
|
||||
p.args << program << args_;
|
||||
p.startProc(true);
|
||||
}
|
||||
|
||||
|
||||
int PIProcess::pID() const {
|
||||
#ifdef WINDOWS
|
||||
return PRIVATE->pi.dwProcessId;
|
||||
#else
|
||||
int PIProcess::pID() const {
|
||||
# ifdef WINDOWS
|
||||
return PRIVATE->pi.dwProcessId;
|
||||
# else
|
||||
return PRIVATE->pid;
|
||||
#endif
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
int PIProcess::currentPID() {
|
||||
#ifdef WINDOWS
|
||||
return GetCurrentProcessId();
|
||||
#else
|
||||
int PIProcess::currentPID() {
|
||||
# ifdef WINDOWS
|
||||
return GetCurrentProcessId();
|
||||
# else
|
||||
return getpid();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
PIStringList PIProcess::currentEnvironment() {
|
||||
PIStringList l;
|
||||
int i = 0;
|
||||
while (environ[i] != 0) {
|
||||
l << environ[i];
|
||||
++i;
|
||||
# endif
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
void PIProcess::run() {
|
||||
startProc(false);
|
||||
}
|
||||
PIStringList PIProcess::currentEnvironment() {
|
||||
PIStringList l;
|
||||
int i = 0;
|
||||
while (environ[i] != 0) {
|
||||
l << environ[i];
|
||||
++i;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
void PIProcess::removeEnvironmentVariable(const PIString & variable) {
|
||||
PIString s;
|
||||
for (int i = 0; i < env.size_s(); ++i) {
|
||||
s = env[i];
|
||||
if (s.left(s.find("=")).trimmed() == variable) {
|
||||
env.remove(i);
|
||||
--i;
|
||||
void PIProcess::run() {
|
||||
startProc(false);
|
||||
}
|
||||
|
||||
|
||||
void PIProcess::removeEnvironmentVariable(const PIString & variable) {
|
||||
PIString s;
|
||||
for (int i = 0; i < env.size_s(); ++i) {
|
||||
s = env[i];
|
||||
if (s.left(s.find("=")).trimmed() == variable) {
|
||||
env.remove(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PIProcess::setEnvironmentVariable(const PIString & variable, const PIString & value) {
|
||||
PIString s, v;
|
||||
for (int i = 0; i < env.size_s(); ++i) {
|
||||
s = env[i];
|
||||
v = s.left(s.find("=")).trimmed();
|
||||
if (v == variable) {
|
||||
env[i] = v + "=" + value;
|
||||
return;
|
||||
void PIProcess::setEnvironmentVariable(const PIString & variable, const PIString & value) {
|
||||
PIString s, v;
|
||||
for (int i = 0; i < env.size_s(); ++i) {
|
||||
s = env[i];
|
||||
v = s.left(s.find("=")).trimmed();
|
||||
if (v == variable) {
|
||||
env[i] = v + "=" + value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
env << variable + "=" + value;
|
||||
}
|
||||
env << variable + "=" + value;
|
||||
}
|
||||
|
||||
|
||||
PIString PIProcess::getEnvironmentVariable(const PIString & variable) {
|
||||
PIStringList env_ = currentEnvironment();
|
||||
PIString s, v;
|
||||
for (int i = 0; i < env_.size_s(); ++i) {
|
||||
s = env_[i];
|
||||
v = s.left(s.find("=")).trimmed();
|
||||
if (v == variable) {
|
||||
return s.right(s.size() - 1 - s.find("=")).trimmed();
|
||||
PIString PIProcess::getEnvironmentVariable(const PIString & variable) {
|
||||
PIStringList env_ = currentEnvironment();
|
||||
PIString s, v;
|
||||
for (int i = 0; i < env_.size_s(); ++i) {
|
||||
s = env_[i];
|
||||
v = s.left(s.find("=")).trimmed();
|
||||
if (v == variable) {
|
||||
return s.right(s.size() - 1 - s.find("=")).trimmed();
|
||||
}
|
||||
}
|
||||
return PIString();
|
||||
}
|
||||
return PIString();
|
||||
}
|
||||
|
||||
#endif // MICRO_PIP
|
||||
|
||||
|
||||
@@ -5,22 +5,22 @@
|
||||
* \~russian Внешний процесс
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Process
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
PIP - Platform Independent Primitives
|
||||
Process
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PIPROCESS_H
|
||||
@@ -28,19 +28,18 @@
|
||||
|
||||
#ifndef MICRO_PIP
|
||||
|
||||
#include "pithread.h"
|
||||
#include "pifile.h"
|
||||
# include "pifile.h"
|
||||
# include "pithread.h"
|
||||
|
||||
|
||||
//! \ingroup System
|
||||
//! \~\brief
|
||||
//! \~english External process.
|
||||
//! \~russian Внешний процесс.
|
||||
class PIP_EXPORT PIProcess: public PIThread
|
||||
{
|
||||
class PIP_EXPORT PIProcess: public PIThread {
|
||||
PIOBJECT_SUBCLASS(PIProcess, PIThread);
|
||||
public:
|
||||
|
||||
public:
|
||||
//! \~english Construct empty %PIProcess
|
||||
//! \~russian Создает пустой %PIProcess
|
||||
PIProcess();
|
||||
@@ -50,70 +49,76 @@ public:
|
||||
|
||||
//! \~english Returns last attached execution exit code
|
||||
//! \~russian Возвращает код завершения последнего выполнения
|
||||
int exitCode() const {return exit_code;}
|
||||
int exitCode() const { return exit_code; }
|
||||
|
||||
//! \~english Returns current attached execution process ID
|
||||
//! \~russian Возвращает ID процесса текущего выполнения
|
||||
int pID() const;
|
||||
|
||||
void setGrabInput(bool yes) {g_in = yes;}
|
||||
void setGrabInput(bool yes) { g_in = yes; }
|
||||
|
||||
//! \~english Set attached execution grab output stream enabled
|
||||
//! \~russian
|
||||
void setGrabOutput(bool yes) {g_out = yes;}
|
||||
void setGrabOutput(bool yes) { g_out = yes; }
|
||||
|
||||
//! \~english Set attached execution grab error stream enabled
|
||||
//! \~russian
|
||||
void setGrabError(bool yes) {g_err = yes;}
|
||||
void setGrabError(bool yes) { g_err = yes; }
|
||||
|
||||
void setInputFile(const PIString & path) {f_in.setPath(path);}
|
||||
void setInputFile(const PIString & path) { f_in.setPath(path); }
|
||||
|
||||
//! \~english Set attached execution grab output stream file
|
||||
//! \~russian
|
||||
void setOutputFile(const PIString & path) {f_out.setPath(path);}
|
||||
void setOutputFile(const PIString & path) { f_out.setPath(path); }
|
||||
|
||||
//! \~english Set attached execution grab error stream file
|
||||
//! \~russian
|
||||
void setErrorFile(const PIString & path) {f_err.setPath(path);}
|
||||
void setErrorFile(const PIString & path) { f_err.setPath(path); }
|
||||
|
||||
void unsetInputFile() {f_in.setPath("");}
|
||||
void unsetInputFile() { f_in.setPath(""); }
|
||||
|
||||
//! \~english Reset attached execution grab output stream file
|
||||
//! \~russian
|
||||
void unsetOutputFile() {f_out.setPath("");}
|
||||
void unsetOutputFile() { f_out.setPath(""); }
|
||||
|
||||
//! \~english Reset attached execution grab error stream file
|
||||
//! \~russian
|
||||
void unsetErrorFile() {f_err.setPath("");}
|
||||
void unsetErrorFile() { f_err.setPath(""); }
|
||||
|
||||
//! \~english Returns current attached execution working directory or empty string if it wasn`t set
|
||||
//! \~russian
|
||||
PIString workingDirectory() const {return wd;}
|
||||
PIString workingDirectory() const { return wd; }
|
||||
|
||||
//! \~english Set attached execution working directory
|
||||
//! \~russian
|
||||
void setWorkingDirectory(const PIString & path) {wd = path;}
|
||||
void setWorkingDirectory(const PIString & path) { wd = path; }
|
||||
|
||||
//! \~english Rseet attached execution working directory, application working dir will be used
|
||||
//! \~russian
|
||||
void resetWorkingDirectory() {wd.clear();}
|
||||
void resetWorkingDirectory() { wd.clear(); }
|
||||
|
||||
//! \~english Returns all attached execution output stream
|
||||
//! \~russian
|
||||
PIByteArray readOutput() {f_out.open(PIIODevice::ReadOnly); return f_out.readAll();}
|
||||
PIByteArray readOutput() {
|
||||
f_out.open(PIIODevice::ReadOnly);
|
||||
return f_out.readAll();
|
||||
}
|
||||
|
||||
//! \~english Returns all attached execution error stream
|
||||
//! \~russian
|
||||
PIByteArray readError() {f_err.open(PIIODevice::ReadOnly); return f_err.readAll();}
|
||||
PIByteArray readError() {
|
||||
f_err.open(PIIODevice::ReadOnly);
|
||||
return f_err.readAll();
|
||||
}
|
||||
|
||||
|
||||
//! \~english Returns current attached execution environment
|
||||
//! \~russian
|
||||
PIStringList environment() {return env;}
|
||||
PIStringList environment() { return env; }
|
||||
|
||||
//! \~english Clear current attached execution environment. Call before \a exec()
|
||||
//! \~russian
|
||||
void clearEnvironment() {env.clear();}
|
||||
void clearEnvironment() { env.clear(); }
|
||||
|
||||
//! \~english Remove variable "variable" from current attached execution environment. Call before \a exec()
|
||||
//! \~russian
|
||||
@@ -125,13 +130,25 @@ public:
|
||||
|
||||
//! \~english Start attached execution "program" with one argument "arg"
|
||||
//! \~russian
|
||||
void exec(const PIString & program, const PIString & arg) {args.clear(); args << program << arg; exec_();}
|
||||
void exec(const PIString & program, const PIString & arg) {
|
||||
args.clear();
|
||||
args << program << arg;
|
||||
exec_();
|
||||
}
|
||||
|
||||
EVENT_HANDLER1(void, exec, const PIString & , program) {args.clear(); args << program; exec_();}
|
||||
EVENT_HANDLER2(void, exec, const PIString & , program, const PIStringList & , args_) {args.clear(); args << program << args_; exec_();}
|
||||
EVENT_HANDLER1(void, exec, const PIString &, program) {
|
||||
args.clear();
|
||||
args << program;
|
||||
exec_();
|
||||
}
|
||||
EVENT_HANDLER2(void, exec, const PIString &, program, const PIStringList &, args_) {
|
||||
args.clear();
|
||||
args << program << args_;
|
||||
exec_();
|
||||
}
|
||||
EVENT_HANDLER(void, terminate);
|
||||
EVENT_HANDLER(bool, waitForFinish) {return waitForFinish(60000);}
|
||||
EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs) {return PIThread::waitForFinish(timeout_msecs);}
|
||||
EVENT_HANDLER(bool, waitForFinish) { return waitForFinish(60000); }
|
||||
EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs) { return PIThread::waitForFinish(timeout_msecs); }
|
||||
|
||||
EVENT1(execStarted, PIString, program);
|
||||
EVENT2(execFinished, PIString, program, int, exit_code);
|
||||
@@ -139,11 +156,11 @@ public:
|
||||
|
||||
//! \~english Start detached execution "program" without arguments
|
||||
//! \~russian
|
||||
static void execIndependent(const PIString & program) {execIndependent(program, PIStringList());}
|
||||
static void execIndependent(const PIString & program) { execIndependent(program, PIStringList()); }
|
||||
|
||||
//! \~english Start detached execution "program" with one argument "arg"
|
||||
//! \~russian
|
||||
static void execIndependent(const PIString & program, const PIString & arg) {execIndependent(program, PIStringList() << arg);}
|
||||
static void execIndependent(const PIString & program, const PIString & arg) { execIndependent(program, PIStringList() << arg); }
|
||||
|
||||
//! \~english Start detached execution "program" with arguments "args"
|
||||
//! \~russian
|
||||
@@ -162,8 +179,8 @@ public:
|
||||
//! \~russian
|
||||
static PIString getEnvironmentVariable(const PIString & variable);
|
||||
|
||||
//! \handlers
|
||||
//! \{
|
||||
//! \handlers
|
||||
//! \{
|
||||
|
||||
//! \fn void exec(const PIString & program)
|
||||
//! \brief
|
||||
@@ -190,9 +207,9 @@ public:
|
||||
//! \~english Wait for attached execution finish maximum for "timeout_msecs" milliseconds
|
||||
//! \~russian
|
||||
|
||||
//! \}
|
||||
//! \events
|
||||
//! \{
|
||||
//! \}
|
||||
//! \events
|
||||
//! \{
|
||||
|
||||
//! \fn void execStarted(PIString program)
|
||||
//! \brief
|
||||
@@ -204,7 +221,7 @@ public:
|
||||
//! \~english Raise on attached execution finish
|
||||
//! \~russian
|
||||
|
||||
//! \}
|
||||
//! \}
|
||||
|
||||
private:
|
||||
void run() override;
|
||||
@@ -219,7 +236,6 @@ private:
|
||||
bool g_in, g_out, g_err, t_in, t_out, t_err;
|
||||
int exit_code;
|
||||
bool is_exec;
|
||||
|
||||
};
|
||||
|
||||
#endif // MICRO_PIP
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Signals
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
PIP - Platform Independent Primitives
|
||||
Signals
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "piincludes.h"
|
||||
#include "pisignals.h"
|
||||
|
||||
#include "piincludes.h"
|
||||
#ifdef BLACKBERRY
|
||||
# include <signal.h>
|
||||
#else
|
||||
@@ -39,10 +40,10 @@ void PISignals::grabSignals(PIFlags<PISignals::Signal> signals_) {
|
||||
if (signals_[PISignals::FPE]) signal(signalCode(PISignals::FPE), PISignals::signal_event);
|
||||
if (signals_[PISignals::SegFault]) signal(signalCode(PISignals::SegFault), PISignals::signal_event);
|
||||
if (signals_[PISignals::Termination]) signal(signalCode(PISignals::Termination), PISignals::signal_event);
|
||||
# ifndef CC_VC
|
||||
#ifndef CC_VC
|
||||
if (signals_[PISignals::UserDefined1]) signal(signalCode(PISignals::UserDefined1), PISignals::signal_event);
|
||||
if (signals_[PISignals::UserDefined2]) signal(signalCode(PISignals::UserDefined2), PISignals::signal_event);
|
||||
# endif
|
||||
#endif
|
||||
#ifndef WINDOWS
|
||||
if (signals_[PISignals::Hangup]) signal(signalCode(PISignals::Hangup), PISignals::signal_event);
|
||||
if (signals_[PISignals::Quit]) signal(signalCode(PISignals::Quit), PISignals::signal_event);
|
||||
@@ -72,10 +73,10 @@ int PISignals::signalCode(PISignals::Signal signal) {
|
||||
case PISignals::FPE: return SIGFPE;
|
||||
case PISignals::SegFault: return SIGSEGV;
|
||||
case PISignals::Termination: return SIGTERM;
|
||||
# ifndef CC_VC
|
||||
#ifndef CC_VC
|
||||
case PISignals::UserDefined1: return SIGUSR1;
|
||||
case PISignals::UserDefined2: return SIGUSR2;
|
||||
# endif
|
||||
#endif
|
||||
#ifndef WINDOWS
|
||||
case PISignals::Hangup: return SIGHUP;
|
||||
case PISignals::Quit: return SIGQUIT;
|
||||
@@ -87,7 +88,7 @@ int PISignals::signalCode(PISignals::Signal signal) {
|
||||
case PISignals::StopProcess: return SIGSTOP;
|
||||
case PISignals::StopTTY: return SIGTSTP;
|
||||
case PISignals::StopTTYInput: return SIGTTIN;
|
||||
case PISignals::StopTTYOutput:return SIGTTOU;
|
||||
case PISignals::StopTTYOutput: return SIGTTOU;
|
||||
#endif
|
||||
default:;
|
||||
}
|
||||
@@ -103,10 +104,10 @@ PISignals::Signal PISignals::signalFromCode(int signal) {
|
||||
case SIGFPE: return PISignals::FPE;
|
||||
case SIGSEGV: return PISignals::SegFault;
|
||||
case SIGTERM: return PISignals::Termination;
|
||||
# ifndef CC_VC
|
||||
#ifndef CC_VC
|
||||
case SIGUSR1: return PISignals::UserDefined1;
|
||||
case SIGUSR2: return PISignals::UserDefined2;
|
||||
# endif
|
||||
#endif
|
||||
#ifndef WINDOWS
|
||||
case SIGHUP: return PISignals::Hangup;
|
||||
case SIGQUIT: return PISignals::Quit;
|
||||
|
||||
@@ -5,64 +5,64 @@
|
||||
* \~russian Сигналы системы
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Signals
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
PIP - Platform Independent Primitives
|
||||
Signals
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PISIGNALS_H
|
||||
#define PISIGNALS_H
|
||||
|
||||
#include "piflags.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
class PIP_EXPORT PISignals
|
||||
{
|
||||
class PIP_EXPORT PISignals {
|
||||
public:
|
||||
enum Signal {
|
||||
Interrupt /** Interrupt from keyboard */ = 0x01, // Term Interrupt from keyboard
|
||||
Illegal /** Illegal Instruction */ = 0x02, // Core Illegal Instruction
|
||||
Abort /** Abort signal */ = 0x04, // Core Abort signal from abort
|
||||
FPE /** Floating point exception */ = 0x08, // Core Floating point exception
|
||||
SegFault /** Invalid memory reference */ = 0x10, // Core Invalid memory reference
|
||||
Termination /** Termination signal */ = 0x20, // Term Termination signal
|
||||
Hangup = 0x40, // Term Hangup detected on controlling terminal or death of controlling process
|
||||
Quit = 0x80, // Core Quit from keyboard
|
||||
Kill = 0x100, // Term Kill signal
|
||||
BrokenPipe = 0x200, // Term Broken pipe: write to pipe with no readers
|
||||
Timer = 0x400, // Term Timer signal from alarm
|
||||
UserDefined1 = 0x800, // Term User-defined signal 1
|
||||
UserDefined2 = 0x1000, // Term User-defined signal 2
|
||||
ChildStopped = 0x2000, // Ign Child stopped or terminated
|
||||
Continue = 0x4000, // Cont Continue if stopped
|
||||
StopProcess = 0x8000, // Stop Stop process
|
||||
StopTTY = 0x10000, // Stop Stop typed at tty
|
||||
StopTTYInput = 0x20000, // Stop tty input for background process
|
||||
StopTTYOutput = 0x40000, // Stop tty output for background process
|
||||
All = 0xFFFFF
|
||||
Interrupt /** Interrupt from keyboard */ = 0x01, // Term Interrupt from keyboard
|
||||
Illegal /** Illegal Instruction */ = 0x02, // Core Illegal Instruction
|
||||
Abort /** Abort signal */ = 0x04, // Core Abort signal from abort
|
||||
FPE /** Floating point exception */ = 0x08, // Core Floating point exception
|
||||
SegFault /** Invalid memory reference */ = 0x10, // Core Invalid memory reference
|
||||
Termination /** Termination signal */ = 0x20, // Term Termination signal
|
||||
Hangup = 0x40, // Term Hangup detected on controlling terminal or death of controlling process
|
||||
Quit = 0x80, // Core Quit from keyboard
|
||||
Kill = 0x100, // Term Kill signal
|
||||
BrokenPipe = 0x200, // Term Broken pipe: write to pipe with no readers
|
||||
Timer = 0x400, // Term Timer signal from alarm
|
||||
UserDefined1 = 0x800, // Term User-defined signal 1
|
||||
UserDefined2 = 0x1000, // Term User-defined signal 2
|
||||
ChildStopped = 0x2000, // Ign Child stopped or terminated
|
||||
Continue = 0x4000, // Cont Continue if stopped
|
||||
StopProcess = 0x8000, // Stop Stop process
|
||||
StopTTY = 0x10000, // Stop Stop typed at tty
|
||||
StopTTYInput = 0x20000, // Stop tty input for background process
|
||||
StopTTYOutput = 0x40000, // Stop tty output for background process
|
||||
All = 0xFFFFF
|
||||
};
|
||||
|
||||
typedef std::function<void(PISignals::Signal)> SignalEvent;
|
||||
// slot is any function format "void(PISignals::Signal)"
|
||||
static void setSlot(SignalEvent slot) {ret_func = slot;}
|
||||
static void setSlot(SignalEvent slot) { ret_func = slot; }
|
||||
static void grabSignals(PIFlags<PISignals::Signal> signals_);
|
||||
static void raiseSignal(PISignals::Signal signal);
|
||||
|
||||
private:
|
||||
PISignals() {ret_func = 0;}
|
||||
PISignals() { ret_func = 0; }
|
||||
~PISignals() {}
|
||||
|
||||
static int signalCode(PISignals::Signal signal);
|
||||
@@ -70,7 +70,6 @@ private:
|
||||
static void signal_event(int signal);
|
||||
|
||||
static SignalEvent ret_func;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Single application
|
||||
Single application
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "pisingleapplication.h"
|
||||
|
||||
#include "pisharedmemory.h"
|
||||
|
||||
|
||||
@@ -60,22 +61,21 @@
|
||||
//!
|
||||
|
||||
|
||||
#define SHM_SIZE 1024*32
|
||||
#define SHM_SIZE 1024 * 32
|
||||
|
||||
|
||||
PISingleApplication::PISingleApplication(const PIString & app_name): PIThread() {
|
||||
first = true;
|
||||
first = true;
|
||||
started = false;
|
||||
sacnt = 0;
|
||||
shm = new PISharedMemory("sa_" + app_name, SHM_SIZE);
|
||||
sacnt = 0;
|
||||
shm = new PISharedMemory("sa_" + app_name, SHM_SIZE);
|
||||
start(100);
|
||||
}
|
||||
|
||||
|
||||
PISingleApplication::~PISingleApplication() {
|
||||
stop();
|
||||
if (!waitForFinish(5000))
|
||||
terminate();
|
||||
if (!waitForFinish(5000)) terminate();
|
||||
delete shm;
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ void PISingleApplication::sendMessage(const PIByteArray & m) {
|
||||
|
||||
void PISingleApplication::begin() {
|
||||
int cnt[2] = {0, 0};
|
||||
int tcnt = 0;
|
||||
int tcnt = 0;
|
||||
shm->read(cnt, 8);
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
tcnt = cnt[0];
|
||||
@@ -113,7 +113,7 @@ void PISingleApplication::begin() {
|
||||
}
|
||||
piMSleep(100);
|
||||
}
|
||||
//piCoutObj << "started" << first << shm->size();
|
||||
// piCoutObj << "started" << first << shm->size();
|
||||
readed.reserve(shm->size());
|
||||
started = true;
|
||||
}
|
||||
@@ -124,8 +124,8 @@ void PISingleApplication::run() {
|
||||
++sacnt;
|
||||
int st_[2] = {sacnt, sacnt};
|
||||
shm->write(st_, 8);
|
||||
//piCoutObj << "write" << sacnt;
|
||||
int ri[3] = {0, 0, 0};
|
||||
// piCoutObj << "write" << sacnt;
|
||||
int ri[3] = {0, 0, 0};
|
||||
const int hdr_sz = sizeof(int) * 3;
|
||||
shm->read(ri, hdr_sz);
|
||||
if (ri[2] != 0 && ri[0] == ri[1]) {
|
||||
@@ -135,7 +135,7 @@ void PISingleApplication::run() {
|
||||
readed >> msg;
|
||||
if (!msg.isEmpty()) {
|
||||
messageReceived(msg);
|
||||
//piCoutObj << "message" << msg;
|
||||
// piCoutObj << "message" << msg;
|
||||
}
|
||||
int wi[3] = {sacnt, sacnt, 0};
|
||||
shm->write(wi, 12);
|
||||
|
||||
@@ -5,22 +5,22 @@
|
||||
* \~russian Контроль одного экземпляра приложения
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Single application
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
PIP - Platform Independent Primitives
|
||||
Single application
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PISINGLEAPPLICATION_H
|
||||
@@ -36,8 +36,8 @@ class PISharedMemory;
|
||||
//! \~russian Контроль одного экземпляра приложения.
|
||||
class PIP_EXPORT PISingleApplication: public PIThread {
|
||||
PIOBJECT_SUBCLASS(PISingleApplication, PIThread);
|
||||
public:
|
||||
|
||||
public:
|
||||
//! \~english Construct %PISingleApplication with name "app_name"
|
||||
//! \~russian Создает %PISingleApplication с именем "app_name"
|
||||
PISingleApplication(const PIString & app_name = PIString());
|
||||
@@ -52,24 +52,24 @@ public:
|
||||
EVENT_HANDLER1(void, sendMessage, const PIByteArray &, m);
|
||||
EVENT1(messageReceived, PIByteArray, m);
|
||||
|
||||
//! \handlers
|
||||
//! \{
|
||||
//! \handlers
|
||||
//! \{
|
||||
|
||||
//! \fn void sendMessage(const PIByteArray & m)
|
||||
//! \brief
|
||||
//! \~english Send message "m" to first launched application
|
||||
//! \~russian Посылает сообщение "m" первому запущеному приложению
|
||||
|
||||
//! \}
|
||||
//! \events
|
||||
//! \{
|
||||
//! \}
|
||||
//! \events
|
||||
//! \{
|
||||
|
||||
//! \fn void messageReceived(PIByteArray m)
|
||||
//! \brief
|
||||
//! \~english Raise on first launched application receive message from another
|
||||
//! \~russian Вызывается первым запущеным приложением по приему сообщения от других
|
||||
|
||||
//! \}
|
||||
//! \}
|
||||
|
||||
private:
|
||||
void begin() override;
|
||||
@@ -81,7 +81,6 @@ private:
|
||||
PIByteArray readed;
|
||||
bool first, started;
|
||||
int sacnt;
|
||||
|
||||
};
|
||||
|
||||
#endif // PISINGLEAPPLICATION_H
|
||||
|
||||
@@ -1,44 +1,42 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
System information
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
PIP - Platform Independent Primitives
|
||||
System information
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pisysteminfo.h"
|
||||
#include "piincludes_p.h"
|
||||
#include "pidir.h"
|
||||
|
||||
#include "picrc.h"
|
||||
#include "pidir.h"
|
||||
#include "piincludes_p.h"
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
# include "esp_system.h"
|
||||
# include "esp_spi_flash.h"
|
||||
# include "esp_system.h"
|
||||
#endif
|
||||
|
||||
#define SALT_SIZE 8
|
||||
|
||||
|
||||
|
||||
|
||||
PISystemInfo * PISystemInfo::instance() {
|
||||
static PISystemInfo ret;
|
||||
return &ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PIStringList PISystemInfo::mountRoots() {
|
||||
PIStringList ret;
|
||||
#ifdef WINDOWS
|
||||
@@ -64,7 +62,10 @@ PIStringList PISystemInfo::mountRoots() {
|
||||
tl = PIString(in).trim().replaceAll(" ", " ").split(" ");
|
||||
if (tl.size_s() < 2) continue;
|
||||
for (int i = 0; i < tl.size_s() - 1; ++i)
|
||||
if (tl[i] == "on") {if (!ret.contains(tl[i + 1])) ret << tl[i + 1]; break;}
|
||||
if (tl[i] == "on") {
|
||||
if (!ret.contains(tl[i + 1])) ret << tl[i + 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
pclose(fp);
|
||||
}
|
||||
@@ -75,20 +76,21 @@ PIStringList PISystemInfo::mountRoots() {
|
||||
}
|
||||
|
||||
|
||||
struct String3 {PIString mp, type, label;};
|
||||
struct String3 {
|
||||
PIString mp, type, label;
|
||||
};
|
||||
|
||||
PIVector<PISystemInfo::MountInfo> PISystemInfo::mountInfo(bool ignore_cache) {
|
||||
static PIVector<PISystemInfo::MountInfo> cache;
|
||||
static PITimeMeasurer tm;
|
||||
static bool first = true;
|
||||
if (!ignore_cache) {
|
||||
if (tm.elapsed_m() < piMountInfoRefreshIntervalMs && !first)
|
||||
return cache;
|
||||
if (tm.elapsed_m() < piMountInfoRefreshIntervalMs && !first) return cache;
|
||||
}
|
||||
first = false;
|
||||
tm.reset();
|
||||
cache.clear();
|
||||
|
||||
|
||||
PIVector<PISystemInfo::MountInfo> ret;
|
||||
MountInfo m;
|
||||
#ifdef WINDOWS
|
||||
@@ -99,18 +101,17 @@ PIVector<PISystemInfo::MountInfo> PISystemInfo::mountInfo(bool ignore_cache) {
|
||||
if (letters[i] == '\0') {
|
||||
if (GetVolumeInformationA(clet.data(), volname, 1023, 0, 0, 0, volfs, 1023)) {
|
||||
m.mount_point = clet;
|
||||
m.filesystem = volfs;
|
||||
m.label = volname;
|
||||
m.filesystem = volfs;
|
||||
m.label = volname;
|
||||
DWORD spc, bps, free_cl, all_cl;
|
||||
if (GetDiskFreeSpaceA(clet.data(), &spc, &bps, &free_cl, &all_cl)) {
|
||||
ullong bpc = ullong(spc) * ullong(bps);
|
||||
m.space_all = bpc * ullong(all_cl);
|
||||
ullong bpc = ullong(spc) * ullong(bps);
|
||||
m.space_all = bpc * ullong(all_cl);
|
||||
m.space_free = bpc * ullong(free_cl);
|
||||
m.space_used = m.space_all - m.space_free;
|
||||
} else
|
||||
m.space_all = m.space_free = m.space_used = 0U;
|
||||
if (GetDriveTypeA(clet.dataAscii()) == DRIVE_REMOVABLE)
|
||||
m.removable = true;
|
||||
if (GetDriveTypeA(clet.dataAscii()) == DRIVE_REMOVABLE) m.removable = true;
|
||||
clet.cutRight(1);
|
||||
int qdd = QueryDosDeviceA(clet.data(), volfs, 1023);
|
||||
if (qdd > 0)
|
||||
@@ -129,7 +130,7 @@ PIVector<PISystemInfo::MountInfo> PISystemInfo::mountInfo(bool ignore_cache) {
|
||||
PIString s_df, s_m;
|
||||
char in[1024];
|
||||
memset(in, 0, 1024);
|
||||
//piCout << "mountInfo 0";
|
||||
// piCout << "mountInfo 0";
|
||||
FILE * fp = popen("df -B1", "r");
|
||||
PIStringList l_df;
|
||||
PIMap<PIString, String3> fs;
|
||||
@@ -139,7 +140,7 @@ PIVector<PISystemInfo::MountInfo> PISystemInfo::mountInfo(bool ignore_cache) {
|
||||
pclose(fp);
|
||||
fp = 0;
|
||||
}
|
||||
//piCout << "mountInfo 1";
|
||||
// piCout << "mountInfo 1";
|
||||
memset(in, 0, 1024);
|
||||
fp = popen("mount -l", "r");
|
||||
PIStringList tl;
|
||||
@@ -151,43 +152,51 @@ PIVector<PISystemInfo::MountInfo> PISystemInfo::mountInfo(bool ignore_cache) {
|
||||
PIString dev;
|
||||
dev = tl.front();
|
||||
for (int i = 0; i < tl.size_s() - 1; ++i) {
|
||||
if (tl[i] == "on") {me.mp = tl[i + 1]; ++i; continue;}
|
||||
if (tl[i] == "type") {me.type = tl[i + 1]; ++i; continue;}
|
||||
if (tl[i] == "on") {
|
||||
me.mp = tl[i + 1];
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
if (tl[i] == "type") {
|
||||
me.type = tl[i + 1];
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (tl.back().startsWith("[")) {
|
||||
me.label = tl.back();
|
||||
me.label.cutLeft(1).cutRight(1);
|
||||
}
|
||||
fs[dev] = me;
|
||||
//piCout << fsmp << fstl;
|
||||
// piCout << fsmp << fstl;
|
||||
}
|
||||
pclose(fp);
|
||||
fp = 0;
|
||||
}
|
||||
if (l_df.size_s() < 2) return ret;
|
||||
l_df.pop_front();
|
||||
piForeachC (PIString & s, l_df) {
|
||||
piForeachC(PIString & s, l_df) {
|
||||
PIStringList ml(s.replacedAll(" ", " ").split(" "));
|
||||
if (ml.size_s() < 2) continue;
|
||||
if (ml.front() == "none") continue;
|
||||
m.space_all = ml[1].toULLong();
|
||||
m.space_used = ml[2].toULLong();
|
||||
m.space_free = m.space_all - m.space_used;
|
||||
String3 s3 = fs.value(ml.front());
|
||||
m.device = ml.front();
|
||||
m.filesystem = s3.type;
|
||||
m.space_all = ml[1].toULLong();
|
||||
m.space_used = ml[2].toULLong();
|
||||
m.space_free = m.space_all - m.space_used;
|
||||
String3 s3 = fs.value(ml.front());
|
||||
m.device = ml.front();
|
||||
m.filesystem = s3.type;
|
||||
m.mount_point = s3.mp;
|
||||
m.label = s3.label;
|
||||
m.label = s3.label;
|
||||
ret << m;
|
||||
//piCout << ml;
|
||||
// piCout << ml;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
esp_chip_info_t chip_info;
|
||||
esp_chip_info(&chip_info);
|
||||
m.device = ((chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded SPI flash" : "external SPI flash");
|
||||
m.space_all = spi_flash_get_chip_size();
|
||||
m.device = ((chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded SPI flash" : "external SPI flash");
|
||||
m.space_all = spi_flash_get_chip_size();
|
||||
m.mount_point = "/";
|
||||
ret << m;
|
||||
#endif
|
||||
@@ -198,19 +207,19 @@ PIVector<PISystemInfo::MountInfo> PISystemInfo::mountInfo(bool ignore_cache) {
|
||||
PIString confDir() {
|
||||
return
|
||||
#ifdef WINDOWS
|
||||
PIDir::home().path() + "/AppData/Local"
|
||||
PIDir::home().path() + "/AppData/Local"
|
||||
#elif defined(ANDROID)
|
||||
""
|
||||
""
|
||||
#else
|
||||
PIDir::home().path() + "/.config"
|
||||
PIDir::home().path() + "/.config"
|
||||
#endif
|
||||
;
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
PIByteArray generateSalt() {
|
||||
PIByteArray ret;
|
||||
piForTimes (SALT_SIZE) {
|
||||
piForTimes(SALT_SIZE) {
|
||||
piMSleep(randomi() % 10);
|
||||
randomize();
|
||||
ret << uchar(randomi() % 0x100);
|
||||
@@ -230,7 +239,7 @@ PIString PISystemInfo::machineKey() {
|
||||
f.open();
|
||||
salt = f.readAll();
|
||||
}
|
||||
if (salt.size_s() != SALT_SIZE){
|
||||
if (salt.size_s() != SALT_SIZE) {
|
||||
salt = generateSalt();
|
||||
PIFile f(conf, PIIODevice::ReadWrite);
|
||||
f.open();
|
||||
@@ -247,8 +256,8 @@ uint PISystemInfo::machineID() {
|
||||
static uint ret = 0;
|
||||
if (ret == 0) {
|
||||
CRC_32 crc = standardCRC_32();
|
||||
ret = crc.calculate(machineKey().toByteArray());
|
||||
//piCout << "machineID \"" << machineKey() << "\" =" << PICoutManipulators::Hex << ret;
|
||||
ret = crc.calculate(machineKey().toByteArray());
|
||||
// piCout << "machineID \"" << machineKey() << "\" =" << PICoutManipulators::Hex << ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -5,22 +5,22 @@
|
||||
* \~russian Информация о системе
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
System information
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
PIP - Platform Independent Primitives
|
||||
System information
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PISYSTEMINFO_H
|
||||
@@ -35,13 +35,11 @@
|
||||
//! \~russian Информация о системе.
|
||||
class PIP_EXPORT PISystemInfo {
|
||||
public:
|
||||
|
||||
//! \ingroup System
|
||||
//! \~\brief
|
||||
//! \~english Mount point information.
|
||||
//! \~russian Информация о точке монтирования.
|
||||
struct PIP_EXPORT MountInfo {
|
||||
|
||||
//! \~english Absolute path to mount point
|
||||
//! \~russian Абсолютный путь к точке монтирования
|
||||
PIString mount_point;
|
||||
@@ -60,7 +58,7 @@ public:
|
||||
|
||||
//! \~english Total space in bytes
|
||||
//! \~russian Полный объем в байтах
|
||||
ullong space_all = 0;
|
||||
ullong space_all = 0;
|
||||
|
||||
//! \~english Used space in bytes
|
||||
//! \~russian Занятый объем в байтах
|
||||
@@ -72,7 +70,7 @@ public:
|
||||
|
||||
//! \~english Is this device is removable
|
||||
//! \~russian Является ли устройство съёмным
|
||||
bool removable = false;
|
||||
bool removable = false;
|
||||
};
|
||||
|
||||
//! \~english Absolute path to "ifconfig" utility
|
||||
@@ -110,7 +108,7 @@ public:
|
||||
//! \~english System logical processors count
|
||||
//! \~russian Количество логических процессоров системы
|
||||
int processorsCount = 1;
|
||||
|
||||
|
||||
|
||||
//! \~english Returns all mount points absolute pathes
|
||||
//! \~russian Возвращает абсолютные пути всех точек монтирования
|
||||
@@ -127,7 +125,7 @@ public:
|
||||
//! \~english Returns system unique key hash
|
||||
//! \~russian Возвращает хэш уникального ключа системы
|
||||
static uint machineID();
|
||||
|
||||
|
||||
|
||||
//! \~english Returns singleton of %PISystemInfo
|
||||
//! \~russian Возвращает синглтон %PISystemInfo
|
||||
@@ -136,19 +134,17 @@ public:
|
||||
private:
|
||||
PISystemInfo() {}
|
||||
NO_COPY_CLASS(PISystemInfo);
|
||||
|
||||
};
|
||||
|
||||
|
||||
//! \relatesalso PICout
|
||||
//! \~english Output operator to \a PICout
|
||||
//! \~russian Оператор вывода в \a PICout
|
||||
inline PICout operator <<(PICout s, const PISystemInfo::MountInfo & v) {
|
||||
inline PICout operator<<(PICout s, const PISystemInfo::MountInfo & v) {
|
||||
s.saveAndSetControls(0);
|
||||
s << "MountInfo(" << v.device << " mounted on \"" << v.mount_point << "\", type " << v.filesystem
|
||||
<< ", label \"" << v.label << "\", all " << PIString::readableSize(v.space_all)
|
||||
<< ", used " << PIString::readableSize(v.space_used)
|
||||
<< ", free " << PIString::readableSize(v.space_free) << ")";
|
||||
s << "MountInfo(" << v.device << " mounted on \"" << v.mount_point << "\", type " << v.filesystem << ", label \"" << v.label
|
||||
<< "\", all " << PIString::readableSize(v.space_all) << ", used " << PIString::readableSize(v.space_used) << ", free "
|
||||
<< PIString::readableSize(v.space_free) << ")";
|
||||
s.restoreControls();
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Module includes
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
PIP - Platform Independent Primitives
|
||||
Module includes
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
//! \defgroup System System
|
||||
//! \~\brief
|
||||
@@ -53,11 +53,11 @@
|
||||
#ifndef PISYSTEMMODULE_H
|
||||
#define PISYSTEMMODULE_H
|
||||
|
||||
#include "pisignals.h"
|
||||
#include "pilibrary.h"
|
||||
#include "pisysteminfo.h"
|
||||
#include "pisystemtests.h"
|
||||
#include "pisystemmonitor.h"
|
||||
#include "pisignals.h"
|
||||
#include "pisingleapplication.h"
|
||||
#include "pisysteminfo.h"
|
||||
#include "pisystemmonitor.h"
|
||||
#include "pisystemtests.h"
|
||||
|
||||
#endif // PISYSTEMMODULE_H
|
||||
|
||||
@@ -1,459 +1,455 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Process resource monitor
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "piincludes_p.h"
|
||||
#include "pisystemmonitor.h"
|
||||
#include "pisysteminfo.h"
|
||||
#include "piprocess.h"
|
||||
#include "pidir.h"
|
||||
#include "pitime_win.h"
|
||||
#ifdef WINDOWS
|
||||
# include <psapi.h>
|
||||
# include <tlhelp32.h>
|
||||
#endif
|
||||
#ifdef MAC_OS
|
||||
struct kqueue_id_t;
|
||||
# include <libproc.h>
|
||||
# include <sys/proc_info.h>
|
||||
#endif
|
||||
#ifdef ESP_PLATFORM
|
||||
# include "esp_heap_caps.h"
|
||||
#endif
|
||||
|
||||
|
||||
void PISystemMonitor::ProcessStats::makeStrings() {
|
||||
physical_memsize_readable.setReadableSize(physical_memsize);
|
||||
resident_memsize_readable.setReadableSize(resident_memsize);
|
||||
share_memsize_readable.setReadableSize(share_memsize);
|
||||
virtual_memsize_readable.setReadableSize(virtual_memsize);
|
||||
data_memsize_readable.setReadableSize(data_memsize);
|
||||
}
|
||||
|
||||
|
||||
#ifndef MICRO_PIP
|
||||
PRIVATE_DEFINITION_START(PISystemMonitor)
|
||||
#ifndef WINDOWS
|
||||
# ifdef MAC_OS
|
||||
PISystemTime
|
||||
# else
|
||||
llong
|
||||
# endif
|
||||
cpu_u_cur, cpu_u_prev, cpu_s_cur, cpu_s_prev;
|
||||
PIString proc_dir;
|
||||
PIFile file, filem;
|
||||
#else
|
||||
HANDLE hProc;
|
||||
PROCESS_MEMORY_COUNTERS mem_cnt;
|
||||
PISystemTime tm_kernel, tm_user;
|
||||
PITimeMeasurer tm;
|
||||
#endif
|
||||
PRIVATE_DEFINITION_END(PISystemMonitor)
|
||||
#endif
|
||||
|
||||
|
||||
PISystemMonitor::PISystemMonitor(): PIThread() {
|
||||
pID_ = cycle = 0;
|
||||
cpu_count = PISystemInfo::instance()->processorsCount;
|
||||
#ifndef MICRO_PIP
|
||||
#ifndef WINDOWS
|
||||
# ifdef QNX
|
||||
page_size = 4096;
|
||||
# else
|
||||
page_size = getpagesize();
|
||||
# endif
|
||||
#else
|
||||
PRIVATE->hProc = 0;
|
||||
PRIVATE->mem_cnt.cb = sizeof(PRIVATE->mem_cnt);
|
||||
#endif
|
||||
#endif
|
||||
setName("system_monitor");
|
||||
}
|
||||
|
||||
|
||||
PISystemMonitor::~PISystemMonitor() {
|
||||
stop();
|
||||
}
|
||||
|
||||
|
||||
#ifndef MICRO_PIP
|
||||
bool PISystemMonitor::startOnProcess(int pID, int interval_ms) {
|
||||
stop();
|
||||
pID_ = pID;
|
||||
Pool::instance()->add(this);
|
||||
cycle = -1;
|
||||
#ifndef WINDOWS
|
||||
# ifndef MAC_OS
|
||||
PRIVATE->proc_dir = PIStringAscii("/proc/") + PIString::fromNumber(pID_) + PIStringAscii("/");
|
||||
PRIVATE->file. open(PRIVATE->proc_dir + "stat", PIIODevice::ReadOnly);
|
||||
PRIVATE->filem.open(PRIVATE->proc_dir + "statm", PIIODevice::ReadOnly);
|
||||
if (!PRIVATE->file.isOpened()) {
|
||||
piCoutObj << "Can`t find process with ID = " << pID_ << "!";
|
||||
return false;
|
||||
}
|
||||
# endif
|
||||
#else
|
||||
PRIVATE->hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pID_);
|
||||
if (PRIVATE->hProc == 0) {
|
||||
piCoutObj << "Can`t open process with ID = " << pID_ << "," << errorString();
|
||||
return false;
|
||||
}
|
||||
PRIVATE->tm.reset();
|
||||
#endif
|
||||
return start(interval_ms);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool PISystemMonitor::startOnSelf(int interval_ms) {
|
||||
#ifndef MICRO_PIP
|
||||
bool ret = startOnProcess(PIProcess::currentPID(), interval_ms);
|
||||
cycle = -1;
|
||||
#else
|
||||
bool ret = start(interval_ms);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIVector<PISystemMonitor::ThreadStats> PISystemMonitor::threadsStatistic() const {
|
||||
lock();
|
||||
PIVector<PISystemMonitor::ThreadStats> ret = cur_ts;
|
||||
unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void PISystemMonitor::setStatistic(const PISystemMonitor::ProcessStats & s) {
|
||||
PIMutexLocker _ml(stat_mutex);
|
||||
stat = s;
|
||||
stat.makeStrings();
|
||||
}
|
||||
|
||||
|
||||
void PISystemMonitor::stop() {
|
||||
PIThread::stop();
|
||||
#ifdef WINDOWS
|
||||
if (PRIVATE->hProc != 0) {
|
||||
CloseHandle(PRIVATE->hProc);
|
||||
PRIVATE->hProc = 0;
|
||||
}
|
||||
#endif
|
||||
Pool::instance()->remove(this);
|
||||
}
|
||||
|
||||
|
||||
PISystemMonitor::ProcessStats PISystemMonitor::statistic() const {
|
||||
PIMutexLocker _ml(stat_mutex);
|
||||
return stat;
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAC_OS
|
||||
PISystemTime uint64toST(uint64_t v) {
|
||||
return PISystemTime(((uint*)&(v))[1], ((uint*)&(v))[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void PISystemMonitor::run() {
|
||||
cur_tm.clear();
|
||||
tbid.clear();
|
||||
__PIThreadCollection * pitc = __PIThreadCollection::instance();
|
||||
pitc->lock();
|
||||
PIVector<PIThread * > tv = pitc->threads();
|
||||
piForeach (PIThread * t, tv)
|
||||
if (t->isPIObject())
|
||||
tbid[t->tid()] = t->name();
|
||||
pitc->unlock();
|
||||
//piCout << tbid.keys().toType<uint>();
|
||||
ProcessStats tstat;
|
||||
tstat.ID = pID_;
|
||||
#ifdef MICRO_PIP
|
||||
piForeach (PIThread * t, tv)
|
||||
if (t->isPIObject())
|
||||
gatherThread(t->tid());
|
||||
#else
|
||||
#ifndef WINDOWS
|
||||
tbid[pID_] = "main";
|
||||
# ifdef MAC_OS
|
||||
rusage_info_current ru;
|
||||
proc_pid_rusage(pID_, RUSAGE_INFO_CURRENT, (rusage_info_t*)&ru);
|
||||
//piCout << PISystemTime(((uint*)&(ru.ri_user_time))[1], ((uint*)&(ru.ri_user_time))[0]);
|
||||
if (cycle < 0) {
|
||||
PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur = uint64toST(ru.ri_user_time);
|
||||
PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur = uint64toST(ru.ri_system_time);
|
||||
}
|
||||
PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur;
|
||||
PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur;
|
||||
PRIVATE->cpu_u_cur = uint64toST(ru.ri_user_time);
|
||||
PRIVATE->cpu_s_cur = uint64toST(ru.ri_system_time);
|
||||
tstat.cpu_load_system = 100.f * (PRIVATE->cpu_s_cur - PRIVATE->cpu_s_prev).toMilliseconds() / delay_;
|
||||
tstat.cpu_load_user = 100.f * (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_;
|
||||
cycle = 0;
|
||||
//piCout << (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_;
|
||||
# else
|
||||
PRIVATE->file.seekToBegin();
|
||||
PIString str(PRIVATE->file.readAll(true));
|
||||
int si = str.find('(') + 1, fi = 0, cc = 1;
|
||||
for (int i = si; i < str.size_s(); ++i) {
|
||||
if (str[i] == '(') cc++;
|
||||
if (str[i] == ')') cc--;
|
||||
if (cc <= 0) {
|
||||
fi = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
tstat.exec_name = str.mid(si, fi - si);
|
||||
str.cutMid(si - 1, fi - si + 3);
|
||||
PIStringList sl = str.split(" ");
|
||||
if (sl.size_s() < 19) return;
|
||||
tstat.ID = sl[0].toInt();
|
||||
tstat.state = sl[1];
|
||||
tstat.parent_ID = sl[2].toInt();
|
||||
tstat.group_ID = sl[3].toInt();
|
||||
tstat.session_ID = sl[4].toInt();
|
||||
if (cycle < 0) {
|
||||
PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur = sl[12].toLLong();
|
||||
PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur = sl[13].toLLong();
|
||||
}
|
||||
PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur;
|
||||
PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur;
|
||||
PRIVATE->cpu_u_cur = sl[12].toLLong();
|
||||
PRIVATE->cpu_s_cur = sl[13].toLLong();
|
||||
tstat.cpu_load_system = (PRIVATE->cpu_s_cur - PRIVATE->cpu_s_prev) / (delay_ / 1000.);
|
||||
tstat.cpu_load_user = (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev) / (delay_ / 1000.);
|
||||
tstat.cpu_load_system /= cpu_count;
|
||||
tstat.cpu_load_user /= cpu_count;
|
||||
cycle = 0;
|
||||
tstat.priority = sl[16].toInt();
|
||||
tstat.threads = sl[18].toInt();
|
||||
//piCout << "\n";
|
||||
//piCout << sl[0] << sl[12] << sl[13];
|
||||
|
||||
PRIVATE->filem.seekToBegin();
|
||||
str = PRIVATE->filem.readAll(true);
|
||||
sl = str.split(" ");
|
||||
if (sl.size_s() < 6) return;
|
||||
tstat.virtual_memsize = sl[0].toLong() * page_size;
|
||||
tstat.resident_memsize = sl[1].toLong() * page_size;
|
||||
tstat.share_memsize = sl[2].toLong() * page_size;
|
||||
tstat.data_memsize = sl[5].toLong() * page_size;
|
||||
tstat.physical_memsize = tstat.resident_memsize - tstat.share_memsize;
|
||||
|
||||
PIVector<PIFile::FileInfo> tld = PIDir(PRIVATE->proc_dir + "task").entries();
|
||||
piForeachC (PIFile::FileInfo & i, tld) {
|
||||
if (i.flags[PIFile::FileInfo::Dot] || i.flags[PIFile::FileInfo::DotDot])
|
||||
continue;
|
||||
gatherThread(i.name().toInt());
|
||||
}
|
||||
# endif
|
||||
#else
|
||||
if (GetProcessMemoryInfo(PRIVATE->hProc, &PRIVATE->mem_cnt, sizeof(PRIVATE->mem_cnt)) != 0) {
|
||||
tstat.physical_memsize = PRIVATE->mem_cnt.WorkingSetSize;
|
||||
}
|
||||
tstat.priority = GetPriorityClass(PRIVATE->hProc);
|
||||
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, pID_);
|
||||
int thcnt = 0;
|
||||
if (snap != 0) {
|
||||
THREADENTRY32 thread;
|
||||
thread.dwSize = sizeof(THREADENTRY32);
|
||||
if (Thread32First(snap, &thread) == TRUE) {
|
||||
if (thread.th32OwnerProcessID == DWORD(pID_)) {
|
||||
++thcnt;
|
||||
gatherThread(thread.th32ThreadID);
|
||||
}
|
||||
while (Thread32Next(snap, &thread) == TRUE) {
|
||||
if (thread.th32OwnerProcessID == DWORD(pID_)) {
|
||||
++thcnt;
|
||||
gatherThread(thread.th32ThreadID);
|
||||
}
|
||||
//piCout << thread.th32ThreadID;
|
||||
}
|
||||
}
|
||||
tstat.threads = thcnt;
|
||||
CloseHandle(snap);
|
||||
}
|
||||
FILETIME ft0, ft1, ft_kernel, ft_user;
|
||||
double el_s = PRIVATE->tm.elapsed_s() * cpu_count / 100.;
|
||||
if (GetProcessTimes(PRIVATE->hProc, &ft0, &ft1, &ft_kernel, &ft_user) != 0) {
|
||||
PISystemTime tm_kernel_c = FILETIME2PISystemTime(ft_kernel);
|
||||
PISystemTime tm_user_c = FILETIME2PISystemTime(ft_user);
|
||||
if (cycle < 0) {
|
||||
PRIVATE->tm_kernel = tm_kernel_c;
|
||||
PRIVATE->tm_user = tm_user_c;
|
||||
}
|
||||
cycle = 0;
|
||||
if (el_s <= 0.) {
|
||||
tstat.cpu_load_system = 0.f;
|
||||
tstat.cpu_load_user = 0.f;
|
||||
} else {
|
||||
tstat.cpu_load_system = (tm_kernel_c - PRIVATE->tm_kernel).toSeconds() / el_s;
|
||||
tstat.cpu_load_user = (tm_user_c - PRIVATE->tm_user).toSeconds() / el_s;
|
||||
}
|
||||
PRIVATE->tm_kernel = tm_kernel_c;
|
||||
PRIVATE->tm_user = tm_user_c;
|
||||
} else {
|
||||
tstat.cpu_load_system = 0.f;
|
||||
tstat.cpu_load_user = 0.f;
|
||||
}
|
||||
PRIVATE->tm.reset();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
tstat.cpu_load_system = piClampf(tstat.cpu_load_system, 0.f, 100.f);
|
||||
tstat.cpu_load_user = piClampf(tstat.cpu_load_user , 0.f, 100.f);
|
||||
|
||||
auto i = cur_tm.makeIterator();
|
||||
while (i.next()) {
|
||||
if (!last_tm.contains(i.key())) continue;
|
||||
ThreadStats & ts_new(i.value());
|
||||
ThreadStats & ts_old(last_tm[i.key()]);
|
||||
ts_new.cpu_load_kernel = calcThreadUsage(ts_new.kernel_time, ts_old.kernel_time);
|
||||
ts_new.cpu_load_user = calcThreadUsage(ts_new.user_time, ts_old.user_time);
|
||||
//piCout << ts_new.cpu_load_user;
|
||||
}
|
||||
last_tm = cur_tm;
|
||||
lock();
|
||||
cur_ts = cur_tm.values();
|
||||
unlock();
|
||||
tstat.ram_total = totalRAM();
|
||||
tstat.ram_used = usedRAM();
|
||||
tstat.ram_free = freeRAM();
|
||||
stat_mutex.lock();
|
||||
stat = tstat;
|
||||
stat.makeStrings();
|
||||
stat_mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
void PISystemMonitor::gatherThread(llong id) {
|
||||
PISystemMonitor::ThreadStats ts;
|
||||
if (id == 0) return;
|
||||
ts.id = id;
|
||||
#ifdef MICRO_PIP
|
||||
ts.name = tbid.value(id, "<PIThread>");
|
||||
#else
|
||||
ts.name = tbid.value(id, "<non-PIThread>");
|
||||
# ifndef WINDOWS
|
||||
PIFile f(PRIVATE->proc_dir + "task/" + PIString::fromNumber(id) + "/stat");
|
||||
//piCout << f.path();
|
||||
if (!f.open(PIIODevice::ReadOnly))
|
||||
return;
|
||||
PIString str = f.readAll(true);
|
||||
int si = str.find('(') + 1, fi = 0, cc = 1;
|
||||
for (int i = si; i < str.size_s(); ++i) {
|
||||
if (str[i] == '(') cc++;
|
||||
if (str[i] == ')') cc--;
|
||||
if (cc <= 0) {
|
||||
fi = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
str.cutMid(si - 1, fi - si + 3);
|
||||
PIStringList sl = str.split(" ");
|
||||
if (sl.size_s() < 14) return;
|
||||
//piCout << sl[0] << sl[12] << sl[13];
|
||||
ts.user_time = PISystemTime::fromMilliseconds(sl[12].toInt() * 10.);
|
||||
ts.kernel_time = PISystemTime::fromMilliseconds(sl[13].toInt() * 10.);
|
||||
# else
|
||||
PISystemTime ct = PISystemTime::current();
|
||||
FILETIME times[4];
|
||||
HANDLE thdl = OpenThread(THREAD_QUERY_INFORMATION, FALSE, DWORD(id));
|
||||
if (!thdl) {
|
||||
piCout << "[PISystemMonitor] gatherThread(" << id << "):: OpenThread() error:" << errorString();
|
||||
return;
|
||||
}
|
||||
if (GetThreadTimes(thdl, &(times[0]), &(times[1]), &(times[2]), &(times[3])) == 0) {
|
||||
CloseHandle(thdl);
|
||||
piCout << "[PISystemMonitor] gatherThread(" << id << "):: GetThreadTimes() error:" << errorString();
|
||||
return;
|
||||
}
|
||||
CloseHandle(thdl);
|
||||
ts.created = FILETIME2PIDateTime(times[0]);
|
||||
ts.work_time = ct - ts.created.toSystemTime();
|
||||
ts.kernel_time = FILETIME2PISystemTime(times[2]);
|
||||
ts.user_time = FILETIME2PISystemTime(times[3]);
|
||||
# endif
|
||||
#endif
|
||||
cur_tm[id] = ts;
|
||||
}
|
||||
|
||||
|
||||
float PISystemMonitor::calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old) {
|
||||
if (delay_ <= 0) return -1.;
|
||||
return piClampf(100. * ((t_new - t_old).toMilliseconds() / delay_), 0.f, 100.f);
|
||||
}
|
||||
|
||||
|
||||
ullong PISystemMonitor::totalRAM() {
|
||||
#ifdef ESP_PLATFORM
|
||||
multi_heap_info_t heap_info;
|
||||
memset(&heap_info, 0, sizeof(multi_heap_info_t));
|
||||
heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
|
||||
return heap_info.total_allocated_bytes + heap_info.total_free_bytes;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ullong PISystemMonitor::freeRAM() {
|
||||
#ifdef ESP_PLATFORM
|
||||
multi_heap_info_t heap_info;
|
||||
memset(&heap_info, 0, sizeof(multi_heap_info_t));
|
||||
heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
|
||||
return heap_info.total_free_bytes;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ullong PISystemMonitor::usedRAM() {
|
||||
#ifdef ESP_PLATFORM
|
||||
multi_heap_info_t heap_info;
|
||||
memset(&heap_info, 0, sizeof(multi_heap_info_t));
|
||||
heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
|
||||
return heap_info.total_allocated_bytes;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PISystemMonitor::Pool * PISystemMonitor::Pool::instance() {
|
||||
static Pool ret;
|
||||
return &ret;
|
||||
}
|
||||
|
||||
|
||||
PISystemMonitor * PISystemMonitor::Pool::getByPID(int pID) {
|
||||
PIMutexLocker _ml(mutex);
|
||||
return sysmons.value(pID, 0);
|
||||
}
|
||||
|
||||
|
||||
void PISystemMonitor::Pool::add(PISystemMonitor * sm) {
|
||||
PIMutexLocker _ml(mutex);
|
||||
sysmons[sm->pID()] = sm;
|
||||
}
|
||||
|
||||
|
||||
void PISystemMonitor::Pool::remove(PISystemMonitor * sm) {
|
||||
PIMutexLocker _ml(mutex);
|
||||
sysmons.remove(sm->pID());
|
||||
}
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Process resource monitor
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pisystemmonitor.h"
|
||||
|
||||
#include "pidir.h"
|
||||
#include "piincludes_p.h"
|
||||
#include "piprocess.h"
|
||||
#include "pisysteminfo.h"
|
||||
#include "pitime_win.h"
|
||||
#ifdef WINDOWS
|
||||
# include <psapi.h>
|
||||
# include <tlhelp32.h>
|
||||
#endif
|
||||
#ifdef MAC_OS
|
||||
struct kqueue_id_t;
|
||||
# include <libproc.h>
|
||||
# include <sys/proc_info.h>
|
||||
#endif
|
||||
#ifdef ESP_PLATFORM
|
||||
# include "esp_heap_caps.h"
|
||||
#endif
|
||||
|
||||
|
||||
void PISystemMonitor::ProcessStats::makeStrings() {
|
||||
physical_memsize_readable.setReadableSize(physical_memsize);
|
||||
resident_memsize_readable.setReadableSize(resident_memsize);
|
||||
share_memsize_readable.setReadableSize(share_memsize);
|
||||
virtual_memsize_readable.setReadableSize(virtual_memsize);
|
||||
data_memsize_readable.setReadableSize(data_memsize);
|
||||
}
|
||||
|
||||
|
||||
#ifndef MICRO_PIP
|
||||
PRIVATE_DEFINITION_START(PISystemMonitor)
|
||||
# ifndef WINDOWS
|
||||
# ifdef MAC_OS
|
||||
PISystemTime
|
||||
# else
|
||||
llong
|
||||
# endif
|
||||
cpu_u_cur,
|
||||
cpu_u_prev, cpu_s_cur, cpu_s_prev;
|
||||
PIString proc_dir;
|
||||
PIFile file, filem;
|
||||
# else
|
||||
HANDLE hProc;
|
||||
PROCESS_MEMORY_COUNTERS mem_cnt;
|
||||
PISystemTime tm_kernel, tm_user;
|
||||
PITimeMeasurer tm;
|
||||
# endif
|
||||
PRIVATE_DEFINITION_END(PISystemMonitor)
|
||||
#endif
|
||||
|
||||
|
||||
PISystemMonitor::PISystemMonitor(): PIThread() {
|
||||
pID_ = cycle = 0;
|
||||
cpu_count = PISystemInfo::instance()->processorsCount;
|
||||
#ifndef MICRO_PIP
|
||||
# ifndef WINDOWS
|
||||
# ifdef QNX
|
||||
page_size = 4096;
|
||||
# else
|
||||
page_size = getpagesize();
|
||||
# endif
|
||||
# else
|
||||
PRIVATE->hProc = 0;
|
||||
PRIVATE->mem_cnt.cb = sizeof(PRIVATE->mem_cnt);
|
||||
# endif
|
||||
#endif
|
||||
setName("system_monitor");
|
||||
}
|
||||
|
||||
|
||||
PISystemMonitor::~PISystemMonitor() {
|
||||
stop();
|
||||
}
|
||||
|
||||
|
||||
#ifndef MICRO_PIP
|
||||
bool PISystemMonitor::startOnProcess(int pID, int interval_ms) {
|
||||
stop();
|
||||
pID_ = pID;
|
||||
Pool::instance()->add(this);
|
||||
cycle = -1;
|
||||
# ifndef WINDOWS
|
||||
# ifndef MAC_OS
|
||||
PRIVATE->proc_dir = PIStringAscii("/proc/") + PIString::fromNumber(pID_) + PIStringAscii("/");
|
||||
PRIVATE->file.open(PRIVATE->proc_dir + "stat", PIIODevice::ReadOnly);
|
||||
PRIVATE->filem.open(PRIVATE->proc_dir + "statm", PIIODevice::ReadOnly);
|
||||
if (!PRIVATE->file.isOpened()) {
|
||||
piCoutObj << "Can`t find process with ID = " << pID_ << "!";
|
||||
return false;
|
||||
}
|
||||
# endif
|
||||
# else
|
||||
PRIVATE->hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pID_);
|
||||
if (PRIVATE->hProc == 0) {
|
||||
piCoutObj << "Can`t open process with ID = " << pID_ << "," << errorString();
|
||||
return false;
|
||||
}
|
||||
PRIVATE->tm.reset();
|
||||
# endif
|
||||
return start(interval_ms);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool PISystemMonitor::startOnSelf(int interval_ms) {
|
||||
#ifndef MICRO_PIP
|
||||
bool ret = startOnProcess(PIProcess::currentPID(), interval_ms);
|
||||
cycle = -1;
|
||||
#else
|
||||
bool ret = start(interval_ms);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIVector<PISystemMonitor::ThreadStats> PISystemMonitor::threadsStatistic() const {
|
||||
lock();
|
||||
PIVector<PISystemMonitor::ThreadStats> ret = cur_ts;
|
||||
unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void PISystemMonitor::setStatistic(const PISystemMonitor::ProcessStats & s) {
|
||||
PIMutexLocker _ml(stat_mutex);
|
||||
stat = s;
|
||||
stat.makeStrings();
|
||||
}
|
||||
|
||||
|
||||
void PISystemMonitor::stop() {
|
||||
PIThread::stop();
|
||||
#ifdef WINDOWS
|
||||
if (PRIVATE->hProc != 0) {
|
||||
CloseHandle(PRIVATE->hProc);
|
||||
PRIVATE->hProc = 0;
|
||||
}
|
||||
#endif
|
||||
Pool::instance()->remove(this);
|
||||
}
|
||||
|
||||
|
||||
PISystemMonitor::ProcessStats PISystemMonitor::statistic() const {
|
||||
PIMutexLocker _ml(stat_mutex);
|
||||
return stat;
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAC_OS
|
||||
PISystemTime uint64toST(uint64_t v) {
|
||||
return PISystemTime(((uint *)&(v))[1], ((uint *)&(v))[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void PISystemMonitor::run() {
|
||||
cur_tm.clear();
|
||||
tbid.clear();
|
||||
__PIThreadCollection * pitc = __PIThreadCollection::instance();
|
||||
pitc->lock();
|
||||
PIVector<PIThread *> tv = pitc->threads();
|
||||
piForeach(PIThread * t, tv)
|
||||
if (t->isPIObject()) tbid[t->tid()] = t->name();
|
||||
pitc->unlock();
|
||||
// piCout << tbid.keys().toType<uint>();
|
||||
ProcessStats tstat;
|
||||
tstat.ID = pID_;
|
||||
#ifdef MICRO_PIP
|
||||
piForeach(PIThread * t, tv)
|
||||
if (t->isPIObject()) gatherThread(t->tid());
|
||||
#else
|
||||
# ifndef WINDOWS
|
||||
tbid[pID_] = "main";
|
||||
# ifdef MAC_OS
|
||||
rusage_info_current ru;
|
||||
proc_pid_rusage(pID_, RUSAGE_INFO_CURRENT, (rusage_info_t *)&ru);
|
||||
// piCout << PISystemTime(((uint*)&(ru.ri_user_time))[1], ((uint*)&(ru.ri_user_time))[0]);
|
||||
if (cycle < 0) {
|
||||
PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur = uint64toST(ru.ri_user_time);
|
||||
PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur = uint64toST(ru.ri_system_time);
|
||||
}
|
||||
PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur;
|
||||
PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur;
|
||||
PRIVATE->cpu_u_cur = uint64toST(ru.ri_user_time);
|
||||
PRIVATE->cpu_s_cur = uint64toST(ru.ri_system_time);
|
||||
tstat.cpu_load_system = 100.f * (PRIVATE->cpu_s_cur - PRIVATE->cpu_s_prev).toMilliseconds() / delay_;
|
||||
tstat.cpu_load_user = 100.f * (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_;
|
||||
cycle = 0;
|
||||
// piCout << (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_;
|
||||
# else
|
||||
PRIVATE->file.seekToBegin();
|
||||
PIString str(PRIVATE->file.readAll(true));
|
||||
int si = str.find('(') + 1, fi = 0, cc = 1;
|
||||
for (int i = si; i < str.size_s(); ++i) {
|
||||
if (str[i] == '(') cc++;
|
||||
if (str[i] == ')') cc--;
|
||||
if (cc <= 0) {
|
||||
fi = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
tstat.exec_name = str.mid(si, fi - si);
|
||||
str.cutMid(si - 1, fi - si + 3);
|
||||
PIStringList sl = str.split(" ");
|
||||
if (sl.size_s() < 19) return;
|
||||
tstat.ID = sl[0].toInt();
|
||||
tstat.state = sl[1];
|
||||
tstat.parent_ID = sl[2].toInt();
|
||||
tstat.group_ID = sl[3].toInt();
|
||||
tstat.session_ID = sl[4].toInt();
|
||||
if (cycle < 0) {
|
||||
PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur = sl[12].toLLong();
|
||||
PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur = sl[13].toLLong();
|
||||
}
|
||||
PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur;
|
||||
PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur;
|
||||
PRIVATE->cpu_u_cur = sl[12].toLLong();
|
||||
PRIVATE->cpu_s_cur = sl[13].toLLong();
|
||||
tstat.cpu_load_system = (PRIVATE->cpu_s_cur - PRIVATE->cpu_s_prev) / (delay_ / 1000.);
|
||||
tstat.cpu_load_user = (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev) / (delay_ / 1000.);
|
||||
tstat.cpu_load_system /= cpu_count;
|
||||
tstat.cpu_load_user /= cpu_count;
|
||||
cycle = 0;
|
||||
tstat.priority = sl[16].toInt();
|
||||
tstat.threads = sl[18].toInt();
|
||||
// piCout << "\n";
|
||||
// piCout << sl[0] << sl[12] << sl[13];
|
||||
|
||||
PRIVATE->filem.seekToBegin();
|
||||
str = PRIVATE->filem.readAll(true);
|
||||
sl = str.split(" ");
|
||||
if (sl.size_s() < 6) return;
|
||||
tstat.virtual_memsize = sl[0].toLong() * page_size;
|
||||
tstat.resident_memsize = sl[1].toLong() * page_size;
|
||||
tstat.share_memsize = sl[2].toLong() * page_size;
|
||||
tstat.data_memsize = sl[5].toLong() * page_size;
|
||||
tstat.physical_memsize = tstat.resident_memsize - tstat.share_memsize;
|
||||
|
||||
PIVector<PIFile::FileInfo> tld = PIDir(PRIVATE->proc_dir + "task").entries();
|
||||
piForeachC(PIFile::FileInfo & i, tld) {
|
||||
if (i.flags[PIFile::FileInfo::Dot] || i.flags[PIFile::FileInfo::DotDot]) continue;
|
||||
gatherThread(i.name().toInt());
|
||||
}
|
||||
# endif
|
||||
# else
|
||||
if (GetProcessMemoryInfo(PRIVATE->hProc, &PRIVATE->mem_cnt, sizeof(PRIVATE->mem_cnt)) != 0) {
|
||||
tstat.physical_memsize = PRIVATE->mem_cnt.WorkingSetSize;
|
||||
}
|
||||
tstat.priority = GetPriorityClass(PRIVATE->hProc);
|
||||
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, pID_);
|
||||
int thcnt = 0;
|
||||
if (snap != 0) {
|
||||
THREADENTRY32 thread;
|
||||
thread.dwSize = sizeof(THREADENTRY32);
|
||||
if (Thread32First(snap, &thread) == TRUE) {
|
||||
if (thread.th32OwnerProcessID == DWORD(pID_)) {
|
||||
++thcnt;
|
||||
gatherThread(thread.th32ThreadID);
|
||||
}
|
||||
while (Thread32Next(snap, &thread) == TRUE) {
|
||||
if (thread.th32OwnerProcessID == DWORD(pID_)) {
|
||||
++thcnt;
|
||||
gatherThread(thread.th32ThreadID);
|
||||
}
|
||||
// piCout << thread.th32ThreadID;
|
||||
}
|
||||
}
|
||||
tstat.threads = thcnt;
|
||||
CloseHandle(snap);
|
||||
}
|
||||
FILETIME ft0, ft1, ft_kernel, ft_user;
|
||||
double el_s = PRIVATE->tm.elapsed_s() * cpu_count / 100.;
|
||||
if (GetProcessTimes(PRIVATE->hProc, &ft0, &ft1, &ft_kernel, &ft_user) != 0) {
|
||||
PISystemTime tm_kernel_c = FILETIME2PISystemTime(ft_kernel);
|
||||
PISystemTime tm_user_c = FILETIME2PISystemTime(ft_user);
|
||||
if (cycle < 0) {
|
||||
PRIVATE->tm_kernel = tm_kernel_c;
|
||||
PRIVATE->tm_user = tm_user_c;
|
||||
}
|
||||
cycle = 0;
|
||||
if (el_s <= 0.) {
|
||||
tstat.cpu_load_system = 0.f;
|
||||
tstat.cpu_load_user = 0.f;
|
||||
} else {
|
||||
tstat.cpu_load_system = (tm_kernel_c - PRIVATE->tm_kernel).toSeconds() / el_s;
|
||||
tstat.cpu_load_user = (tm_user_c - PRIVATE->tm_user).toSeconds() / el_s;
|
||||
}
|
||||
PRIVATE->tm_kernel = tm_kernel_c;
|
||||
PRIVATE->tm_user = tm_user_c;
|
||||
} else {
|
||||
tstat.cpu_load_system = 0.f;
|
||||
tstat.cpu_load_user = 0.f;
|
||||
}
|
||||
PRIVATE->tm.reset();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
tstat.cpu_load_system = piClampf(tstat.cpu_load_system, 0.f, 100.f);
|
||||
tstat.cpu_load_user = piClampf(tstat.cpu_load_user, 0.f, 100.f);
|
||||
|
||||
auto i = cur_tm.makeIterator();
|
||||
while (i.next()) {
|
||||
if (!last_tm.contains(i.key())) continue;
|
||||
ThreadStats & ts_new(i.value());
|
||||
ThreadStats & ts_old(last_tm[i.key()]);
|
||||
ts_new.cpu_load_kernel = calcThreadUsage(ts_new.kernel_time, ts_old.kernel_time);
|
||||
ts_new.cpu_load_user = calcThreadUsage(ts_new.user_time, ts_old.user_time);
|
||||
// piCout << ts_new.cpu_load_user;
|
||||
}
|
||||
last_tm = cur_tm;
|
||||
lock();
|
||||
cur_ts = cur_tm.values();
|
||||
unlock();
|
||||
tstat.ram_total = totalRAM();
|
||||
tstat.ram_used = usedRAM();
|
||||
tstat.ram_free = freeRAM();
|
||||
stat_mutex.lock();
|
||||
stat = tstat;
|
||||
stat.makeStrings();
|
||||
stat_mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
void PISystemMonitor::gatherThread(llong id) {
|
||||
PISystemMonitor::ThreadStats ts;
|
||||
if (id == 0) return;
|
||||
ts.id = id;
|
||||
#ifdef MICRO_PIP
|
||||
ts.name = tbid.value(id, "<PIThread>");
|
||||
#else
|
||||
ts.name = tbid.value(id, "<non-PIThread>");
|
||||
# ifndef WINDOWS
|
||||
PIFile f(PRIVATE->proc_dir + "task/" + PIString::fromNumber(id) + "/stat");
|
||||
// piCout << f.path();
|
||||
if (!f.open(PIIODevice::ReadOnly)) return;
|
||||
PIString str = f.readAll(true);
|
||||
int si = str.find('(') + 1, fi = 0, cc = 1;
|
||||
for (int i = si; i < str.size_s(); ++i) {
|
||||
if (str[i] == '(') cc++;
|
||||
if (str[i] == ')') cc--;
|
||||
if (cc <= 0) {
|
||||
fi = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
str.cutMid(si - 1, fi - si + 3);
|
||||
PIStringList sl = str.split(" ");
|
||||
if (sl.size_s() < 14) return;
|
||||
// piCout << sl[0] << sl[12] << sl[13];
|
||||
ts.user_time = PISystemTime::fromMilliseconds(sl[12].toInt() * 10.);
|
||||
ts.kernel_time = PISystemTime::fromMilliseconds(sl[13].toInt() * 10.);
|
||||
# else
|
||||
PISystemTime ct = PISystemTime::current();
|
||||
FILETIME times[4];
|
||||
HANDLE thdl = OpenThread(THREAD_QUERY_INFORMATION, FALSE, DWORD(id));
|
||||
if (!thdl) {
|
||||
piCout << "[PISystemMonitor] gatherThread(" << id << "):: OpenThread() error:" << errorString();
|
||||
return;
|
||||
}
|
||||
if (GetThreadTimes(thdl, &(times[0]), &(times[1]), &(times[2]), &(times[3])) == 0) {
|
||||
CloseHandle(thdl);
|
||||
piCout << "[PISystemMonitor] gatherThread(" << id << "):: GetThreadTimes() error:" << errorString();
|
||||
return;
|
||||
}
|
||||
CloseHandle(thdl);
|
||||
ts.created = FILETIME2PIDateTime(times[0]);
|
||||
ts.work_time = ct - ts.created.toSystemTime();
|
||||
ts.kernel_time = FILETIME2PISystemTime(times[2]);
|
||||
ts.user_time = FILETIME2PISystemTime(times[3]);
|
||||
# endif
|
||||
#endif
|
||||
cur_tm[id] = ts;
|
||||
}
|
||||
|
||||
|
||||
float PISystemMonitor::calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old) {
|
||||
if (delay_ <= 0) return -1.;
|
||||
return piClampf(100. * ((t_new - t_old).toMilliseconds() / delay_), 0.f, 100.f);
|
||||
}
|
||||
|
||||
|
||||
ullong PISystemMonitor::totalRAM() {
|
||||
#ifdef ESP_PLATFORM
|
||||
multi_heap_info_t heap_info;
|
||||
memset(&heap_info, 0, sizeof(multi_heap_info_t));
|
||||
heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
|
||||
return heap_info.total_allocated_bytes + heap_info.total_free_bytes;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ullong PISystemMonitor::freeRAM() {
|
||||
#ifdef ESP_PLATFORM
|
||||
multi_heap_info_t heap_info;
|
||||
memset(&heap_info, 0, sizeof(multi_heap_info_t));
|
||||
heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
|
||||
return heap_info.total_free_bytes;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ullong PISystemMonitor::usedRAM() {
|
||||
#ifdef ESP_PLATFORM
|
||||
multi_heap_info_t heap_info;
|
||||
memset(&heap_info, 0, sizeof(multi_heap_info_t));
|
||||
heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
|
||||
return heap_info.total_allocated_bytes;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
PISystemMonitor::Pool * PISystemMonitor::Pool::instance() {
|
||||
static Pool ret;
|
||||
return &ret;
|
||||
}
|
||||
|
||||
|
||||
PISystemMonitor * PISystemMonitor::Pool::getByPID(int pID) {
|
||||
PIMutexLocker _ml(mutex);
|
||||
return sysmons.value(pID, 0);
|
||||
}
|
||||
|
||||
|
||||
void PISystemMonitor::Pool::add(PISystemMonitor * sm) {
|
||||
PIMutexLocker _ml(mutex);
|
||||
sysmons[sm->pID()] = sm;
|
||||
}
|
||||
|
||||
|
||||
void PISystemMonitor::Pool::remove(PISystemMonitor * sm) {
|
||||
PIMutexLocker _ml(mutex);
|
||||
sysmons.remove(sm->pID());
|
||||
}
|
||||
|
||||
@@ -1,331 +1,323 @@
|
||||
/*! \file pisystemmonitor.h
|
||||
* \ingroup System
|
||||
* \~\brief
|
||||
* \~english System resources monitoring
|
||||
* \~russian Мониторинг ресурсов системы
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Process resource monitor
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PISYSTEMMONITOR_H
|
||||
#define PISYSTEMMONITOR_H
|
||||
|
||||
#include "pithread.h"
|
||||
#include "pifile.h"
|
||||
|
||||
|
||||
//! \ingroup System
|
||||
//! \~\brief
|
||||
//! \~english Process monitoring.
|
||||
//! \~russian Мониторинг процесса.
|
||||
class PIP_EXPORT PISystemMonitor: public PIThread {
|
||||
PIOBJECT_SUBCLASS(PISystemMonitor, PIThread);
|
||||
friend class PIIntrospectionServer;
|
||||
public:
|
||||
//! \~english Constructs unassigned %PISystemMonitor
|
||||
//! \~russian Создает непривязанный %PISystemMonitor
|
||||
PISystemMonitor();
|
||||
|
||||
~PISystemMonitor();
|
||||
|
||||
#pragma pack(push, 1)
|
||||
//! \ingroup System
|
||||
//! \~\brief
|
||||
//! \~english Process statistics (fixed-size fields).
|
||||
//! \~russian Статистика процесса (фиксированные поля).
|
||||
struct PIP_EXPORT ProcessStatsFixed {
|
||||
|
||||
//! \~english PID
|
||||
//! \~russian PID
|
||||
int ID = 0;
|
||||
|
||||
//! \~english Parent PID
|
||||
//! \~russian PID родителя
|
||||
int parent_ID = 0;
|
||||
|
||||
//! \~english Group ID
|
||||
//! \~russian ID группы
|
||||
int group_ID = 0;
|
||||
|
||||
//! \~english Session ID
|
||||
//! \~russian ID сессии
|
||||
int session_ID = 0;
|
||||
|
||||
//! \~english Priority
|
||||
//! \~russian Приоритет
|
||||
int priority = 0;
|
||||
|
||||
//! \~english Threads count
|
||||
//! \~russian Количество потоков
|
||||
int threads = 0;
|
||||
|
||||
//! \~english Physical memory in bytes
|
||||
//! \~russian Физическая память в байтах
|
||||
ullong physical_memsize = 0;
|
||||
|
||||
//! \~english Resident memory in bytes
|
||||
//! \~russian Резидентная память в байтах
|
||||
ullong resident_memsize = 0;
|
||||
|
||||
//! \~english Share memory in bytes
|
||||
//! \~russian Разделяемая память в байтах
|
||||
ullong share_memsize = 0;
|
||||
|
||||
//! \~english Virtual memory in bytes
|
||||
//! \~russian Виртуальная память в байтах
|
||||
ullong virtual_memsize = 0;
|
||||
|
||||
//! \~english Data memory in bytes
|
||||
//! \~russian Память данных в байтах
|
||||
ullong data_memsize = 0;
|
||||
|
||||
//! \~english
|
||||
//! \~russian
|
||||
ullong ram_total = 0;
|
||||
|
||||
//! \~english
|
||||
//! \~russian
|
||||
ullong ram_free = 0;
|
||||
|
||||
//! \~english
|
||||
//! \~russian
|
||||
ullong ram_used = 0;
|
||||
|
||||
//! \~english CPU load in kernel space
|
||||
//! \~russian Загрузка CPU в пространстве ядра
|
||||
float cpu_load_system = 0.f;
|
||||
|
||||
//! \~english CPU load in user space
|
||||
//! \~russian Загрузка CPU в пространстве пользователя
|
||||
float cpu_load_user = 0.f;
|
||||
};
|
||||
|
||||
//! \ingroup System
|
||||
//! \~\brief
|
||||
//! \~english Thread statistics (fixed-size fields).
|
||||
//! \~russian Статистика потока (фиксированные поля).
|
||||
struct PIP_EXPORT ThreadStatsFixed {
|
||||
|
||||
//! \~english TID
|
||||
//! \~russian TID
|
||||
llong id = 0;
|
||||
|
||||
//! \~english Overall live time
|
||||
//! \~russian Полное время жизни
|
||||
PISystemTime work_time;
|
||||
|
||||
//! \~english Busy time in kernel space
|
||||
//! \~russian Время работы в пространстве ядра
|
||||
PISystemTime kernel_time;
|
||||
|
||||
//! \~english Busy time in user space
|
||||
//! \~russian Время работы в пространстве пользователя
|
||||
PISystemTime user_time;
|
||||
|
||||
//! \~english CPU load in kernel space
|
||||
//! \~russian Загрузка CPU в пространстве ядра
|
||||
float cpu_load_kernel = -1.f;
|
||||
|
||||
//! \~english CPU load in user space
|
||||
//! \~russian Загрузка CPU в пространстве пользователя
|
||||
float cpu_load_user = -1.f;
|
||||
|
||||
//! \~english Date and time of creation
|
||||
//! \~russian Дата и время создания
|
||||
PIDateTime created;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
//! \ingroup System
|
||||
//! \~\brief
|
||||
//! \~english Process statistics.
|
||||
//! \~russian Статистика процесса.
|
||||
struct PIP_EXPORT ProcessStats: ProcessStatsFixed {
|
||||
|
||||
//! \~english Fill human-readable fields
|
||||
//! \~russian Заполнить читаемые поля
|
||||
void makeStrings();
|
||||
|
||||
//! \~english Execution command
|
||||
//! \~russian Команда запуска
|
||||
PIString exec_name;
|
||||
|
||||
//! \~english State
|
||||
//! \~russian Состояние
|
||||
PIString state;
|
||||
|
||||
//! \~english Human-readable physical memory
|
||||
//! \~russian Физическая память в читаемом виде
|
||||
PIString physical_memsize_readable;
|
||||
|
||||
//! \~english Human-readable resident memory
|
||||
//! \~russian Резидентная память в читаемом виде
|
||||
PIString resident_memsize_readable;
|
||||
|
||||
//! \~english Human-readable share memory
|
||||
//! \~russian Разделяемая память в читаемом виде
|
||||
PIString share_memsize_readable;
|
||||
|
||||
//! \~english Human-readable virtual memory
|
||||
//! \~russian Виртуальная память в читаемом виде
|
||||
PIString virtual_memsize_readable;
|
||||
|
||||
//! \~english Human-readable data memory
|
||||
//! \~russian Память данных в читаемом виде
|
||||
PIString data_memsize_readable;
|
||||
};
|
||||
|
||||
//! \ingroup System
|
||||
//! \~\brief
|
||||
//! \~english Thread statistics.
|
||||
//! \~russian Статистика потока.
|
||||
struct PIP_EXPORT ThreadStats: ThreadStatsFixed {
|
||||
|
||||
//! \~english Name
|
||||
//! \~russian Имя
|
||||
PIString name;
|
||||
};
|
||||
|
||||
#ifndef MICRO_PIP
|
||||
|
||||
//! \~english Starts monitoring of process with PID "pID" and update interval "interval_ms" milliseconds
|
||||
//! \~russian Начинает мониторинг процесса с PID "pID" и интервалом обновления "interval_ms" миллисекунд
|
||||
bool startOnProcess(int pID, int interval_ms = 1000);
|
||||
#endif
|
||||
|
||||
//! \~english Starts monitoring of application process with update interval "interval_ms" milliseconds
|
||||
//! \~russian Начинает мониторинг процесса приложения с интервалом обновления "interval_ms" миллисекунд
|
||||
bool startOnSelf(int interval_ms = 1000);
|
||||
|
||||
//! \~english Stop monitoring
|
||||
//! \~russian Останавливает мониторинг
|
||||
void stop();
|
||||
|
||||
|
||||
//! \~english Returns monitoring process PID
|
||||
//! \~russian Возвращает PID наблюдаемого процесса
|
||||
int pID() const {return pID_;}
|
||||
|
||||
//! \~english Returns monitoring process statistics
|
||||
//! \~russian Возвращает статистику наблюдаемого процесса
|
||||
ProcessStats statistic() const;
|
||||
|
||||
//! \~english Returns monitoring process threads statistics
|
||||
//! \~russian Возвращает статистику потоков наблюдаемого процесса
|
||||
PIVector<ThreadStats> threadsStatistic() const;
|
||||
|
||||
void setStatistic(const ProcessStats & s);
|
||||
|
||||
|
||||
//! \~english
|
||||
//! \~russian
|
||||
static ullong totalRAM();
|
||||
|
||||
//! \~english
|
||||
//! \~russian
|
||||
static ullong freeRAM();
|
||||
|
||||
//! \~english
|
||||
//! \~russian
|
||||
static ullong usedRAM();
|
||||
|
||||
|
||||
private:
|
||||
void run() override;
|
||||
void gatherThread(llong id);
|
||||
float calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old);
|
||||
|
||||
ProcessStats stat;
|
||||
PIVector<ThreadStats> cur_ts;
|
||||
PIMap<llong, ThreadStats> last_tm, cur_tm;
|
||||
PIMap<llong, PIString> tbid;
|
||||
mutable PIMutex stat_mutex;
|
||||
int pID_, page_size, cpu_count, cycle;
|
||||
#ifndef MICRO_PIP
|
||||
PRIVATE_DECLARATION(PIP_EXPORT)
|
||||
#endif
|
||||
|
||||
class PIP_EXPORT Pool {
|
||||
friend class PISystemMonitor;
|
||||
public:
|
||||
static Pool * instance();
|
||||
PISystemMonitor * getByPID(int pID);
|
||||
private:
|
||||
void add(PISystemMonitor * sm);
|
||||
void remove(PISystemMonitor * sm);
|
||||
PIMap<int, PISystemMonitor*> sysmons;
|
||||
PIMutex mutex;
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
//! \relatesalso PICout
|
||||
//! \~english Output operator to \a PICout
|
||||
//! \~russian Оператор вывода в \a PICout
|
||||
inline PICout operator <<(PICout s, const PISystemMonitor::ThreadStats & v) {
|
||||
s.saveAndSetControls(0);
|
||||
s << "ThreadInfo(\"" << v.name << "\", created " << v.created
|
||||
<< ", work " << v.work_time.toMilliseconds() << " ms"
|
||||
<< ", kernel " << v.kernel_time.toMilliseconds() << " ms"
|
||||
<< ", user " << v.user_time.toMilliseconds() << " ms"
|
||||
<< ")\n";
|
||||
s.restoreControls();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \relatesalso PIBinaryStream
|
||||
//! \~english Store operator.
|
||||
//! \~russian Оператор сохранения.
|
||||
BINARY_STREAM_WRITE(PISystemMonitor::ProcessStats) {
|
||||
s << PIMemoryBlock(&v, sizeof(PISystemMonitor::ProcessStatsFixed))
|
||||
<< v.exec_name << v.state;
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIBinaryStream
|
||||
//! \~english Restore operator.
|
||||
//! \~russian Оператор извлечения.
|
||||
BINARY_STREAM_READ (PISystemMonitor::ProcessStats) {
|
||||
s >> PIMemoryBlock(&v, sizeof(PISystemMonitor::ProcessStatsFixed))
|
||||
>> v.exec_name >> v.state;
|
||||
v.makeStrings();
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIBinaryStream
|
||||
//! \~english Store operator.
|
||||
//! \~russian Оператор сохранения.
|
||||
BINARY_STREAM_WRITE(PISystemMonitor::ThreadStats) {
|
||||
s << PIMemoryBlock(&v, sizeof(PISystemMonitor::ThreadStatsFixed))
|
||||
<< v.name;
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIBinaryStream
|
||||
//! \~english Restore operator.
|
||||
//! \~russian Оператор извлечения.
|
||||
BINARY_STREAM_READ (PISystemMonitor::ThreadStats) {
|
||||
s >> PIMemoryBlock(&v, sizeof(PISystemMonitor::ThreadStatsFixed))
|
||||
>> v.name;
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif // PISYSTEMMONITOR_H
|
||||
/*! \file pisystemmonitor.h
|
||||
* \ingroup System
|
||||
* \~\brief
|
||||
* \~english System resources monitoring
|
||||
* \~russian Мониторинг ресурсов системы
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Process resource monitor
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PISYSTEMMONITOR_H
|
||||
#define PISYSTEMMONITOR_H
|
||||
|
||||
#include "pifile.h"
|
||||
#include "pithread.h"
|
||||
|
||||
|
||||
//! \ingroup System
|
||||
//! \~\brief
|
||||
//! \~english Process monitoring.
|
||||
//! \~russian Мониторинг процесса.
|
||||
class PIP_EXPORT PISystemMonitor: public PIThread {
|
||||
PIOBJECT_SUBCLASS(PISystemMonitor, PIThread);
|
||||
friend class PIIntrospectionServer;
|
||||
|
||||
public:
|
||||
//! \~english Constructs unassigned %PISystemMonitor
|
||||
//! \~russian Создает непривязанный %PISystemMonitor
|
||||
PISystemMonitor();
|
||||
|
||||
~PISystemMonitor();
|
||||
|
||||
#pragma pack(push, 1)
|
||||
//! \ingroup System
|
||||
//! \~\brief
|
||||
//! \~english Process statistics (fixed-size fields).
|
||||
//! \~russian Статистика процесса (фиксированные поля).
|
||||
struct PIP_EXPORT ProcessStatsFixed {
|
||||
//! \~english PID
|
||||
//! \~russian PID
|
||||
int ID = 0;
|
||||
|
||||
//! \~english Parent PID
|
||||
//! \~russian PID родителя
|
||||
int parent_ID = 0;
|
||||
|
||||
//! \~english Group ID
|
||||
//! \~russian ID группы
|
||||
int group_ID = 0;
|
||||
|
||||
//! \~english Session ID
|
||||
//! \~russian ID сессии
|
||||
int session_ID = 0;
|
||||
|
||||
//! \~english Priority
|
||||
//! \~russian Приоритет
|
||||
int priority = 0;
|
||||
|
||||
//! \~english Threads count
|
||||
//! \~russian Количество потоков
|
||||
int threads = 0;
|
||||
|
||||
//! \~english Physical memory in bytes
|
||||
//! \~russian Физическая память в байтах
|
||||
ullong physical_memsize = 0;
|
||||
|
||||
//! \~english Resident memory in bytes
|
||||
//! \~russian Резидентная память в байтах
|
||||
ullong resident_memsize = 0;
|
||||
|
||||
//! \~english Share memory in bytes
|
||||
//! \~russian Разделяемая память в байтах
|
||||
ullong share_memsize = 0;
|
||||
|
||||
//! \~english Virtual memory in bytes
|
||||
//! \~russian Виртуальная память в байтах
|
||||
ullong virtual_memsize = 0;
|
||||
|
||||
//! \~english Data memory in bytes
|
||||
//! \~russian Память данных в байтах
|
||||
ullong data_memsize = 0;
|
||||
|
||||
//! \~english
|
||||
//! \~russian
|
||||
ullong ram_total = 0;
|
||||
|
||||
//! \~english
|
||||
//! \~russian
|
||||
ullong ram_free = 0;
|
||||
|
||||
//! \~english
|
||||
//! \~russian
|
||||
ullong ram_used = 0;
|
||||
|
||||
//! \~english CPU load in kernel space
|
||||
//! \~russian Загрузка CPU в пространстве ядра
|
||||
float cpu_load_system = 0.f;
|
||||
|
||||
//! \~english CPU load in user space
|
||||
//! \~russian Загрузка CPU в пространстве пользователя
|
||||
float cpu_load_user = 0.f;
|
||||
};
|
||||
|
||||
//! \ingroup System
|
||||
//! \~\brief
|
||||
//! \~english Thread statistics (fixed-size fields).
|
||||
//! \~russian Статистика потока (фиксированные поля).
|
||||
struct PIP_EXPORT ThreadStatsFixed {
|
||||
//! \~english TID
|
||||
//! \~russian TID
|
||||
llong id = 0;
|
||||
|
||||
//! \~english Overall live time
|
||||
//! \~russian Полное время жизни
|
||||
PISystemTime work_time;
|
||||
|
||||
//! \~english Busy time in kernel space
|
||||
//! \~russian Время работы в пространстве ядра
|
||||
PISystemTime kernel_time;
|
||||
|
||||
//! \~english Busy time in user space
|
||||
//! \~russian Время работы в пространстве пользователя
|
||||
PISystemTime user_time;
|
||||
|
||||
//! \~english CPU load in kernel space
|
||||
//! \~russian Загрузка CPU в пространстве ядра
|
||||
float cpu_load_kernel = -1.f;
|
||||
|
||||
//! \~english CPU load in user space
|
||||
//! \~russian Загрузка CPU в пространстве пользователя
|
||||
float cpu_load_user = -1.f;
|
||||
|
||||
//! \~english Date and time of creation
|
||||
//! \~russian Дата и время создания
|
||||
PIDateTime created;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
//! \ingroup System
|
||||
//! \~\brief
|
||||
//! \~english Process statistics.
|
||||
//! \~russian Статистика процесса.
|
||||
struct PIP_EXPORT ProcessStats: ProcessStatsFixed {
|
||||
//! \~english Fill human-readable fields
|
||||
//! \~russian Заполнить читаемые поля
|
||||
void makeStrings();
|
||||
|
||||
//! \~english Execution command
|
||||
//! \~russian Команда запуска
|
||||
PIString exec_name;
|
||||
|
||||
//! \~english State
|
||||
//! \~russian Состояние
|
||||
PIString state;
|
||||
|
||||
//! \~english Human-readable physical memory
|
||||
//! \~russian Физическая память в читаемом виде
|
||||
PIString physical_memsize_readable;
|
||||
|
||||
//! \~english Human-readable resident memory
|
||||
//! \~russian Резидентная память в читаемом виде
|
||||
PIString resident_memsize_readable;
|
||||
|
||||
//! \~english Human-readable share memory
|
||||
//! \~russian Разделяемая память в читаемом виде
|
||||
PIString share_memsize_readable;
|
||||
|
||||
//! \~english Human-readable virtual memory
|
||||
//! \~russian Виртуальная память в читаемом виде
|
||||
PIString virtual_memsize_readable;
|
||||
|
||||
//! \~english Human-readable data memory
|
||||
//! \~russian Память данных в читаемом виде
|
||||
PIString data_memsize_readable;
|
||||
};
|
||||
|
||||
//! \ingroup System
|
||||
//! \~\brief
|
||||
//! \~english Thread statistics.
|
||||
//! \~russian Статистика потока.
|
||||
struct PIP_EXPORT ThreadStats: ThreadStatsFixed {
|
||||
//! \~english Name
|
||||
//! \~russian Имя
|
||||
PIString name;
|
||||
};
|
||||
|
||||
#ifndef MICRO_PIP
|
||||
|
||||
//! \~english Starts monitoring of process with PID "pID" and update interval "interval_ms" milliseconds
|
||||
//! \~russian Начинает мониторинг процесса с PID "pID" и интервалом обновления "interval_ms" миллисекунд
|
||||
bool startOnProcess(int pID, int interval_ms = 1000);
|
||||
#endif
|
||||
|
||||
//! \~english Starts monitoring of application process with update interval "interval_ms" milliseconds
|
||||
//! \~russian Начинает мониторинг процесса приложения с интервалом обновления "interval_ms" миллисекунд
|
||||
bool startOnSelf(int interval_ms = 1000);
|
||||
|
||||
//! \~english Stop monitoring
|
||||
//! \~russian Останавливает мониторинг
|
||||
void stop();
|
||||
|
||||
|
||||
//! \~english Returns monitoring process PID
|
||||
//! \~russian Возвращает PID наблюдаемого процесса
|
||||
int pID() const { return pID_; }
|
||||
|
||||
//! \~english Returns monitoring process statistics
|
||||
//! \~russian Возвращает статистику наблюдаемого процесса
|
||||
ProcessStats statistic() const;
|
||||
|
||||
//! \~english Returns monitoring process threads statistics
|
||||
//! \~russian Возвращает статистику потоков наблюдаемого процесса
|
||||
PIVector<ThreadStats> threadsStatistic() const;
|
||||
|
||||
void setStatistic(const ProcessStats & s);
|
||||
|
||||
|
||||
//! \~english
|
||||
//! \~russian
|
||||
static ullong totalRAM();
|
||||
|
||||
//! \~english
|
||||
//! \~russian
|
||||
static ullong freeRAM();
|
||||
|
||||
//! \~english
|
||||
//! \~russian
|
||||
static ullong usedRAM();
|
||||
|
||||
|
||||
private:
|
||||
void run() override;
|
||||
void gatherThread(llong id);
|
||||
float calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old);
|
||||
|
||||
ProcessStats stat;
|
||||
PIVector<ThreadStats> cur_ts;
|
||||
PIMap<llong, ThreadStats> last_tm, cur_tm;
|
||||
PIMap<llong, PIString> tbid;
|
||||
mutable PIMutex stat_mutex;
|
||||
int pID_, page_size, cpu_count, cycle;
|
||||
#ifndef MICRO_PIP
|
||||
PRIVATE_DECLARATION(PIP_EXPORT)
|
||||
#endif
|
||||
|
||||
class PIP_EXPORT Pool {
|
||||
friend class PISystemMonitor;
|
||||
|
||||
public:
|
||||
static Pool * instance();
|
||||
PISystemMonitor * getByPID(int pID);
|
||||
|
||||
private:
|
||||
void add(PISystemMonitor * sm);
|
||||
void remove(PISystemMonitor * sm);
|
||||
PIMap<int, PISystemMonitor *> sysmons;
|
||||
PIMutex mutex;
|
||||
};
|
||||
};
|
||||
|
||||
//! \relatesalso PICout
|
||||
//! \~english Output operator to \a PICout
|
||||
//! \~russian Оператор вывода в \a PICout
|
||||
inline PICout operator<<(PICout s, const PISystemMonitor::ThreadStats & v) {
|
||||
s.saveAndSetControls(0);
|
||||
s << "ThreadInfo(\"" << v.name << "\", created " << v.created << ", work " << v.work_time.toMilliseconds() << " ms"
|
||||
<< ", kernel " << v.kernel_time.toMilliseconds() << " ms"
|
||||
<< ", user " << v.user_time.toMilliseconds() << " ms"
|
||||
<< ")\n";
|
||||
s.restoreControls();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \relatesalso PIBinaryStream
|
||||
//! \~english Store operator.
|
||||
//! \~russian Оператор сохранения.
|
||||
BINARY_STREAM_WRITE(PISystemMonitor::ProcessStats) {
|
||||
s << PIMemoryBlock(&v, sizeof(PISystemMonitor::ProcessStatsFixed)) << v.exec_name << v.state;
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIBinaryStream
|
||||
//! \~english Restore operator.
|
||||
//! \~russian Оператор извлечения.
|
||||
BINARY_STREAM_READ(PISystemMonitor::ProcessStats) {
|
||||
s >> PIMemoryBlock(&v, sizeof(PISystemMonitor::ProcessStatsFixed)) >> v.exec_name >> v.state;
|
||||
v.makeStrings();
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIBinaryStream
|
||||
//! \~english Store operator.
|
||||
//! \~russian Оператор сохранения.
|
||||
BINARY_STREAM_WRITE(PISystemMonitor::ThreadStats) {
|
||||
s << PIMemoryBlock(&v, sizeof(PISystemMonitor::ThreadStatsFixed)) << v.name;
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIBinaryStream
|
||||
//! \~english Restore operator.
|
||||
//! \~russian Оператор извлечения.
|
||||
BINARY_STREAM_READ(PISystemMonitor::ThreadStats) {
|
||||
s >> PIMemoryBlock(&v, sizeof(PISystemMonitor::ThreadStatsFixed)) >> v.name;
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif // PISYSTEMMONITOR_H
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
System tests results (see system_test folder)
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
PIP - Platform Independent Primitives
|
||||
System tests results (see system_test folder)
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pisystemtests.h"
|
||||
@@ -25,22 +25,20 @@
|
||||
|
||||
|
||||
namespace PISystemTests {
|
||||
long time_resolution_ns = 1;
|
||||
long time_elapsed_ns = 0;
|
||||
long usleep_offset_us = 60;
|
||||
|
||||
PISystemTestReader pisystestreader;
|
||||
long time_resolution_ns = 1;
|
||||
long time_elapsed_ns = 0;
|
||||
long usleep_offset_us = 60;
|
||||
|
||||
};
|
||||
PISystemTestReader pisystestreader;
|
||||
|
||||
}; // namespace PISystemTests
|
||||
|
||||
|
||||
PISystemTests::PISystemTestReader::PISystemTestReader() {
|
||||
#if !defined(WINDOWS) && !defined(MICRO_PIP)
|
||||
PIConfig conf(PIStringAscii("/etc/pip.conf"), PIIODevice::ReadOnly);
|
||||
time_resolution_ns = conf.getValue(PIStringAscii("time_resolution_ns"), 1).toLong();
|
||||
time_elapsed_ns = conf.getValue(PIStringAscii("time_elapsed_ns"), 0).toLong();
|
||||
usleep_offset_us = conf.getValue(PIStringAscii("usleep_offset_us"), 60).toLong();
|
||||
time_elapsed_ns = conf.getValue(PIStringAscii("time_elapsed_ns"), 0).toLong();
|
||||
usleep_offset_us = conf.getValue(PIStringAscii("usleep_offset_us"), 60).toLong();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
System tests results (see system_test folder)
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
PIP - Platform Independent Primitives
|
||||
System tests results (see system_test folder)
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License for more details.
|
||||
This program 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PISYSTEMTESTS_H
|
||||
@@ -23,16 +23,16 @@
|
||||
#include "pibase.h"
|
||||
|
||||
namespace PISystemTests {
|
||||
extern PIP_EXPORT long time_resolution_ns;
|
||||
extern PIP_EXPORT long time_elapsed_ns;
|
||||
extern PIP_EXPORT long usleep_offset_us;
|
||||
extern PIP_EXPORT long time_resolution_ns;
|
||||
extern PIP_EXPORT long time_elapsed_ns;
|
||||
extern PIP_EXPORT long usleep_offset_us;
|
||||
|
||||
class PIP_EXPORT PISystemTestReader {
|
||||
public:
|
||||
PISystemTestReader();
|
||||
};
|
||||
class PIP_EXPORT PISystemTestReader {
|
||||
public:
|
||||
PISystemTestReader();
|
||||
};
|
||||
|
||||
extern PIP_EXPORT PISystemTestReader pisystestreader;
|
||||
}
|
||||
extern PIP_EXPORT PISystemTestReader pisystestreader;
|
||||
} // namespace PISystemTests
|
||||
|
||||
#endif // PISYSTEMTESTS_H
|
||||
|
||||
Reference in New Issue
Block a user