From d71432136c315e0656feb42e714a8190965b9d6a Mon Sep 17 00:00:00 2001 From: peri4 Date: Wed, 9 Jun 2021 11:32:28 +0300 Subject: [PATCH 1/3] resurrect and assertions --- libs/main/core/pibytearray.h | 1076 +++++++++-------- .../introspection/piintrospection_server.cpp | 215 ++-- .../introspection/piintrospection_server.h | 122 +- .../piintrospection_server_p.cpp | 494 ++++---- libs/main/system/pisystemmonitor.cpp | 1002 +++++++-------- libs/main/system/pisystemmonitor.h | 288 ++--- utils/system_daemon/main.cpp | 2 +- 7 files changed, 1621 insertions(+), 1578 deletions(-) diff --git a/libs/main/core/pibytearray.h b/libs/main/core/pibytearray.h index 687a4d76..548a073c 100644 --- a/libs/main/core/pibytearray.h +++ b/libs/main/core/pibytearray.h @@ -1,520 +1,556 @@ -/*! \file pibytearray.h - * \brief Byte array -*/ -/* - PIP - Platform Independent Primitives - Byte array - Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@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 . -*/ - -#ifndef PIBYTEARRAY_H -#define PIBYTEARRAY_H - -#include "pichar.h" -#include "pibitarray.h" -#include "pimap.h" -#include "pivector2d.h" - -class PIString; -class PIByteArray; - - -class PIP_EXPORT PIByteArray: public PIDeque -{ -public: - - //! Constructs an empty byte array - PIByteArray() {;} - - PIByteArray(const PIByteArray & o): PIDeque(o) {} - - PIByteArray(PIByteArray && o): PIDeque(std::move(o)) {} - - //! Constructs 0-filled byte array with size "size" - PIByteArray(const uint size) {resize(size);} - - //! Constructs byte array from data "data" and size "size" - PIByteArray(const void * data, const uint size): PIDeque((const uchar*)data, size_t(size)) {} - - //! Constructs byte array with size "size" filled by "t" - PIByteArray(const uint size, uchar t): PIDeque(size, t) {} - - - //! Help struct to store/restore custom blocks of data to/from PIByteArray - struct RawData { - friend PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v); - friend PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v); - public: - //! Constructs data block - RawData(void * data = 0, int size = 0) {d = data; s = size;} - RawData(const RawData & o) {d = o.d; s = o.s;} - //! Constructs data block - RawData(const void * data, const int size) {d = const_cast(data); s = size;} - RawData & operator =(const RawData & o) {d = o.d; s = o.s; return *this;} - private: - void * d; - int s; - }; - - //! Return resized byte array - PIByteArray resized(uint new_size) const {PIByteArray ret(new_size); memcpy(ret.data(), data(), new_size); return ret;} - - //! Convert data to Base 64 and return this byte array - PIByteArray & convertToBase64(); - - //! Convert data from Base 64 and return this byte array - PIByteArray & convertFromBase64(); - - //! Return converted to Base 64 data - PIByteArray toBase64() const; - - //! Return converted from Base 64 data - - PIByteArray & compressRLE(uchar threshold = 192); - PIByteArray & decompressRLE(uchar threshold = 192); - PIByteArray compressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.compressRLE(threshold); return ba;} - PIByteArray decompressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.decompressRLE(threshold); return ba;} - - PIString toString(int base = 16) const; - PIString toHex() const; - - //! Add to the end data "data" with size "size" - PIByteArray & append(const void * data_, int size_) {uint ps = size(); enlarge(size_); memcpy(data(ps), data_, size_); return *this;} - - //! Add to the end byte array "data" - PIByteArray & append(const PIByteArray & data_) {uint ps = size(); enlarge(data_.size_s()); memcpy(data(ps), data_.data(), data_.size()); return *this;} - - //! Add to the end "t" - PIByteArray & append(uchar t) {push_back(t); return *this;} - - //! Returns plain 8-bit checksum - uchar checksumPlain8() const; - - //! Returns plain 32-bit checksum - uint checksumPlain32() const; - - //! Returns hash - uint hash() const; - - void operator =(const PIDeque & d) {resize(d.size()); memcpy(data(), d.data(), d.size());} - - PIByteArray & operator =(const PIByteArray & o) {if (this == &o) return *this; clear(); append(o); return *this;} - - PIByteArray & operator =(PIByteArray && o) {swap(o); return *this;} - - static PIByteArray fromUserInput(PIString str); - static PIByteArray fromHex(PIString str); - static PIByteArray fromBase64(const PIByteArray & base64); - static PIByteArray fromBase64(const PIString & base64); - - - class StreamRef { - public: - StreamRef(PIByteArray & s): ba(s) {} - operator PIByteArray&() {return ba;} - private: - PIByteArray & ba; - }; - -}; - -//! \relatesalso PIByteArray \brief Byte arrays compare operator -inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) { - if (v0.size() == v1.size()) { - for (uint i = 0; i < v0.size(); ++i) - if (v0[i] != v1[i]) - return v0[i] < v1[i]; - return false; - } - return v0.size() < v1.size(); -} - -//! \relatesalso PIByteArray \brief Byte arrays compare operator -inline bool operator ==(PIByteArray & f, PIByteArray & s) { - if (f.size_s() != s.size_s()) - return false; - for (int i = 0; i < f.size_s(); ++i) - if (f[i] != s[i]) - return false; - return true; -} - -//! \relatesalso PIByteArray \brief Byte arrays compare operator -inline bool operator !=(PIByteArray & f, PIByteArray & s) { - if (f.size_s() != s.size_s()) - return true; - for (int i = 0; i < f.size_s(); ++i) - if (f[i] != s[i]) - return true; - return false; -} - -#ifdef PIP_STD_IOSTREAM -//! \relatesalso PIByteArray \brief Output to std::ostream operator -inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba); -#endif - -//! \relatesalso PIByteArray \brief Output to PICout operator -PIP_EXPORT PICout operator <<(PICout s, const PIByteArray & ba); - - - - -// store operators for basic types - - -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const bool v) {s.push_back(v); return s;} - -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const char v) {s.push_back(v); return s;} - -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const uchar v) {s.push_back(v); return s;} - -//! \relatesalso PIByteArray \brief Store operator for any trivial copyable type -template::value, int>::type = 0> -inline PIByteArray::StreamRef operator <<(PIByteArray & s, const T & v) { - int os = s.size_s(); - s.enlarge(sizeof(v)); - memcpy(s.data(os), &v, sizeof(v)); - return s; -} - -//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details -PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v); - -//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details -inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) { - int os = s.size_s(); - if (v.s > 0) { - s.enlarge(v.s); - memcpy(s.data(os), v.d, v.s); - } - return s; -} - -//! \relatesalso PIByteArray \brief Store operator for PIVector of any trivial copyable type -template::value, int>::type = 0, - typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> -inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) { - s << int(v.size_s()); - int os = s.size_s(); - if (v.size_s() > 0) { - s.enlarge(v.size_s()*sizeof(T)); - memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); - } - return s; -} -template::value, int>::type = 0, - typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> -inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) { - s << int(v.size_s()); - for (uint i = 0; i < v.size(); ++i) s << v[i]; - return s; -} - -//! \relatesalso PIByteArray \brief Store operator for PIDeque of any trivial copyable type -template::value, int>::type = 0, - typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> -inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) { - s << int(v.size_s()); - int os = s.size_s(); - if (v.size_s() > 0) { - s.enlarge(v.size_s()*sizeof(T)); - memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); - } - return s; -} -template::value, int>::type = 0, - typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> -inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) { - s << int(v.size_s()); - for (uint i = 0; i < v.size(); ++i) s << v[i]; - return s; -} - -//! \relatesalso PIByteArray \brief Store operator for PIVector2D of any trivial copyable type -template::value, int>::type = 0, - typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> -inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D & v) { - s << int(v.rows()) << int(v.cols()); - int os = s.size_s(); - if (v.size_s() > 0) { - s.enlarge(v.size_s()*sizeof(T)); - memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); - } - return s; -} -template::value, int>::type = 0, - typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> -inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D & v) { - s << int(v.rows()) << int(v.cols()) << v.toPlainVector(); - return s; -} - -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const PIBitArray & v) {s << v.size_ << v.data_; return s;} - -//! \relatesalso PIPair \brief Store operator -template -inline PIByteArray & operator <<(PIByteArray & s, const PIPair & v) {s << v.first << v.second; return s;} - - - - -// restore operators for basic types - - -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, bool & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} - -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, char & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} - -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} - -//! \relatesalso PIByteArray \brief Restore operator for any trivial copyable type -template::value, int>::type = 0> -inline PIByteArray::StreamRef operator >>(PIByteArray & s, T & v) { - assert(s.size() >= sizeof(v)); - memcpy((void*)(&v), s.data(), sizeof(v)); - s.remove(0, sizeof(v)); - return s; -} - -//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details -PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIByteArray & v); - -//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details -inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) { - assert(s.size_s() >= v.s); - if (v.s > 0) { - memcpy((void*)(v.d), s.data(), v.s); - s.remove(0, v.s); - } - return s; -} - -//! \relatesalso PIByteArray \brief Restore operator for PIVector of any trivial copyable type -template::value, int>::type = 0, - typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> -inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) { - assert(s.size_s() >= 4); - int sz; s >> sz; - v._resizeRaw(sz); - if (sz > 0) { - memcpy(v.data(), s.data(), sz*sizeof(T)); - s.remove(0, sz*sizeof(T)); - } - return s; -} -template::value, int>::type = 0, - typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> -inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) { - assert(s.size_s() >= 4); - int sz; s >> sz; - v.resize(sz); - for (int i = 0; i < sz; ++i) s >> v[i]; - return s; -} - -//! \relatesalso PIByteArray \brief Restore operator for PIDeque of any trivial copyable type -template::value, int>::type = 0, - typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> -inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) { - assert(s.size_s() >= 4); - int sz; s >> sz; - v._resizeRaw(sz); - if (sz > 0) { - memcpy(v.data(), s.data(), sz*sizeof(T)); - s.remove(0, sz*sizeof(T)); - } - return s; -} -template::value, int>::type = 0, - typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> -inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) { - assert(s.size_s() >= 4); - int sz; s >> sz; - v.resize(sz); - for (int i = 0; i < sz; ++i) s >> v[i]; - return s; -} - -//! \relatesalso PIByteArray \brief Restore operator for PIVector2D of any trivial copyable type -template::value, int>::type = 0, - typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> -inline PIByteArray & operator >>(PIByteArray & s, PIVector2D & v) { - assert(s.size_s() >= 8); - int r, c; s >> r >> c; - v._resizeRaw(r, c); - int sz = r*c; - if (sz > 0) { - memcpy(v.data(), s.data(), sz*sizeof(T)); - s.remove(0, sz*sizeof(T)); - } - return s; -} -template::value, int>::type = 0, - typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> -inline PIByteArray & operator >>(PIByteArray & s, PIVector2D & v) { - assert(s.size_s() >= 8); - int r,c; - PIVector tmp; - s >> r >> c >> tmp; - v = PIVector2D(r, c, tmp); - return s; -} - -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, PIBitArray & v) {assert(s.size_s() >= 8); s >> v.size_ >> v.data_; return s;} - -//! \relatesalso PIPair \brief Restore operator -template -inline PIByteArray & operator >>(PIByteArray & s, PIPair & v) {s >> v.first >> v.second; return s;} - - - - -// store operators for complex types - - -//! \relatesalso PIByteArray \brief Store operator for PIVector of any compound type -template::value, int>::type = 0> -inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) { - s << int(v.size_s()); - for (uint i = 0; i < v.size(); ++i) s << v[i]; - return s; -} - -//! \relatesalso PIByteArray \brief Store operator for PIDeque of any compound type -template::value, int>::type = 0> -inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) { - s << int(v.size_s()); - for (uint i = 0; i < v.size(); ++i) s << v[i]; - return s; -} - -//! \relatesalso PIByteArray \brief Store operator for PIVector2D of any compound type -template::value, int>::type = 0> -inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D & v) { - s << int(v.rows()) << int(v.cols()) << v.toPlainVector(); - return s; -} - - - - -// restore operators for complex types - - -//! \relatesalso PIByteArray \brief Restore operator for PIVector of any compound type -template::value, int>::type = 0> -inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) { - assert(s.size_s() >= 4); - int sz; s >> sz; - v.resize(sz); - for (int i = 0; i < sz; ++i) s >> v[i]; - return s; -} - -//! \relatesalso PIByteArray \brief Restore operator for PIDeque of any compound type -template::value, int>::type = 0> -inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) { - assert(s.size_s() >= 4); - int sz; s >> sz; - v.resize(sz); - for (int i = 0; i < sz; ++i) s >> v[i]; - return s; -} - -//! \relatesalso PIByteArray \brief Restore operator for PIVector2D of any compound type -template::value, int>::type = 0> -inline PIByteArray & operator >>(PIByteArray & s, PIVector2D & v) { - assert(s.size_s() >= 8); - int r,c; - PIVector tmp; - s >> r >> c >> tmp; - v = PIVector2D(r, c, tmp); - return s; -} - - - - -// other types - - -template -inline PIByteArray & operator <<(PIByteArray & s, const PIMap & v) { - s << int(v.pim_index.size_s()); - for (uint i = 0; i < v.size(); ++i) - s << int(v.pim_index[i].index) << v.pim_index[i].key; - s << v.pim_content; - return s; -} - - -template -inline PIByteArray & operator >>(PIByteArray & s, PIMap & v) { - assert(s.size_s() >= 4); - int sz; s >> sz; v.pim_index.resize(sz); - int ind = 0; - for (int i = 0; i < sz; ++i) { - s >> ind >> v.pim_index[i].key; - v.pim_index[i].index = ind; - } - s >> v.pim_content; - if (v.pim_content.size_s() != v.pim_index.size_s()) { - piCout << "Warning: loaded invalid PIMap, clear"; - v.clear(); - } - return s; -} - - - -template::value, int>::type = 0> -inline PIByteArray & operator <<(PIByteArray & s, const T & ) { - static_assert(std::is_trivially_copyable::value, "[PIByteArray] Error: using undeclared operator << for complex type!"); - return s; -} - -template::value, int>::type = 0> -inline PIByteArray & operator >>(PIByteArray & s, T & ) { - static_assert(std::is_trivially_copyable::value, "[PIByteArray] Error: using undeclared operator >> for complex type!"); - return s; -} - -template<> inline uint piHash(const PIByteArray & ba) {return ba.hash();} -template<> inline void piSwap(PIByteArray & f, PIByteArray & s) {f.swap(s);} - - -#endif // PIBYTEARRAY_H +/*! \file pibytearray.h + * \brief Byte array +*/ +/* + PIP - Platform Independent Primitives + Byte array + Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@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 . +*/ + +#ifndef PIBYTEARRAY_H +#define PIBYTEARRAY_H + +#include "pichar.h" +#include "pibitarray.h" +#include "pimap.h" +#include "pivector2d.h" + +class PIString; +class PIByteArray; + + +class PIP_EXPORT PIByteArray: public PIDeque +{ +public: + + //! Constructs an empty byte array + PIByteArray() {;} + + PIByteArray(const PIByteArray & o): PIDeque(o) {} + + PIByteArray(PIByteArray && o): PIDeque(std::move(o)) {} + + //! Constructs 0-filled byte array with size "size" + PIByteArray(const uint size) {resize(size);} + + //! Constructs byte array from data "data" and size "size" + PIByteArray(const void * data, const uint size): PIDeque((const uchar*)data, size_t(size)) {} + + //! Constructs byte array with size "size" filled by "t" + PIByteArray(const uint size, uchar t): PIDeque(size, t) {} + + + //! Help struct to store/restore custom blocks of data to/from PIByteArray + struct RawData { + friend PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v); + friend PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v); + public: + //! Constructs data block + RawData(void * data = 0, int size = 0) {d = data; s = size;} + RawData(const RawData & o) {d = o.d; s = o.s;} + //! Constructs data block + RawData(const void * data, const int size) {d = const_cast(data); s = size;} + RawData & operator =(const RawData & o) {d = o.d; s = o.s; return *this;} + private: + void * d; + int s; + }; + + //! Return resized byte array + PIByteArray resized(uint new_size) const {PIByteArray ret(new_size); memcpy(ret.data(), data(), new_size); return ret;} + + //! Convert data to Base 64 and return this byte array + PIByteArray & convertToBase64(); + + //! Convert data from Base 64 and return this byte array + PIByteArray & convertFromBase64(); + + //! Return converted to Base 64 data + PIByteArray toBase64() const; + + //! Return converted from Base 64 data + + PIByteArray & compressRLE(uchar threshold = 192); + PIByteArray & decompressRLE(uchar threshold = 192); + PIByteArray compressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.compressRLE(threshold); return ba;} + PIByteArray decompressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.decompressRLE(threshold); return ba;} + + PIString toString(int base = 16) const; + PIString toHex() const; + + //! Add to the end data "data" with size "size" + PIByteArray & append(const void * data_, int size_) {uint ps = size(); enlarge(size_); memcpy(data(ps), data_, size_); return *this;} + + //! Add to the end byte array "data" + PIByteArray & append(const PIByteArray & data_) {uint ps = size(); enlarge(data_.size_s()); memcpy(data(ps), data_.data(), data_.size()); return *this;} + + //! Add to the end "t" + PIByteArray & append(uchar t) {push_back(t); return *this;} + + //! Returns plain 8-bit checksum + uchar checksumPlain8() const; + + //! Returns plain 32-bit checksum + uint checksumPlain32() const; + + //! Returns hash + uint hash() const; + + void operator =(const PIDeque & d) {resize(d.size()); memcpy(data(), d.data(), d.size());} + + PIByteArray & operator =(const PIByteArray & o) {if (this == &o) return *this; clear(); append(o); return *this;} + + PIByteArray & operator =(PIByteArray && o) {swap(o); return *this;} + + static PIByteArray fromUserInput(PIString str); + static PIByteArray fromHex(PIString str); + static PIByteArray fromBase64(const PIByteArray & base64); + static PIByteArray fromBase64(const PIString & base64); + + + class StreamRef { + public: + StreamRef(PIByteArray & s): ba(s) {} + operator PIByteArray&() {return ba;} + private: + PIByteArray & ba; + }; + +}; + +//! \relatesalso PIByteArray \brief Byte arrays compare operator +inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) { + if (v0.size() == v1.size()) { + for (uint i = 0; i < v0.size(); ++i) + if (v0[i] != v1[i]) + return v0[i] < v1[i]; + return false; + } + return v0.size() < v1.size(); +} + +//! \relatesalso PIByteArray \brief Byte arrays compare operator +inline bool operator ==(PIByteArray & f, PIByteArray & s) { + if (f.size_s() != s.size_s()) + return false; + for (int i = 0; i < f.size_s(); ++i) + if (f[i] != s[i]) + return false; + return true; +} + +//! \relatesalso PIByteArray \brief Byte arrays compare operator +inline bool operator !=(PIByteArray & f, PIByteArray & s) { + if (f.size_s() != s.size_s()) + return true; + for (int i = 0; i < f.size_s(); ++i) + if (f[i] != s[i]) + return true; + return false; +} + +#ifdef PIP_STD_IOSTREAM +//! \relatesalso PIByteArray \brief Output to std::ostream operator +inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba); +#endif + +//! \relatesalso PIByteArray \brief Output to PICout operator +PIP_EXPORT PICout operator <<(PICout s, const PIByteArray & ba); + + + + +// store operators for basic types + + +//! \relatesalso PIByteArray \brief Store operator +inline PIByteArray & operator <<(PIByteArray & s, const bool v) {s.push_back(v); return s;} + +//! \relatesalso PIByteArray \brief Store operator +inline PIByteArray & operator <<(PIByteArray & s, const char v) {s.push_back(v); return s;} + +//! \relatesalso PIByteArray \brief Store operator +inline PIByteArray & operator <<(PIByteArray & s, const uchar v) {s.push_back(v); return s;} + +//! \relatesalso PIByteArray \brief Store operator for any trivial copyable type +template::value, int>::type = 0> +inline PIByteArray::StreamRef operator <<(PIByteArray & s, const T & v) { + int os = s.size_s(); + s.enlarge(sizeof(v)); + memcpy(s.data(os), &v, sizeof(v)); + return s; +} + +//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details +PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v); + +//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details +inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) { + int os = s.size_s(); + if (v.s > 0) { + s.enlarge(v.s); + memcpy(s.data(os), v.d, v.s); + } + return s; +} + +//! \relatesalso PIByteArray \brief Store operator for PIVector of any trivial copyable type +template::value, int>::type = 0, + typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) { + s << int(v.size_s()); + int os = s.size_s(); + if (v.size_s() > 0) { + s.enlarge(v.size_s()*sizeof(T)); + memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); + } + return s; +} +template::value, int>::type = 0, + typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) { + s << int(v.size_s()); + for (uint i = 0; i < v.size(); ++i) s << v[i]; + return s; +} + +//! \relatesalso PIByteArray \brief Store operator for PIDeque of any trivial copyable type +template::value, int>::type = 0, + typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) { + s << int(v.size_s()); + int os = s.size_s(); + if (v.size_s() > 0) { + s.enlarge(v.size_s()*sizeof(T)); + memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); + } + return s; +} +template::value, int>::type = 0, + typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) { + s << int(v.size_s()); + for (uint i = 0; i < v.size(); ++i) s << v[i]; + return s; +} + +//! \relatesalso PIByteArray \brief Store operator for PIVector2D of any trivial copyable type +template::value, int>::type = 0, + typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D & v) { + s << int(v.rows()) << int(v.cols()); + int os = s.size_s(); + if (v.size_s() > 0) { + s.enlarge(v.size_s()*sizeof(T)); + memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); + } + return s; +} +template::value, int>::type = 0, + typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D & v) { + s << int(v.rows()) << int(v.cols()) << v.toPlainVector(); + return s; +} + +//! \relatesalso PIByteArray \brief Store operator +inline PIByteArray & operator <<(PIByteArray & s, const PIBitArray & v) {s << v.size_ << v.data_; return s;} + +//! \relatesalso PIPair \brief Store operator +template +inline PIByteArray & operator <<(PIByteArray & s, const PIPair & v) {s << v.first << v.second; return s;} + + + + +// restore operators for basic types + + +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, bool & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} + +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, char & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} + +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} + +//! \relatesalso PIByteArray \brief Restore operator for any trivial copyable type +template::value, int>::type = 0> +inline PIByteArray::StreamRef operator >>(PIByteArray & s, T & v) { + if (s.size() < sizeof(v)) { + printf("error with %s\n", typeid(T).name()); + assert(s.size() >= sizeof(v)); + } + memcpy((void*)(&v), s.data(), sizeof(v)); + s.remove(0, sizeof(v)); + return s; +} + +//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details +PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIByteArray & v); + +//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details +inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) { + if (s.size_s() < v.s) { + printf("error with RawData %d < %d\n", s.size_s(), v.s); + assert(s.size_s() >= v.s); + } + if (v.s > 0) { + memcpy((void*)(v.d), s.data(), v.s); + s.remove(0, v.s); + } + return s; +} + +//! \relatesalso PIByteArray \brief Restore operator for PIVector of any trivial copyable type +template::value, int>::type = 0, + typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) { + if (s.size_s() < 4) { + printf("error with PIVector<%s>\n", typeid(T).name()); + assert(s.size_s() >= 4); + } + int sz; s >> sz; + v._resizeRaw(sz); + if (sz > 0) { + memcpy(v.data(), s.data(), sz*sizeof(T)); + s.remove(0, sz*sizeof(T)); + } + return s; +} +template::value, int>::type = 0, + typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) { + if (s.size_s() < 4) { + printf("error with PIVector<%s>\n", typeid(T).name()); + assert(s.size_s() >= 4); + } + int sz; s >> sz; + v.resize(sz); + for (int i = 0; i < sz; ++i) s >> v[i]; + return s; +} + +//! \relatesalso PIByteArray \brief Restore operator for PIDeque of any trivial copyable type +template::value, int>::type = 0, + typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) { + if (s.size_s() < 4) { + printf("error with PIDeque<%s>\n", typeid(T).name()); + assert(s.size_s() >= 4); + } + int sz; s >> sz; + v._resizeRaw(sz); + if (sz > 0) { + memcpy(v.data(), s.data(), sz*sizeof(T)); + s.remove(0, sz*sizeof(T)); + } + return s; +} +template::value, int>::type = 0, + typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) { + if (s.size_s() < 4) { + printf("error with PIDeque<%s>\n", typeid(T).name()); + assert(s.size_s() >= 4); + } + int sz; s >> sz; + v.resize(sz); + for (int i = 0; i < sz; ++i) s >> v[i]; + return s; +} + +//! \relatesalso PIByteArray \brief Restore operator for PIVector2D of any trivial copyable type +template::value, int>::type = 0, + typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIVector2D & v) { + if (s.size_s() < 8) { + printf("error with PIVecto2Dr<%s>\n", typeid(T).name()); + assert(s.size_s() >= 8); + } + int r, c; s >> r >> c; + v._resizeRaw(r, c); + int sz = r*c; + if (sz > 0) { + memcpy(v.data(), s.data(), sz*sizeof(T)); + s.remove(0, sz*sizeof(T)); + } + return s; +} +template::value, int>::type = 0, + typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIVector2D & v) { + if (s.size_s() < 8) { + printf("error with PIVecto2Dr<%s>\n", typeid(T).name()); + assert(s.size_s() >= 8); + } + int r,c; + PIVector tmp; + s >> r >> c >> tmp; + v = PIVector2D(r, c, tmp); + return s; +} + +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, PIBitArray & v) {assert(s.size_s() >= 8); s >> v.size_ >> v.data_; return s;} + +//! \relatesalso PIPair \brief Restore operator +template +inline PIByteArray & operator >>(PIByteArray & s, PIPair & v) {s >> v.first >> v.second; return s;} + + + + +// store operators for complex types + + +//! \relatesalso PIByteArray \brief Store operator for PIVector of any compound type +template::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) { + s << int(v.size_s()); + for (uint i = 0; i < v.size(); ++i) s << v[i]; + return s; +} + +//! \relatesalso PIByteArray \brief Store operator for PIDeque of any compound type +template::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) { + s << int(v.size_s()); + for (uint i = 0; i < v.size(); ++i) s << v[i]; + return s; +} + +//! \relatesalso PIByteArray \brief Store operator for PIVector2D of any compound type +template::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D & v) { + s << int(v.rows()) << int(v.cols()) << v.toPlainVector(); + return s; +} + + + + +// restore operators for complex types + + +//! \relatesalso PIByteArray \brief Restore operator for PIVector of any compound type +template::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) { + if (s.size_s() < 4) { + printf("error with PIVector<%s>\n", typeid(T).name()); + assert(s.size_s() >= 4); + } + int sz; s >> sz; + v.resize(sz); + for (int i = 0; i < sz; ++i) s >> v[i]; + return s; +} + +//! \relatesalso PIByteArray \brief Restore operator for PIDeque of any compound type +template::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) { + if (s.size_s() < 4) { + printf("error with PIDeque<%s>\n", typeid(T).name()); + assert(s.size_s() >= 4); + } + int sz; s >> sz; + v.resize(sz); + for (int i = 0; i < sz; ++i) s >> v[i]; + return s; +} + +//! \relatesalso PIByteArray \brief Restore operator for PIVector2D of any compound type +template::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIVector2D & v) { + if (s.size_s() < 8) { + printf("error with PIVecto2Dr<%s>\n", typeid(T).name()); + assert(s.size_s() >= 8); + } + int r,c; + PIVector tmp; + s >> r >> c >> tmp; + v = PIVector2D(r, c, tmp); + return s; +} + + + + +// other types + + +template +inline PIByteArray & operator <<(PIByteArray & s, const PIMap & v) { + s << int(v.pim_index.size_s()); + for (uint i = 0; i < v.size(); ++i) + s << int(v.pim_index[i].index) << v.pim_index[i].key; + s << v.pim_content; + return s; +} + + +template +inline PIByteArray & operator >>(PIByteArray & s, PIMap & v) { + if (s.size_s() < 4) { + printf("error with PIMap<%s, %s>\n", typeid(Key).name(), typeid(T).name()); + assert(s.size_s() >= 4); + } + int sz; s >> sz; v.pim_index.resize(sz); + int ind = 0; + for (int i = 0; i < sz; ++i) { + s >> ind >> v.pim_index[i].key; + v.pim_index[i].index = ind; + } + s >> v.pim_content; + if (v.pim_content.size_s() != v.pim_index.size_s()) { + piCout << "Warning: loaded invalid PIMap, clear"; + v.clear(); + } + return s; +} + + + +template::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const T & ) { + static_assert(std::is_trivially_copyable::value, "[PIByteArray] Error: using undeclared operator << for complex type!"); + return s; +} + +template::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, T & ) { + static_assert(std::is_trivially_copyable::value, "[PIByteArray] Error: using undeclared operator >> for complex type!"); + return s; +} + +template<> inline uint piHash(const PIByteArray & ba) {return ba.hash();} +template<> inline void piSwap(PIByteArray & f, PIByteArray & s) {f.swap(s);} + + +#endif // PIBYTEARRAY_H diff --git a/libs/main/introspection/piintrospection_server.cpp b/libs/main/introspection/piintrospection_server.cpp index 2ea2a85f..6275d91d 100644 --- a/libs/main/introspection/piintrospection_server.cpp +++ b/libs/main/introspection/piintrospection_server.cpp @@ -1,104 +1,111 @@ -/* - PIP - Platform Independent Primitives - Introspection module - 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 . -*/ - -#ifdef PIP_INTROSPECTION - -#include "piintrospection_server.h" -#include "piintrospection_server_p.h" -#include "piprocess.h" -#include "pichunkstream.h" - - -PRIVATE_DEFINITION_START(PIIntrospectionServer) - PIIntrospection::ProcessInfo process_info; -PRIVATE_DEFINITION_END(PIIntrospectionServer) - - -PIIntrospectionServer::PIIntrospectionServer(): PIPeer(genName()) { - PRIVATE->process_info = PIIntrospection::getInfo(); - sysmon = 0; -} - - -PIIntrospectionServer::~PIIntrospectionServer() { - PIPeer::stop(); - if (sysmon) - if (sysmon->property("__iserver__").toBool()) - delete sysmon; - sysmon = 0; -} - - -void PIIntrospectionServer::start() { - if (!sysmon) { - sysmon = PISystemMonitor::Pool::instance()->getByPID(PIProcess::currentPID()); - if (sysmon) { - piCoutObj << "using existing sysmon"; - CONNECTU(sysmon, deleted, this, sysmonDeleted); - } else { - piCoutObj << "create own sysmon"; - sysmon = new PISystemMonitor(); - sysmon->setProperty("__iserver__", true); - sysmon->startOnSelf(); - } - } - PIPeer::start(); -} - - -PIString PIIntrospectionServer::genName() { - randomize(); - return "__introspection__server_" + PIString::fromNumber(randomi() % 1000); -} - - -void PIIntrospectionServer::dataReceived(const PIString & from, const PIByteArray & data) { - if (data.size() < 8) return; - PIByteArray rba(data); - uint _sign(0); rba >> _sign; - if (_sign != PIIntrospection::sign) return; - PIIntrospection::RequiredInfo ri; - rba >> ri; - PIChunkStream cs; - if (ri.types[PIIntrospection::itInfo]) - cs.add(PIIntrospection::itInfo, PIIntrospection::packInfo()); - if (ri.types[PIIntrospection::itProcStat]) { - sysmon_mutex.lock(); - cs.add(PIIntrospection::itProcStat, PIIntrospection::packProcStat(sysmon)); - sysmon_mutex.unlock(); - } - if (ri.types[PIIntrospection::itContainers]) - cs.add(PIIntrospection::itContainers, PIIntrospection::packContainers()); - if (ri.types[PIIntrospection::itObjects]) - cs.add(PIIntrospection::itObjects, PIIntrospection::packObjects()); - if (ri.types[PIIntrospection::itThreads]) - cs.add(PIIntrospection::itThreads, PIIntrospection::packThreads()); - PIByteArray ba; - ba << PIIntrospection::sign; - ba.append(cs.data()); - send(from, ba); -} - - -void PIIntrospectionServer::sysmonDeleted() { - PIMutexLocker _ml(sysmon_mutex); - sysmon = 0; -} - -#endif // PIP_INTROSPECTION +/* + PIP - Platform Independent Primitives + Introspection module + 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 . +*/ + +#ifdef PIP_INTROSPECTION + +#include "piintrospection_server.h" +#include "piintrospection_server_p.h" +#include "piprocess.h" +#include "pichunkstream.h" + + +PRIVATE_DEFINITION_START(PIIntrospectionServer) + PIIntrospection::ProcessInfo process_info; +PRIVATE_DEFINITION_END(PIIntrospectionServer) + + +PIIntrospectionServer::PIIntrospectionServer(): PIPeer(genName()) { + PRIVATE->process_info = PIIntrospection::getInfo(); + sysmon = 0; +} + + +PIIntrospectionServer::~PIIntrospectionServer() { + PIPeer::stop(); + if (sysmon) + if (sysmon->property("__iserver__").toBool()) + delete sysmon; + sysmon = 0; +} + + +PIIntrospectionServer * PIIntrospectionServer::instance() { + static PIIntrospectionServer ret; + return &ret; +} + + +void PIIntrospectionServer::start(const PIString & server_name) { + if (!sysmon) { + sysmon = PISystemMonitor::Pool::instance()->getByPID(PIProcess::currentPID()); + if (sysmon) { + piCoutObj << "using existing sysmon"; + CONNECTU(sysmon, deleted, this, sysmonDeleted); + } else { + piCoutObj << "create own sysmon"; + sysmon = new PISystemMonitor(); + sysmon->setProperty("__iserver__", true); + sysmon->startOnSelf(); + } + } + changeName(server_name + genName()); + PIPeer::start(); +} + + +PIString PIIntrospectionServer::genName() { + randomize(); + return "__introspection__server_" + PIString::fromNumber(randomi() % 1000); +} + + +void PIIntrospectionServer::dataReceived(const PIString & from, const PIByteArray & data) { + if (data.size() < 8) return; + PIByteArray rba(data); + uint _sign(0); rba >> _sign; + if (_sign != PIIntrospection::sign) return; + PIIntrospection::RequiredInfo ri; + rba >> ri; + PIChunkStream cs; + if (ri.types[PIIntrospection::itInfo]) + cs.add(PIIntrospection::itInfo, PIIntrospection::packInfo()); + if (ri.types[PIIntrospection::itProcStat]) { + sysmon_mutex.lock(); + cs.add(PIIntrospection::itProcStat, PIIntrospection::packProcStat(sysmon)); + sysmon_mutex.unlock(); + } + if (ri.types[PIIntrospection::itContainers]) + cs.add(PIIntrospection::itContainers, PIIntrospection::packContainers()); + if (ri.types[PIIntrospection::itObjects]) + cs.add(PIIntrospection::itObjects, PIIntrospection::packObjects()); + if (ri.types[PIIntrospection::itThreads]) + cs.add(PIIntrospection::itThreads, PIIntrospection::packThreads()); + PIByteArray ba; + ba << PIIntrospection::sign; + ba.append(cs.data()); + send(from, ba); +} + + +void PIIntrospectionServer::sysmonDeleted() { + PIMutexLocker _ml(sysmon_mutex); + sysmon = 0; +} + +#endif // PIP_INTROSPECTION diff --git a/libs/main/introspection/piintrospection_server.h b/libs/main/introspection/piintrospection_server.h index 19b5f655..31b2620a 100644 --- a/libs/main/introspection/piintrospection_server.h +++ b/libs/main/introspection/piintrospection_server.h @@ -1,61 +1,61 @@ -/* - PIP - Platform Independent Primitives - Introspection module - 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 . -*/ - -#ifndef PIINTROSPECTION_SERVER_H -#define PIINTROSPECTION_SERVER_H - - -#include "pipeer.h" - -#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION) - -class PIIntrospectionServer; -class PISystemMonitor; - -# define PIINTROSPECTION_SERVER (PIIntrospectionServer::instance()) -# define PIINTROSPECTION_START PIINTROSPECTION_SERVER->start(); - -class PIP_EXPORT PIIntrospectionServer: public PIPeer { - PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer) -public: - static PIIntrospectionServer * instance() {static PIIntrospectionServer ret; return &ret;} - - void start(); - -private: - PIIntrospectionServer(); - ~PIIntrospectionServer(); - NO_COPY_CLASS(PIIntrospectionServer) - - PIString genName(); - virtual void dataReceived(const PIString & from, const PIByteArray & data); - EVENT_HANDLER(void, sysmonDeleted); - - PRIVATE_DECLARATION - PITimer itimer; - PISystemMonitor * sysmon; - PIMutex sysmon_mutex; - -}; - -#else -# define PIINTROSPECTION_START -#endif - -#endif // PIINTROSPECTION_SERVER_H +/* + PIP - Platform Independent Primitives + Introspection module + 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 . +*/ + +#ifndef PIINTROSPECTION_SERVER_H +#define PIINTROSPECTION_SERVER_H + + +#include "pipeer.h" + +#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION) + +class PIIntrospectionServer; +class PISystemMonitor; + +# define PIINTROSPECTION_SERVER (PIIntrospectionServer::instance()) +# define PIINTROSPECTION_START(name) PIINTROSPECTION_SERVER->start(#name); + +class PIP_EXPORT PIIntrospectionServer: public PIPeer { + PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer) +public: + static PIIntrospectionServer * instance(); + + void start(const PIString & server_name); + +private: + PIIntrospectionServer(); + ~PIIntrospectionServer(); + NO_COPY_CLASS(PIIntrospectionServer) + + PIString genName(); + virtual void dataReceived(const PIString & from, const PIByteArray & data); + EVENT_HANDLER(void, sysmonDeleted); + + PRIVATE_DECLARATION(PIP_EXPORT) + PITimer itimer; + PISystemMonitor * sysmon; + PIMutex sysmon_mutex; + +}; + +#else +# define PIINTROSPECTION_START(name) +#endif + +#endif // PIINTROSPECTION_SERVER_H diff --git a/libs/main/introspection/piintrospection_server_p.cpp b/libs/main/introspection/piintrospection_server_p.cpp index f0aee35c..bcdcd6d8 100644 --- a/libs/main/introspection/piintrospection_server_p.cpp +++ b/libs/main/introspection/piintrospection_server_p.cpp @@ -1,247 +1,247 @@ -/* - PIP - Platform Independent Primitives - Introspection module - Base server structs - 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 . -*/ - -#include "piintrospection_server_p.h" -#include "pichunkstream.h" -#include "piinit.h" -#include "pisysteminfo.h" -#include "piobject.h" - - -const uint PIIntrospection::sign = 0x0F1C2B3A; - - -PIIntrospection::RequiredInfo::RequiredInfo() { - types = itInfo; -} - - -PIIntrospection::ProcessInfo::ProcessInfo() { - processorsCount = 0; -} - - -PIIntrospection::ObjectInfo::ObjectInfo() { - queued_events = 0; -} - - -PIIntrospection::ProcessInfo PIIntrospection::getInfo() { - PIIntrospection::ProcessInfo ret; - PISystemInfo * si = PISystemInfo::instance(); - ret.architecture = si->architecture; - ret.execCommand = si->execCommand; - ret.execDateTime = si->execDateTime; - ret.hostname = si->hostname; - ret.OS_name = si->OS_name; - ret.OS_version = si->OS_version; - ret.processorsCount = si->processorsCount; - ret.user = si->user; - ret.build_options = PIInit::buildOptions(); - return ret; -} - - -PIVector PIIntrospection::getObjects() { - PIVector ret; - PIObject::mutexObjects().lock(); - const PIVector & ao(PIObject::objects()); - ret.resize(ao.size()); - for (int i = 0; i < ao.size_s(); ++i) { - ret[i].classname = PIStringAscii(ao[i]->className()); - ret[i].name = ao[i]->name(); - ret[i].properties = ao[i]->properties(); - ret[i].parents = ao[i]->scopeList(); - ao[i]->mutex_queue.lock(); - ret[i].queued_events = ao[i]->events_queue.size_s(); - ao[i]->mutex_queue.unlock(); - } - PIObject::mutexObjects().unlock(); - return ret; -} - - -PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::RequiredInfo & v) { - PIChunkStream cs; - cs.add(1, v.types); - b << cs.data(); - return b; -} - - -PIByteArray & operator >>(PIByteArray & b, PIIntrospection::RequiredInfo & v) { - PIByteArray csba; b >> csba; - PIChunkStream cs(csba); - while (!cs.atEnd()) { - switch (cs.read()) { - case 1: cs.get(v.types); break; - default: break; - } - } - return b; -} - - -PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ProcessInfo & v) { - PIChunkStream cs; - cs.add(1, v.architecture).add(2, v.execCommand).add(3, v.execDateTime).add(4, v.hostname).add(5, v.OS_name) - .add(6, v.OS_version).add(7, v.processorsCount).add(8, v.user).add(9, v.build_options); - b << cs.data(); - return b; -} - - -PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ProcessInfo & v) { - PIByteArray csba; b >> csba; - PIChunkStream cs(csba); - while (!cs.atEnd()) { - switch (cs.read()) { - case 1: cs.get(v.architecture); break; - case 2: cs.get(v.execCommand); break; - case 3: cs.get(v.execDateTime); break; - case 4: cs.get(v.hostname); break; - case 5: cs.get(v.OS_name); break; - case 6: cs.get(v.OS_version); break; - case 7: cs.get(v.processorsCount); break; - case 8: cs.get(v.user); break; - case 9: cs.get(v.build_options); break; - default: break; - } - } - return b; -} - - -PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ObjectInfo & v) { - PIChunkStream cs; - cs.add(1, v.classname).add(2, v.name).add(3, v.parents).add(4, v.properties).add(5, v.queued_events); - b << cs.data(); - return b; -} - - -PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ObjectInfo & v) { - PIByteArray csba; b >> csba; - PIChunkStream cs(csba); - while (!cs.atEnd()) { - switch (cs.read()) { - case 1: cs.get(v.classname); break; - case 2: cs.get(v.name); break; - case 3: cs.get(v.parents); break; - case 4: cs.get(v.properties); break; - case 5: cs.get(v.queued_events); break; - default: break; - } - } - return b; -} - - - - -PIByteArray PIIntrospection::packInfo() { - PIByteArray ret; - ret << getInfo(); - return ret; -} - - -void PIIntrospection::unpackInfo(PIByteArray & ba, PIIntrospection::ProcessInfo & info) { - ba >> info; -} - - -PIByteArray PIIntrospection::packProcStat(PISystemMonitor * sm) { - ProcessStat ps; - if (sm) { - ps.proc = sm->statistic(); - ps.threads = sm->threadsStatistic(); - } - PIByteArray ret; - ret << ps.proc << ps.threads; - return ret; -} - - -void PIIntrospection::unpackProcStat(PIByteArray & ba, PIIntrospection::ProcessStat & info) { - ba >> info.proc >> info.threads; -} - - -PIByteArray PIIntrospection::packContainers() { - PIByteArray ret; - PIVector data; - PIIntrospectionContainers * p = 0; -#ifdef PIP_INTROSPECTION - p = PIINTROSPECTION_CONTAINERS->p; -#endif - if (p) { - data = p->getInfo(); - } - ret << data; - return ret; -} - - -void PIIntrospection::unpackContainers(PIByteArray & ba, PIVector & data) { - data.clear(); - ba >> data; -} - - -PIByteArray PIIntrospection::packThreads() { - PIByteArray ret; - PIIntrospectionThreads * p = 0; -#ifdef PIP_INTROSPECTION - p = PIINTROSPECTION_THREADS->p; -#endif - if (p) { - p->mutex.lock(); - PIMap & tm(p->threads); - auto it = tm.makeIterator(); - while (it.next()) { - it.valueRef().classname = PIStringAscii(it.key()->className()); - it.valueRef().name = it.key()->name(); - } - ret << tm.values(); - p->mutex.unlock(); - } else { - ret << PIVector(); - } - return ret; -} - - -void PIIntrospection::unpackThreads(PIByteArray & ba, PIVector & threads) { - threads.clear(); - ba >> threads; -} - - -PIByteArray PIIntrospection::packObjects() { - PIByteArray ret; - ret << getObjects(); - return ret; -} - - -void PIIntrospection::unpackObjects(PIByteArray & ba, PIVector & objects) { - objects.clear(); - ba >> objects; -} +/* + PIP - Platform Independent Primitives + Introspection module - Base server structs + 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 . +*/ + +#include "piintrospection_server_p.h" +#include "pichunkstream.h" +#include "piinit.h" +#include "pisysteminfo.h" +#include "piobject.h" + + +const uint PIIntrospection::sign = 0x0F1C2B3A; + + +PIIntrospection::RequiredInfo::RequiredInfo() { + types = itInfo; +} + + +PIIntrospection::ProcessInfo::ProcessInfo() { + processorsCount = 0; +} + + +PIIntrospection::ObjectInfo::ObjectInfo() { + queued_events = 0; +} + + +PIIntrospection::ProcessInfo PIIntrospection::getInfo() { + PIIntrospection::ProcessInfo ret; + PISystemInfo * si = PISystemInfo::instance(); + ret.architecture = si->architecture; + ret.execCommand = si->execCommand; + ret.execDateTime = si->execDateTime; + ret.hostname = si->hostname; + ret.OS_name = si->OS_name; + ret.OS_version = si->OS_version; + ret.processorsCount = si->processorsCount; + ret.user = si->user; + ret.build_options = PIInit::buildOptions(); + return ret; +} + + +PIVector PIIntrospection::getObjects() { + PIVector ret; + PIObject::mutexObjects().lock(); + const PIVector & ao(PIObject::objects()); + ret.resize(ao.size()); + for (int i = 0; i < ao.size_s(); ++i) { + ret[i].classname = PIStringAscii(ao[i]->className()); + ret[i].name = ao[i]->name(); + ret[i].properties = ao[i]->properties(); + ret[i].parents = ao[i]->scopeList(); + ao[i]->mutex_queue.lock(); + ret[i].queued_events = ao[i]->events_queue.size_s(); + ao[i]->mutex_queue.unlock(); + } + PIObject::mutexObjects().unlock(); + return ret; +} + + +PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::RequiredInfo & v) { + PIChunkStream cs; + cs.add(1, v.types); + b << cs.data(); + return b; +} + + +PIByteArray & operator >>(PIByteArray & b, PIIntrospection::RequiredInfo & v) { + PIByteArray csba; b >> csba; + PIChunkStream cs(csba); + while (!cs.atEnd()) { + switch (cs.read()) { + case 1: cs.get(v.types); break; + default: break; + } + } + return b; +} + + +PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ProcessInfo & v) { + PIChunkStream cs; + cs.add(1, v.architecture).add(2, v.execCommand).add(3, v.execDateTime).add(4, v.hostname).add(5, v.OS_name) + .add(6, v.OS_version).add(7, v.processorsCount).add(8, v.user).add(9, v.build_options); + b << cs.data(); + return b; +} + + +PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ProcessInfo & v) { + PIByteArray csba; b >> csba; + PIChunkStream cs(csba); + while (!cs.atEnd()) { + switch (cs.read()) { + case 1: cs.get(v.architecture); break; + case 2: cs.get(v.execCommand); break; + case 3: cs.get(v.execDateTime); break; + case 4: cs.get(v.hostname); break; + case 5: cs.get(v.OS_name); break; + case 6: cs.get(v.OS_version); break; + case 7: cs.get(v.processorsCount); break; + case 8: cs.get(v.user); break; + case 9: cs.get(v.build_options); break; + default: break; + } + } + return b; +} + + +PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ObjectInfo & v) { + PIChunkStream cs; + cs.add(1, v.classname).add(2, v.name).add(3, v.parents).add(4, v.properties).add(5, v.queued_events); + b << cs.data(); + return b; +} + + +PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ObjectInfo & v) { + PIByteArray csba; b >> csba; + PIChunkStream cs(csba); + while (!cs.atEnd()) { + switch (cs.read()) { + case 1: cs.get(v.classname); break; + case 2: cs.get(v.name); break; + case 3: cs.get(v.parents); break; + case 4: cs.get(v.properties); break; + case 5: cs.get(v.queued_events); break; + default: break; + } + } + return b; +} + + + + +PIByteArray PIIntrospection::packInfo() { + PIByteArray ret; + ret << getInfo(); + return ret; +} + + +void PIIntrospection::unpackInfo(PIByteArray & ba, PIIntrospection::ProcessInfo & info) { + ba >> info; +} + + +PIByteArray PIIntrospection::packProcStat(PISystemMonitor * sm) { + ProcessStat ps; + if (sm) { + ps.proc = sm->statistic(); + ps.threads = sm->threadsStatistic(); + } + PIByteArray ret; + ret << ps.proc << ps.threads; + return ret; +} + + +void PIIntrospection::unpackProcStat(PIByteArray & ba, PIIntrospection::ProcessStat & info) { + ba >> info.proc >> info.threads; +} + + +PIByteArray PIIntrospection::packContainers() { + PIByteArray ret; + PIVector data; + PIIntrospectionContainers * p = 0; +#ifdef PIP_INTROSPECTION + p = PIINTROSPECTION_CONTAINERS->p; +#endif + if (p) { + data = p->getInfo(); + } + ret << data; + return ret; +} + + +void PIIntrospection::unpackContainers(PIByteArray & ba, PIVector & data) { + data.clear(); + ba >> data; +} + + +PIByteArray PIIntrospection::packThreads() { + PIByteArray ret; + PIIntrospectionThreads * p = 0; +#ifdef PIP_INTROSPECTION + p = PIINTROSPECTION_THREADS->p; +#endif + if (p) { + p->mutex.lock(); + PIMap & tm(p->threads); + auto it = tm.makeIterator(); + while (it.next()) { + it.valueRef().classname = PIStringAscii(it.key()->className()); + it.valueRef().name = it.key()->name(); + } + ret << tm.values(); + p->mutex.unlock(); + } else { + ret << PIVector(); + } + return ret; +} + + +void PIIntrospection::unpackThreads(PIByteArray & ba, PIVector & threads) { + threads.clear(); + ba >> threads; +} + + +PIByteArray PIIntrospection::packObjects() { + PIByteArray ret; + ret << getObjects(); + return ret; +} + + +void PIIntrospection::unpackObjects(PIByteArray & ba, PIVector & objects) { + objects.clear(); + ba >> objects; +} diff --git a/libs/main/system/pisystemmonitor.cpp b/libs/main/system/pisystemmonitor.cpp index 98e259a6..1e2e39e2 100644 --- a/libs/main/system/pisystemmonitor.cpp +++ b/libs/main/system/pisystemmonitor.cpp @@ -1,501 +1,501 @@ -/* - 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 . -*/ - -#include "piincludes_p.h" -#include "pisystemmonitor.h" -#include "pisysteminfo.h" -#include "piprocess.h" -#include "pidir.h" -#include "pitime_win.h" -#ifdef WINDOWS -# include -# include -#endif -#ifdef MAC_OS - struct kqueue_id_t; -# include -# include -#endif -#ifdef ESP_PLATFORM -# include "esp_heap_caps.h" -#endif - - -PISystemMonitor::ProcessStatsFixed::ProcessStatsFixed() { - ID = parent_ID = group_ID = session_ID = priority = threads = 0; - physical_memsize = resident_memsize = share_memsize = virtual_memsize = data_memsize = 0; - cpu_load_user = cpu_load_system = 0.f; -} - - -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); -} - - -PISystemMonitor::ThreadStatsFixed::ThreadStatsFixed() { - id = 0; - cpu_load_kernel = cpu_load_user = -1.f; -} - - -#ifndef FREERTOS -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 FREERTOS -#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 FREERTOS -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 FREERTOS - bool ret = startOnProcess(PIProcess::currentPID(), interval_ms); - cycle = -1; -#else - bool ret = start(interval_ms); -#endif - return ret; -} - - -PIVector PISystemMonitor::threadsStatistic() const { - mutex_.lock(); - PIVector ret = cur_ts; - mutex_.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 tv = pitc->threads(); - piForeach (PIThread * t, tv) - if (t->isPIObject()) - tbid[t->tid()] = t->name(); - pitc->unlock(); - //piCout << tbid.keys().toType(); - ProcessStats tstat; - tstat.ID = pID_; -#ifdef FREERTOS - 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 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.valueRef()); - 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; - ts.id = id; -#ifdef FREERTOS - ts.name = tbid.value(id, ""); -#else - ts.name = tbid.value(id, ""); -# 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 == NULL) { - piCout << "[PISystemMonitor] gatherThread(" << id << "):: OpenThread() error:" << errorString(); - return; - } - if (GetThreadTimes(thdl, &(times[0]), &(times[1]), &(times[2]), &(times[3])) == 0) { - 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()); -} - - - - -PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ProcessStats & v) { - s << PIByteArray::RawData(&v, sizeof(PISystemMonitor::ProcessStatsFixed)) - << v.exec_name << v.state; - return s; -} - - -PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ProcessStats & v) { - s >> PIByteArray::RawData(&v, sizeof(PISystemMonitor::ProcessStatsFixed)) - >> v.exec_name >> v.state; - v.makeStrings(); - return s; -} - - -PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ThreadStats & v) { - s << PIByteArray::RawData(&v, sizeof(PISystemMonitor::ThreadStatsFixed)) - << v.name << v.created; - return s; -} - - -PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ThreadStats & v) { - s >> PIByteArray::RawData(&v, sizeof(PISystemMonitor::ThreadStatsFixed)) - >> v.name >> v.created; - return s; -} +/* + 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 . +*/ + +#include "piincludes_p.h" +#include "pisystemmonitor.h" +#include "pisysteminfo.h" +#include "piprocess.h" +#include "pidir.h" +#include "pitime_win.h" +#ifdef WINDOWS +# include +# include +#endif +#ifdef MAC_OS + struct kqueue_id_t; +# include +# include +#endif +#ifdef ESP_PLATFORM +# include "esp_heap_caps.h" +#endif + + +PISystemMonitor::ProcessStatsFixed::ProcessStatsFixed() { + ID = parent_ID = group_ID = session_ID = priority = threads = 0; + physical_memsize = resident_memsize = share_memsize = virtual_memsize = data_memsize = 0; + cpu_load_user = cpu_load_system = 0.f; +} + + +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); +} + + +PISystemMonitor::ThreadStatsFixed::ThreadStatsFixed() { + id = 0; + cpu_load_kernel = cpu_load_user = -1.f; +} + + +#ifndef FREERTOS +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 FREERTOS +#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 FREERTOS +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 FREERTOS + bool ret = startOnProcess(PIProcess::currentPID(), interval_ms); + cycle = -1; +#else + bool ret = start(interval_ms); +#endif + return ret; +} + + +PIVector PISystemMonitor::threadsStatistic() const { + mutex_.lock(); + PIVector ret = cur_ts; + mutex_.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 tv = pitc->threads(); + piForeach (PIThread * t, tv) + if (t->isPIObject()) + tbid[t->tid()] = t->name(); + pitc->unlock(); + //piCout << tbid.keys().toType(); + ProcessStats tstat; + tstat.ID = pID_; +#ifdef FREERTOS + 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 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.valueRef()); + 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; + mutex_.lock(); + cur_ts = cur_tm.values(); + mutex_.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; + ts.id = id; +#ifdef FREERTOS + ts.name = tbid.value(id, ""); +#else + ts.name = tbid.value(id, ""); +# 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 == NULL) { + piCout << "[PISystemMonitor] gatherThread(" << id << "):: OpenThread() error:" << errorString(); + return; + } + if (GetThreadTimes(thdl, &(times[0]), &(times[1]), &(times[2]), &(times[3])) == 0) { + 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()); +} + + + + +PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ProcessStats & v) { + s << PIByteArray::RawData(&v, sizeof(PISystemMonitor::ProcessStatsFixed)) + << v.exec_name << v.state; + return s; +} + + +PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ProcessStats & v) { + s >> PIByteArray::RawData(&v, sizeof(PISystemMonitor::ProcessStatsFixed)) + >> v.exec_name >> v.state; + v.makeStrings(); + return s; +} + + +PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ThreadStats & v) { + s << PIByteArray::RawData(&v, sizeof(PISystemMonitor::ThreadStatsFixed)) + << v.name; + return s; +} + + +PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ThreadStats & v) { + s >> PIByteArray::RawData(&v, sizeof(PISystemMonitor::ThreadStatsFixed)) + >> v.name; + return s; +} diff --git a/libs/main/system/pisystemmonitor.h b/libs/main/system/pisystemmonitor.h index f3407f81..dbae9e97 100644 --- a/libs/main/system/pisystemmonitor.h +++ b/libs/main/system/pisystemmonitor.h @@ -1,144 +1,144 @@ -/* - 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 . -*/ - -#ifndef PISYSTEMMONITOR_H -#define PISYSTEMMONITOR_H - -#include "pithread.h" -#include "pifile.h" - -class PIP_EXPORT PISystemMonitor: public PIThread -{ - PIOBJECT_SUBCLASS(PISystemMonitor, PIThread) - friend class PIIntrospectionServer; -public: - PISystemMonitor(); - ~PISystemMonitor(); - -#pragma pack(push, 1) - struct PIP_EXPORT ProcessStatsFixed { - ProcessStatsFixed(); - int ID; - int parent_ID; - int group_ID; - int session_ID; - int priority; - int threads; - ullong physical_memsize; - ullong resident_memsize; - ullong share_memsize; - ullong virtual_memsize; - ullong data_memsize; - ullong ram_total; - ullong ram_free; - ullong ram_used; - float cpu_load_system; - float cpu_load_user; - }; - - struct PIP_EXPORT ThreadStatsFixed { - ThreadStatsFixed(); - llong id; - PISystemTime work_time; - PISystemTime kernel_time; - PISystemTime user_time; - float cpu_load_kernel; - float cpu_load_user; - }; -#pragma pack(pop) - - struct PIP_EXPORT ProcessStats: ProcessStatsFixed { - void makeStrings(); - PIString exec_name; - PIString state; - PIString physical_memsize_readable; - PIString resident_memsize_readable; - PIString share_memsize_readable; - PIString virtual_memsize_readable; - PIString data_memsize_readable; - }; - - struct PIP_EXPORT ThreadStats: ThreadStatsFixed { - PIString name; - PIDateTime created; - }; - -#ifndef FREERTOS - bool startOnProcess(int pID, int interval_ms = 1000); -#endif - bool startOnSelf(int interval_ms = 1000); - void stop(); - - int pID() const {return pID_;} - ProcessStats statistic() const; - PIVector threadsStatistic() const; - void setStatistic(const ProcessStats & s); - - static ullong totalRAM(); - static ullong freeRAM(); - static ullong usedRAM(); - - -private: - void run(); - void gatherThread(llong id); - float calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old); - - ProcessStats stat; - PIVector cur_ts; - PIMap last_tm, cur_tm; - PIMap tbid; - mutable PIMutex stat_mutex; - int pID_, page_size, cpu_count, cycle; -#ifndef FREERTOS - 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 sysmons; - PIMutex mutex; - }; - - -}; - -inline PICout operator <<(PICout s, const PISystemMonitor::ThreadStats & v) { - s.setControl(0, true); - 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.restoreControl(); - return s; -} - -PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ProcessStats & v); -PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ProcessStats & v); -PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ThreadStats & v); -PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ThreadStats & v); - -#endif // PISYSTEMMONITOR_H +/* + 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 . +*/ + +#ifndef PISYSTEMMONITOR_H +#define PISYSTEMMONITOR_H + +#include "pithread.h" +#include "pifile.h" + +class PIP_EXPORT PISystemMonitor: public PIThread +{ + PIOBJECT_SUBCLASS(PISystemMonitor, PIThread) + friend class PIIntrospectionServer; +public: + PISystemMonitor(); + ~PISystemMonitor(); + +#pragma pack(push, 1) + struct PIP_EXPORT ProcessStatsFixed { + ProcessStatsFixed(); + int ID; + int parent_ID; + int group_ID; + int session_ID; + int priority; + int threads; + ullong physical_memsize; + ullong resident_memsize; + ullong share_memsize; + ullong virtual_memsize; + ullong data_memsize; + ullong ram_total; + ullong ram_free; + ullong ram_used; + float cpu_load_system; + float cpu_load_user; + }; + + struct PIP_EXPORT ThreadStatsFixed { + ThreadStatsFixed(); + llong id; + PISystemTime work_time; + PISystemTime kernel_time; + PISystemTime user_time; + float cpu_load_kernel; + float cpu_load_user; + PIDateTime created; + }; +#pragma pack(pop) + + struct PIP_EXPORT ProcessStats: ProcessStatsFixed { + void makeStrings(); + PIString exec_name; + PIString state; + PIString physical_memsize_readable; + PIString resident_memsize_readable; + PIString share_memsize_readable; + PIString virtual_memsize_readable; + PIString data_memsize_readable; + }; + + struct PIP_EXPORT ThreadStats: ThreadStatsFixed { + PIString name; + }; + +#ifndef FREERTOS + bool startOnProcess(int pID, int interval_ms = 1000); +#endif + bool startOnSelf(int interval_ms = 1000); + void stop(); + + int pID() const {return pID_;} + ProcessStats statistic() const; + PIVector threadsStatistic() const; + void setStatistic(const ProcessStats & s); + + static ullong totalRAM(); + static ullong freeRAM(); + static ullong usedRAM(); + + +private: + void run(); + void gatherThread(llong id); + float calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old); + + ProcessStats stat; + PIVector cur_ts; + PIMap last_tm, cur_tm; + PIMap tbid; + mutable PIMutex stat_mutex; + int pID_, page_size, cpu_count, cycle; +#ifndef FREERTOS + 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 sysmons; + PIMutex mutex; + }; + + +}; + +inline PICout operator <<(PICout s, const PISystemMonitor::ThreadStats & v) { + s.setControl(0, true); + 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.restoreControl(); + return s; +} + +PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ProcessStats & v); +PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ProcessStats & v); +PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ThreadStats & v); +PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ThreadStats & v); + +#endif // PISYSTEMMONITOR_H diff --git a/utils/system_daemon/main.cpp b/utils/system_daemon/main.cpp index 85900bd1..664d7590 100755 --- a/utils/system_daemon/main.cpp +++ b/utils/system_daemon/main.cpp @@ -332,7 +332,7 @@ void usage() { int main(int argc, char * argv[]) { sys_mon.startOnSelf(); - PIINTROSPECTION_START + PIINTROSPECTION_START(pisd) //piDebug = false; PICLI cli(argc, argv); cli.addArgument("help"); From d839832ee6df320ba1469638f7949dfe85f2fb99 Mon Sep 17 00:00:00 2001 From: peri4 Date: Thu, 10 Jun 2021 20:05:23 +0300 Subject: [PATCH 2/3] PIBinaryLog recreate index performance patch --- libs/main/core/pibytearray.h | 2 +- libs/main/io_devices/pibinarylog.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/main/core/pibytearray.h b/libs/main/core/pibytearray.h index 548a073c..f9c81938 100644 --- a/libs/main/core/pibytearray.h +++ b/libs/main/core/pibytearray.h @@ -312,7 +312,7 @@ PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIByteArray & v); //! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) { if (s.size_s() < v.s) { - printf("error with RawData %d < %d\n", s.size_s(), v.s); + printf("error with RawData %d < %d\n", (int)s.size_s(), v.s); assert(s.size_s() >= v.s); } if (v.s > 0) { diff --git a/libs/main/io_devices/pibinarylog.cpp b/libs/main/io_devices/pibinarylog.cpp index 1a8472dc..7d434d96 100644 --- a/libs/main/io_devices/pibinarylog.cpp +++ b/libs/main/io_devices/pibinarylog.cpp @@ -153,6 +153,7 @@ bool PIBinaryLog::openDevice() { bool PIBinaryLog::closeDevice() { stopThreadedRead(); pausemutex.unlock(); + logmutex.unlock(); moveIndex(-1); is_indexed = false; index.clear(); @@ -654,7 +655,9 @@ bool PIBinaryLog::createIndex() { llong cp = file.pos(); file.seekToBegin(); index.clear(); + index = PIVector(); index_pos.clear(); + index_pos = PIMap(); parseLog(&file, &binfo, &index); file.seek(cp); is_indexed = !index.isEmpty(); From 00f76fa6b5cd1165fec140956e96c9c5ac0c0918 Mon Sep 17 00:00:00 2001 From: peri4 Date: Fri, 11 Jun 2021 21:01:25 +0300 Subject: [PATCH 3/3] rollback PIBinaryLog optimization due to last PIDeque fix --- libs/main/io_devices/pibinarylog.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/main/io_devices/pibinarylog.cpp b/libs/main/io_devices/pibinarylog.cpp index 7d434d96..d79fddc1 100644 --- a/libs/main/io_devices/pibinarylog.cpp +++ b/libs/main/io_devices/pibinarylog.cpp @@ -655,9 +655,7 @@ bool PIBinaryLog::createIndex() { llong cp = file.pos(); file.seekToBegin(); index.clear(); - index = PIVector(); index_pos.clear(); - index_pos = PIMap(); parseLog(&file, &binfo, &index); file.seek(cp); is_indexed = !index.isEmpty();