Merge pull request 'introspection' (#75) from introspection into master

Reviewed-on: https://git.shs.tools/SHS/pip/pulls/75
This commit was merged in pull request #75.
This commit is contained in:
2021-06-11 21:02:56 +03:00
8 changed files with 1622 additions and 1578 deletions

View File

@@ -1,520 +1,556 @@
/*! \file pibytearray.h /*! \file pibytearray.h
* \brief Byte array * \brief Byte array
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Byte array Byte array
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIBYTEARRAY_H #ifndef PIBYTEARRAY_H
#define PIBYTEARRAY_H #define PIBYTEARRAY_H
#include "pichar.h" #include "pichar.h"
#include "pibitarray.h" #include "pibitarray.h"
#include "pimap.h" #include "pimap.h"
#include "pivector2d.h" #include "pivector2d.h"
class PIString; class PIString;
class PIByteArray; class PIByteArray;
class PIP_EXPORT PIByteArray: public PIDeque<uchar> class PIP_EXPORT PIByteArray: public PIDeque<uchar>
{ {
public: public:
//! Constructs an empty byte array //! Constructs an empty byte array
PIByteArray() {;} PIByteArray() {;}
PIByteArray(const PIByteArray & o): PIDeque<uchar>(o) {} PIByteArray(const PIByteArray & o): PIDeque<uchar>(o) {}
PIByteArray(PIByteArray && o): PIDeque<uchar>(std::move(o)) {} PIByteArray(PIByteArray && o): PIDeque<uchar>(std::move(o)) {}
//! Constructs 0-filled byte array with size "size" //! Constructs 0-filled byte array with size "size"
PIByteArray(const uint size) {resize(size);} PIByteArray(const uint size) {resize(size);}
//! Constructs byte array from data "data" and size "size" //! Constructs byte array from data "data" and size "size"
PIByteArray(const void * data, const uint size): PIDeque<uchar>((const uchar*)data, size_t(size)) {} PIByteArray(const void * data, const uint size): PIDeque<uchar>((const uchar*)data, size_t(size)) {}
//! Constructs byte array with size "size" filled by "t" //! Constructs byte array with size "size" filled by "t"
PIByteArray(const uint size, uchar t): PIDeque<uchar>(size, t) {} PIByteArray(const uint size, uchar t): PIDeque<uchar>(size, t) {}
//! Help struct to store/restore custom blocks of data to/from PIByteArray //! Help struct to store/restore custom blocks of data to/from PIByteArray
struct RawData { struct RawData {
friend PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v); friend PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v);
friend PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v); friend PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v);
public: public:
//! Constructs data block //! Constructs data block
RawData(void * data = 0, int size = 0) {d = data; s = size;} RawData(void * data = 0, int size = 0) {d = data; s = size;}
RawData(const RawData & o) {d = o.d; s = o.s;} RawData(const RawData & o) {d = o.d; s = o.s;}
//! Constructs data block //! Constructs data block
RawData(const void * data, const int size) {d = const_cast<void * >(data); s = size;} RawData(const void * data, const int size) {d = const_cast<void * >(data); s = size;}
RawData & operator =(const RawData & o) {d = o.d; s = o.s; return *this;} RawData & operator =(const RawData & o) {d = o.d; s = o.s; return *this;}
private: private:
void * d; void * d;
int s; int s;
}; };
//! Return resized byte array //! Return resized byte array
PIByteArray resized(uint new_size) const {PIByteArray ret(new_size); memcpy(ret.data(), data(), new_size); return ret;} 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 //! Convert data to Base 64 and return this byte array
PIByteArray & convertToBase64(); PIByteArray & convertToBase64();
//! Convert data from Base 64 and return this byte array //! Convert data from Base 64 and return this byte array
PIByteArray & convertFromBase64(); PIByteArray & convertFromBase64();
//! Return converted to Base 64 data //! Return converted to Base 64 data
PIByteArray toBase64() const; PIByteArray toBase64() const;
//! Return converted from Base 64 data //! Return converted from Base 64 data
PIByteArray & compressRLE(uchar threshold = 192); PIByteArray & compressRLE(uchar threshold = 192);
PIByteArray & decompressRLE(uchar threshold = 192); PIByteArray & decompressRLE(uchar threshold = 192);
PIByteArray compressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.compressRLE(threshold); return ba;} 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;} PIByteArray decompressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.decompressRLE(threshold); return ba;}
PIString toString(int base = 16) const; PIString toString(int base = 16) const;
PIString toHex() const; PIString toHex() const;
//! Add to the end data "data" with size "size" //! 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;} 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" //! 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;} 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" //! Add to the end "t"
PIByteArray & append(uchar t) {push_back(t); return *this;} PIByteArray & append(uchar t) {push_back(t); return *this;}
//! Returns plain 8-bit checksum //! Returns plain 8-bit checksum
uchar checksumPlain8() const; uchar checksumPlain8() const;
//! Returns plain 32-bit checksum //! Returns plain 32-bit checksum
uint checksumPlain32() const; uint checksumPlain32() const;
//! Returns hash //! Returns hash
uint hash() const; uint hash() const;
void operator =(const PIDeque<uchar> & d) {resize(d.size()); memcpy(data(), d.data(), d.size());} void operator =(const PIDeque<uchar> & 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 =(const PIByteArray & o) {if (this == &o) return *this; clear(); append(o); return *this;}
PIByteArray & operator =(PIByteArray && o) {swap(o); return *this;} PIByteArray & operator =(PIByteArray && o) {swap(o); return *this;}
static PIByteArray fromUserInput(PIString str); static PIByteArray fromUserInput(PIString str);
static PIByteArray fromHex(PIString str); static PIByteArray fromHex(PIString str);
static PIByteArray fromBase64(const PIByteArray & base64); static PIByteArray fromBase64(const PIByteArray & base64);
static PIByteArray fromBase64(const PIString & base64); static PIByteArray fromBase64(const PIString & base64);
class StreamRef { class StreamRef {
public: public:
StreamRef(PIByteArray & s): ba(s) {} StreamRef(PIByteArray & s): ba(s) {}
operator PIByteArray&() {return ba;} operator PIByteArray&() {return ba;}
private: private:
PIByteArray & ba; PIByteArray & ba;
}; };
}; };
//! \relatesalso PIByteArray \brief Byte arrays compare operator //! \relatesalso PIByteArray \brief Byte arrays compare operator
inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) { inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) {
if (v0.size() == v1.size()) { if (v0.size() == v1.size()) {
for (uint i = 0; i < v0.size(); ++i) for (uint i = 0; i < v0.size(); ++i)
if (v0[i] != v1[i]) if (v0[i] != v1[i])
return v0[i] < v1[i]; return v0[i] < v1[i];
return false; return false;
} }
return v0.size() < v1.size(); return v0.size() < v1.size();
} }
//! \relatesalso PIByteArray \brief Byte arrays compare operator //! \relatesalso PIByteArray \brief Byte arrays compare operator
inline bool operator ==(PIByteArray & f, PIByteArray & s) { inline bool operator ==(PIByteArray & f, PIByteArray & s) {
if (f.size_s() != s.size_s()) if (f.size_s() != s.size_s())
return false; return false;
for (int i = 0; i < f.size_s(); ++i) for (int i = 0; i < f.size_s(); ++i)
if (f[i] != s[i]) if (f[i] != s[i])
return false; return false;
return true; return true;
} }
//! \relatesalso PIByteArray \brief Byte arrays compare operator //! \relatesalso PIByteArray \brief Byte arrays compare operator
inline bool operator !=(PIByteArray & f, PIByteArray & s) { inline bool operator !=(PIByteArray & f, PIByteArray & s) {
if (f.size_s() != s.size_s()) if (f.size_s() != s.size_s())
return true; return true;
for (int i = 0; i < f.size_s(); ++i) for (int i = 0; i < f.size_s(); ++i)
if (f[i] != s[i]) if (f[i] != s[i])
return true; return true;
return false; return false;
} }
#ifdef PIP_STD_IOSTREAM #ifdef PIP_STD_IOSTREAM
//! \relatesalso PIByteArray \brief Output to std::ostream operator //! \relatesalso PIByteArray \brief Output to std::ostream operator
inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba); inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba);
#endif #endif
//! \relatesalso PIByteArray \brief Output to PICout operator //! \relatesalso PIByteArray \brief Output to PICout operator
PIP_EXPORT PICout operator <<(PICout s, const PIByteArray & ba); PIP_EXPORT PICout operator <<(PICout s, const PIByteArray & ba);
// store operators for basic types // store operators for basic types
//! \relatesalso PIByteArray \brief Store operator //! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, const bool v) {s.push_back(v); return s;} inline PIByteArray & operator <<(PIByteArray & s, const bool v) {s.push_back(v); return s;}
//! \relatesalso PIByteArray \brief Store operator //! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, const char v) {s.push_back(v); return s;} inline PIByteArray & operator <<(PIByteArray & s, const char v) {s.push_back(v); return s;}
//! \relatesalso PIByteArray \brief Store operator //! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, const uchar v) {s.push_back(v); return s;} inline PIByteArray & operator <<(PIByteArray & s, const uchar v) {s.push_back(v); return s;}
//! \relatesalso PIByteArray \brief Store operator for any trivial copyable type //! \relatesalso PIByteArray \brief Store operator for any trivial copyable type
template<typename T, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0> template<typename T, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray::StreamRef operator <<(PIByteArray & s, const T & v) { inline PIByteArray::StreamRef operator <<(PIByteArray & s, const T & v) {
int os = s.size_s(); int os = s.size_s();
s.enlarge(sizeof(v)); s.enlarge(sizeof(v));
memcpy(s.data(os), &v, sizeof(v)); memcpy(s.data(os), &v, sizeof(v));
return s; return s;
} }
//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details //! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details
PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v); PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v);
//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details //! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details
inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) { inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {
int os = s.size_s(); int os = s.size_s();
if (v.s > 0) { if (v.s > 0) {
s.enlarge(v.s); s.enlarge(v.s);
memcpy(s.data(os), v.d, v.s); memcpy(s.data(os), v.d, v.s);
} }
return s; return s;
} }
//! \relatesalso PIByteArray \brief Store operator for PIVector of any trivial copyable type //! \relatesalso PIByteArray \brief Store operator for PIVector of any trivial copyable type
template<typename T, template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0> typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) { inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {
s << int(v.size_s()); s << int(v.size_s());
int os = s.size_s(); int os = s.size_s();
if (v.size_s() > 0) { if (v.size_s() > 0) {
s.enlarge(v.size_s()*sizeof(T)); s.enlarge(v.size_s()*sizeof(T));
memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
} }
return s; return s;
} }
template<typename T, template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0> typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) { inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {
s << int(v.size_s()); s << int(v.size_s());
for (uint i = 0; i < v.size(); ++i) s << v[i]; for (uint i = 0; i < v.size(); ++i) s << v[i];
return s; return s;
} }
//! \relatesalso PIByteArray \brief Store operator for PIDeque of any trivial copyable type //! \relatesalso PIByteArray \brief Store operator for PIDeque of any trivial copyable type
template<typename T, template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0> typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) { inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {
s << int(v.size_s()); s << int(v.size_s());
int os = s.size_s(); int os = s.size_s();
if (v.size_s() > 0) { if (v.size_s() > 0) {
s.enlarge(v.size_s()*sizeof(T)); s.enlarge(v.size_s()*sizeof(T));
memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
} }
return s; return s;
} }
template<typename T, template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0> typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) { inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {
s << int(v.size_s()); s << int(v.size_s());
for (uint i = 0; i < v.size(); ++i) s << v[i]; for (uint i = 0; i < v.size(); ++i) s << v[i];
return s; return s;
} }
//! \relatesalso PIByteArray \brief Store operator for PIVector2D of any trivial copyable type //! \relatesalso PIByteArray \brief Store operator for PIVector2D of any trivial copyable type
template<typename T, template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0> typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) { inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
s << int(v.rows()) << int(v.cols()); s << int(v.rows()) << int(v.cols());
int os = s.size_s(); int os = s.size_s();
if (v.size_s() > 0) { if (v.size_s() > 0) {
s.enlarge(v.size_s()*sizeof(T)); s.enlarge(v.size_s()*sizeof(T));
memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
} }
return s; return s;
} }
template<typename T, template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0> typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) { inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
s << int(v.rows()) << int(v.cols()) << v.toPlainVector(); s << int(v.rows()) << int(v.cols()) << v.toPlainVector();
return s; return s;
} }
//! \relatesalso PIByteArray \brief Store operator //! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, const PIBitArray & v) {s << v.size_ << v.data_; return s;} inline PIByteArray & operator <<(PIByteArray & s, const PIBitArray & v) {s << v.size_ << v.data_; return s;}
//! \relatesalso PIPair \brief Store operator //! \relatesalso PIPair \brief Store operator
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
inline PIByteArray & operator <<(PIByteArray & s, const PIPair<Type0, Type1> & v) {s << v.first << v.second; return s;} inline PIByteArray & operator <<(PIByteArray & s, const PIPair<Type0, Type1> & v) {s << v.first << v.second; return s;}
// restore operators for basic types // restore operators for basic types
//! \relatesalso PIByteArray \brief Restore operator //! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, bool & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} inline PIByteArray & operator >>(PIByteArray & s, bool & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
//! \relatesalso PIByteArray \brief Restore operator //! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, char & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} inline PIByteArray & operator >>(PIByteArray & s, char & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
//! \relatesalso PIByteArray \brief Restore operator //! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} 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 //! \relatesalso PIByteArray \brief Restore operator for any trivial copyable type
template<typename T, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0> template<typename T, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray::StreamRef operator >>(PIByteArray & s, T & v) { inline PIByteArray::StreamRef operator >>(PIByteArray & s, T & v) {
assert(s.size() >= sizeof(v)); if (s.size() < sizeof(v)) {
memcpy((void*)(&v), s.data(), sizeof(v)); printf("error with %s\n", typeid(T).name());
s.remove(0, sizeof(v)); assert(s.size() >= sizeof(v));
return s; }
} memcpy((void*)(&v), s.data(), sizeof(v));
s.remove(0, sizeof(v));
//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details return s;
PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIByteArray & v); }
//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details //! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) { PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIByteArray & v);
assert(s.size_s() >= v.s);
if (v.s > 0) { //! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
memcpy((void*)(v.d), s.data(), v.s); inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {
s.remove(0, v.s); if (s.size_s() < v.s) {
} printf("error with RawData %d < %d\n", (int)s.size_s(), v.s);
return s; assert(s.size_s() >= v.s);
} }
if (v.s > 0) {
//! \relatesalso PIByteArray \brief Restore operator for PIVector of any trivial copyable type memcpy((void*)(v.d), s.data(), v.s);
template<typename T, s.remove(0, v.s);
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0, }
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0> return s;
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) { }
assert(s.size_s() >= 4);
int sz; s >> sz; //! \relatesalso PIByteArray \brief Restore operator for PIVector of any trivial copyable type
v._resizeRaw(sz); template<typename T,
if (sz > 0) { typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
memcpy(v.data(), s.data(), sz*sizeof(T)); typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
s.remove(0, sz*sizeof(T)); inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
} if (s.size_s() < 4) {
return s; printf("error with PIVector<%s>\n", typeid(T).name());
} assert(s.size_s() >= 4);
template<typename T, }
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0, int sz; s >> sz;
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0> v._resizeRaw(sz);
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) { if (sz > 0) {
assert(s.size_s() >= 4); memcpy(v.data(), s.data(), sz*sizeof(T));
int sz; s >> sz; s.remove(0, sz*sizeof(T));
v.resize(sz); }
for (int i = 0; i < sz; ++i) s >> v[i]; return s;
return s; }
} template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
//! \relatesalso PIByteArray \brief Restore operator for PIDeque of any trivial copyable type typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
template<typename T, inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0, if (s.size_s() < 4) {
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0> printf("error with PIVector<%s>\n", typeid(T).name());
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) { assert(s.size_s() >= 4);
assert(s.size_s() >= 4); }
int sz; s >> sz; int sz; s >> sz;
v._resizeRaw(sz); v.resize(sz);
if (sz > 0) { for (int i = 0; i < sz; ++i) s >> v[i];
memcpy(v.data(), s.data(), sz*sizeof(T)); return s;
s.remove(0, sz*sizeof(T)); }
}
return s; //! \relatesalso PIByteArray \brief Restore operator for PIDeque of any trivial copyable type
} template<typename T,
template<typename T, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0, typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0> inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) { if (s.size_s() < 4) {
assert(s.size_s() >= 4); printf("error with PIDeque<%s>\n", typeid(T).name());
int sz; s >> sz; assert(s.size_s() >= 4);
v.resize(sz); }
for (int i = 0; i < sz; ++i) s >> v[i]; int sz; s >> sz;
return s; v._resizeRaw(sz);
} if (sz > 0) {
memcpy(v.data(), s.data(), sz*sizeof(T));
//! \relatesalso PIByteArray \brief Restore operator for PIVector2D of any trivial copyable type s.remove(0, sz*sizeof(T));
template<typename T, }
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0, return s;
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0> }
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) { template<typename T,
assert(s.size_s() >= 8); typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
int r, c; s >> r >> c; typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
v._resizeRaw(r, c); inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
int sz = r*c; if (s.size_s() < 4) {
if (sz > 0) { printf("error with PIDeque<%s>\n", typeid(T).name());
memcpy(v.data(), s.data(), sz*sizeof(T)); assert(s.size_s() >= 4);
s.remove(0, sz*sizeof(T)); }
} int sz; s >> sz;
return s; v.resize(sz);
} for (int i = 0; i < sz; ++i) s >> v[i];
template<typename T, return s;
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0, }
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) { //! \relatesalso PIByteArray \brief Restore operator for PIVector2D of any trivial copyable type
assert(s.size_s() >= 8); template<typename T,
int r,c; typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
PIVector<T> tmp; typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
s >> r >> c >> tmp; inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
v = PIVector2D<T>(r, c, tmp); if (s.size_s() < 8) {
return s; printf("error with PIVecto2Dr<%s>\n", typeid(T).name());
} assert(s.size_s() >= 8);
}
//! \relatesalso PIByteArray \brief Restore operator int r, c; s >> r >> c;
inline PIByteArray & operator >>(PIByteArray & s, PIBitArray & v) {assert(s.size_s() >= 8); s >> v.size_ >> v.data_; return s;} v._resizeRaw(r, c);
int sz = r*c;
//! \relatesalso PIPair \brief Restore operator if (sz > 0) {
template<typename Type0, typename Type1> memcpy(v.data(), s.data(), sz*sizeof(T));
inline PIByteArray & operator >>(PIByteArray & s, PIPair<Type0, Type1> & v) {s >> v.first >> v.second; return s;} s.remove(0, sz*sizeof(T));
}
return s;
}
template<typename T,
// store operators for complex types typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
//! \relatesalso PIByteArray \brief Store operator for PIVector of any compound type if (s.size_s() < 8) {
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0> printf("error with PIVecto2Dr<%s>\n", typeid(T).name());
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) { assert(s.size_s() >= 8);
s << int(v.size_s()); }
for (uint i = 0; i < v.size(); ++i) s << v[i]; int r,c;
return s; PIVector<T> tmp;
} s >> r >> c >> tmp;
v = PIVector2D<T>(r, c, tmp);
//! \relatesalso PIByteArray \brief Store operator for PIDeque of any compound type return s;
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0> }
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {
s << int(v.size_s()); //! \relatesalso PIByteArray \brief Restore operator
for (uint i = 0; i < v.size(); ++i) s << v[i]; inline PIByteArray & operator >>(PIByteArray & s, PIBitArray & v) {assert(s.size_s() >= 8); s >> v.size_ >> v.data_; return s;}
return s;
} //! \relatesalso PIPair \brief Restore operator
template<typename Type0, typename Type1>
//! \relatesalso PIByteArray \brief Store operator for PIVector2D of any compound type inline PIByteArray & operator >>(PIByteArray & s, PIPair<Type0, Type1> & v) {s >> v.first >> v.second; return s;}
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
s << int(v.rows()) << int(v.cols()) << v.toPlainVector();
return s;
} // store operators for complex types
//! \relatesalso PIByteArray \brief Store operator for PIVector of any compound type
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
// restore operators for complex types inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {
s << int(v.size_s());
for (uint i = 0; i < v.size(); ++i) s << v[i];
//! \relatesalso PIByteArray \brief Restore operator for PIVector of any compound type return s;
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0> }
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
assert(s.size_s() >= 4); //! \relatesalso PIByteArray \brief Store operator for PIDeque of any compound type
int sz; s >> sz; template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
v.resize(sz); inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {
for (int i = 0; i < sz; ++i) s >> v[i]; s << int(v.size_s());
return s; for (uint i = 0; i < v.size(); ++i) s << v[i];
} return s;
}
//! \relatesalso PIByteArray \brief Restore operator for PIDeque of any compound type
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0> //! \relatesalso PIByteArray \brief Store operator for PIVector2D of any compound type
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) { template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
assert(s.size_s() >= 4); inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
int sz; s >> sz; s << int(v.rows()) << int(v.cols()) << v.toPlainVector();
v.resize(sz); return s;
for (int i = 0; i < sz; ++i) s >> v[i]; }
return s;
}
//! \relatesalso PIByteArray \brief Restore operator for PIVector2D of any compound type
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0> // restore operators for complex types
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
assert(s.size_s() >= 8);
int r,c; //! \relatesalso PIByteArray \brief Restore operator for PIVector of any compound type
PIVector<T> tmp; template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
s >> r >> c >> tmp; inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
v = PIVector2D<T>(r, c, tmp); if (s.size_s() < 4) {
return s; 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];
// other types return s;
}
template <typename Key, typename T> //! \relatesalso PIByteArray \brief Restore operator for PIDeque of any compound type
inline PIByteArray & operator <<(PIByteArray & s, const PIMap<Key, T> & v) { template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
s << int(v.pim_index.size_s()); inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
for (uint i = 0; i < v.size(); ++i) if (s.size_s() < 4) {
s << int(v.pim_index[i].index) << v.pim_index[i].key; printf("error with PIDeque<%s>\n", typeid(T).name());
s << v.pim_content; assert(s.size_s() >= 4);
return s; }
} int sz; s >> sz;
v.resize(sz);
for (int i = 0; i < sz; ++i) s >> v[i];
template <typename Key, typename T> return s;
inline PIByteArray & operator >>(PIByteArray & s, PIMap<Key, T> & v) { }
assert(s.size_s() >= 4);
int sz; s >> sz; v.pim_index.resize(sz); //! \relatesalso PIByteArray \brief Restore operator for PIVector2D of any compound type
int ind = 0; template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
for (int i = 0; i < sz; ++i) { inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
s >> ind >> v.pim_index[i].key; if (s.size_s() < 8) {
v.pim_index[i].index = ind; printf("error with PIVecto2Dr<%s>\n", typeid(T).name());
} assert(s.size_s() >= 8);
s >> v.pim_content; }
if (v.pim_content.size_s() != v.pim_index.size_s()) { int r,c;
piCout << "Warning: loaded invalid PIMap, clear"; PIVector<T> tmp;
v.clear(); s >> r >> c >> tmp;
} v = PIVector2D<T>(r, c, tmp);
return s; return s;
} }
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray & operator <<(PIByteArray & s, const T & ) { // other types
static_assert(std::is_trivially_copyable<T>::value, "[PIByteArray] Error: using undeclared operator << for complex type!");
return s;
} template <typename Key, typename T>
inline PIByteArray & operator <<(PIByteArray & s, const PIMap<Key, T> & v) {
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0> s << int(v.pim_index.size_s());
inline PIByteArray & operator >>(PIByteArray & s, T & ) { for (uint i = 0; i < v.size(); ++i)
static_assert(std::is_trivially_copyable<T>::value, "[PIByteArray] Error: using undeclared operator >> for complex type!"); s << int(v.pim_index[i].index) << v.pim_index[i].key;
return s; s << v.pim_content;
} return s;
}
template<> inline uint piHash(const PIByteArray & ba) {return ba.hash();}
template<> inline void piSwap(PIByteArray & f, PIByteArray & s) {f.swap(s);}
template <typename Key, typename T>
inline PIByteArray & operator >>(PIByteArray & s, PIMap<Key, T> & v) {
#endif // PIBYTEARRAY_H 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<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray & operator <<(PIByteArray & s, const T & ) {
static_assert(std::is_trivially_copyable<T>::value, "[PIByteArray] Error: using undeclared operator << for complex type!");
return s;
}
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray & operator >>(PIByteArray & s, T & ) {
static_assert(std::is_trivially_copyable<T>::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

View File

@@ -1,104 +1,111 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Introspection module Introspection module
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef PIP_INTROSPECTION #ifdef PIP_INTROSPECTION
#include "piintrospection_server.h" #include "piintrospection_server.h"
#include "piintrospection_server_p.h" #include "piintrospection_server_p.h"
#include "piprocess.h" #include "piprocess.h"
#include "pichunkstream.h" #include "pichunkstream.h"
PRIVATE_DEFINITION_START(PIIntrospectionServer) PRIVATE_DEFINITION_START(PIIntrospectionServer)
PIIntrospection::ProcessInfo process_info; PIIntrospection::ProcessInfo process_info;
PRIVATE_DEFINITION_END(PIIntrospectionServer) PRIVATE_DEFINITION_END(PIIntrospectionServer)
PIIntrospectionServer::PIIntrospectionServer(): PIPeer(genName()) { PIIntrospectionServer::PIIntrospectionServer(): PIPeer(genName()) {
PRIVATE->process_info = PIIntrospection::getInfo(); PRIVATE->process_info = PIIntrospection::getInfo();
sysmon = 0; sysmon = 0;
} }
PIIntrospectionServer::~PIIntrospectionServer() { PIIntrospectionServer::~PIIntrospectionServer() {
PIPeer::stop(); PIPeer::stop();
if (sysmon) if (sysmon)
if (sysmon->property("__iserver__").toBool()) if (sysmon->property("__iserver__").toBool())
delete sysmon; delete sysmon;
sysmon = 0; sysmon = 0;
} }
void PIIntrospectionServer::start() { PIIntrospectionServer * PIIntrospectionServer::instance() {
if (!sysmon) { static PIIntrospectionServer ret;
sysmon = PISystemMonitor::Pool::instance()->getByPID(PIProcess::currentPID()); return &ret;
if (sysmon) { }
piCoutObj << "using existing sysmon";
CONNECTU(sysmon, deleted, this, sysmonDeleted);
} else { void PIIntrospectionServer::start(const PIString & server_name) {
piCoutObj << "create own sysmon"; if (!sysmon) {
sysmon = new PISystemMonitor(); sysmon = PISystemMonitor::Pool::instance()->getByPID(PIProcess::currentPID());
sysmon->setProperty("__iserver__", true); if (sysmon) {
sysmon->startOnSelf(); piCoutObj << "using existing sysmon";
} CONNECTU(sysmon, deleted, this, sysmonDeleted);
} } else {
PIPeer::start(); piCoutObj << "create own sysmon";
} sysmon = new PISystemMonitor();
sysmon->setProperty("__iserver__", true);
sysmon->startOnSelf();
PIString PIIntrospectionServer::genName() { }
randomize(); }
return "__introspection__server_" + PIString::fromNumber(randomi() % 1000); changeName(server_name + genName());
} PIPeer::start();
}
void PIIntrospectionServer::dataReceived(const PIString & from, const PIByteArray & data) {
if (data.size() < 8) return; PIString PIIntrospectionServer::genName() {
PIByteArray rba(data); randomize();
uint _sign(0); rba >> _sign; return "__introspection__server_" + PIString::fromNumber(randomi() % 1000);
if (_sign != PIIntrospection::sign) return; }
PIIntrospection::RequiredInfo ri;
rba >> ri;
PIChunkStream cs; void PIIntrospectionServer::dataReceived(const PIString & from, const PIByteArray & data) {
if (ri.types[PIIntrospection::itInfo]) if (data.size() < 8) return;
cs.add(PIIntrospection::itInfo, PIIntrospection::packInfo()); PIByteArray rba(data);
if (ri.types[PIIntrospection::itProcStat]) { uint _sign(0); rba >> _sign;
sysmon_mutex.lock(); if (_sign != PIIntrospection::sign) return;
cs.add(PIIntrospection::itProcStat, PIIntrospection::packProcStat(sysmon)); PIIntrospection::RequiredInfo ri;
sysmon_mutex.unlock(); rba >> ri;
} PIChunkStream cs;
if (ri.types[PIIntrospection::itContainers]) if (ri.types[PIIntrospection::itInfo])
cs.add(PIIntrospection::itContainers, PIIntrospection::packContainers()); cs.add(PIIntrospection::itInfo, PIIntrospection::packInfo());
if (ri.types[PIIntrospection::itObjects]) if (ri.types[PIIntrospection::itProcStat]) {
cs.add(PIIntrospection::itObjects, PIIntrospection::packObjects()); sysmon_mutex.lock();
if (ri.types[PIIntrospection::itThreads]) cs.add(PIIntrospection::itProcStat, PIIntrospection::packProcStat(sysmon));
cs.add(PIIntrospection::itThreads, PIIntrospection::packThreads()); sysmon_mutex.unlock();
PIByteArray ba; }
ba << PIIntrospection::sign; if (ri.types[PIIntrospection::itContainers])
ba.append(cs.data()); cs.add(PIIntrospection::itContainers, PIIntrospection::packContainers());
send(from, ba); if (ri.types[PIIntrospection::itObjects])
} cs.add(PIIntrospection::itObjects, PIIntrospection::packObjects());
if (ri.types[PIIntrospection::itThreads])
cs.add(PIIntrospection::itThreads, PIIntrospection::packThreads());
void PIIntrospectionServer::sysmonDeleted() { PIByteArray ba;
PIMutexLocker _ml(sysmon_mutex); ba << PIIntrospection::sign;
sysmon = 0; ba.append(cs.data());
} send(from, ba);
}
#endif // PIP_INTROSPECTION
void PIIntrospectionServer::sysmonDeleted() {
PIMutexLocker _ml(sysmon_mutex);
sysmon = 0;
}
#endif // PIP_INTROSPECTION

View File

@@ -1,61 +1,61 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Introspection module Introspection module
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIINTROSPECTION_SERVER_H #ifndef PIINTROSPECTION_SERVER_H
#define PIINTROSPECTION_SERVER_H #define PIINTROSPECTION_SERVER_H
#include "pipeer.h" #include "pipeer.h"
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION) #if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
class PIIntrospectionServer; class PIIntrospectionServer;
class PISystemMonitor; class PISystemMonitor;
# define PIINTROSPECTION_SERVER (PIIntrospectionServer::instance()) # define PIINTROSPECTION_SERVER (PIIntrospectionServer::instance())
# define PIINTROSPECTION_START PIINTROSPECTION_SERVER->start(); # define PIINTROSPECTION_START(name) PIINTROSPECTION_SERVER->start(#name);
class PIP_EXPORT PIIntrospectionServer: public PIPeer { class PIP_EXPORT PIIntrospectionServer: public PIPeer {
PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer) PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer)
public: public:
static PIIntrospectionServer * instance() {static PIIntrospectionServer ret; return &ret;} static PIIntrospectionServer * instance();
void start(); void start(const PIString & server_name);
private: private:
PIIntrospectionServer(); PIIntrospectionServer();
~PIIntrospectionServer(); ~PIIntrospectionServer();
NO_COPY_CLASS(PIIntrospectionServer) NO_COPY_CLASS(PIIntrospectionServer)
PIString genName(); PIString genName();
virtual void dataReceived(const PIString & from, const PIByteArray & data); virtual void dataReceived(const PIString & from, const PIByteArray & data);
EVENT_HANDLER(void, sysmonDeleted); EVENT_HANDLER(void, sysmonDeleted);
PRIVATE_DECLARATION PRIVATE_DECLARATION(PIP_EXPORT)
PITimer itimer; PITimer itimer;
PISystemMonitor * sysmon; PISystemMonitor * sysmon;
PIMutex sysmon_mutex; PIMutex sysmon_mutex;
}; };
#else #else
# define PIINTROSPECTION_START # define PIINTROSPECTION_START(name)
#endif #endif
#endif // PIINTROSPECTION_SERVER_H #endif // PIINTROSPECTION_SERVER_H

View File

@@ -1,247 +1,247 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Introspection module - Base server structs Introspection module - Base server structs
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "piintrospection_server_p.h" #include "piintrospection_server_p.h"
#include "pichunkstream.h" #include "pichunkstream.h"
#include "piinit.h" #include "piinit.h"
#include "pisysteminfo.h" #include "pisysteminfo.h"
#include "piobject.h" #include "piobject.h"
const uint PIIntrospection::sign = 0x0F1C2B3A; const uint PIIntrospection::sign = 0x0F1C2B3A;
PIIntrospection::RequiredInfo::RequiredInfo() { PIIntrospection::RequiredInfo::RequiredInfo() {
types = itInfo; types = itInfo;
} }
PIIntrospection::ProcessInfo::ProcessInfo() { PIIntrospection::ProcessInfo::ProcessInfo() {
processorsCount = 0; processorsCount = 0;
} }
PIIntrospection::ObjectInfo::ObjectInfo() { PIIntrospection::ObjectInfo::ObjectInfo() {
queued_events = 0; queued_events = 0;
} }
PIIntrospection::ProcessInfo PIIntrospection::getInfo() { PIIntrospection::ProcessInfo PIIntrospection::getInfo() {
PIIntrospection::ProcessInfo ret; PIIntrospection::ProcessInfo ret;
PISystemInfo * si = PISystemInfo::instance(); PISystemInfo * si = PISystemInfo::instance();
ret.architecture = si->architecture; ret.architecture = si->architecture;
ret.execCommand = si->execCommand; ret.execCommand = si->execCommand;
ret.execDateTime = si->execDateTime; ret.execDateTime = si->execDateTime;
ret.hostname = si->hostname; ret.hostname = si->hostname;
ret.OS_name = si->OS_name; ret.OS_name = si->OS_name;
ret.OS_version = si->OS_version; ret.OS_version = si->OS_version;
ret.processorsCount = si->processorsCount; ret.processorsCount = si->processorsCount;
ret.user = si->user; ret.user = si->user;
ret.build_options = PIInit::buildOptions(); ret.build_options = PIInit::buildOptions();
return ret; return ret;
} }
PIVector<PIIntrospection::ObjectInfo> PIIntrospection::getObjects() { PIVector<PIIntrospection::ObjectInfo> PIIntrospection::getObjects() {
PIVector<PIIntrospection::ObjectInfo> ret; PIVector<PIIntrospection::ObjectInfo> ret;
PIObject::mutexObjects().lock(); PIObject::mutexObjects().lock();
const PIVector<PIObject * > & ao(PIObject::objects()); const PIVector<PIObject * > & ao(PIObject::objects());
ret.resize(ao.size()); ret.resize(ao.size());
for (int i = 0; i < ao.size_s(); ++i) { for (int i = 0; i < ao.size_s(); ++i) {
ret[i].classname = PIStringAscii(ao[i]->className()); ret[i].classname = PIStringAscii(ao[i]->className());
ret[i].name = ao[i]->name(); ret[i].name = ao[i]->name();
ret[i].properties = ao[i]->properties(); ret[i].properties = ao[i]->properties();
ret[i].parents = ao[i]->scopeList(); ret[i].parents = ao[i]->scopeList();
ao[i]->mutex_queue.lock(); ao[i]->mutex_queue.lock();
ret[i].queued_events = ao[i]->events_queue.size_s(); ret[i].queued_events = ao[i]->events_queue.size_s();
ao[i]->mutex_queue.unlock(); ao[i]->mutex_queue.unlock();
} }
PIObject::mutexObjects().unlock(); PIObject::mutexObjects().unlock();
return ret; return ret;
} }
PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::RequiredInfo & v) { PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::RequiredInfo & v) {
PIChunkStream cs; PIChunkStream cs;
cs.add(1, v.types); cs.add(1, v.types);
b << cs.data(); b << cs.data();
return b; return b;
} }
PIByteArray & operator >>(PIByteArray & b, PIIntrospection::RequiredInfo & v) { PIByteArray & operator >>(PIByteArray & b, PIIntrospection::RequiredInfo & v) {
PIByteArray csba; b >> csba; PIByteArray csba; b >> csba;
PIChunkStream cs(csba); PIChunkStream cs(csba);
while (!cs.atEnd()) { while (!cs.atEnd()) {
switch (cs.read()) { switch (cs.read()) {
case 1: cs.get(v.types); break; case 1: cs.get(v.types); break;
default: break; default: break;
} }
} }
return b; return b;
} }
PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ProcessInfo & v) { PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ProcessInfo & v) {
PIChunkStream cs; PIChunkStream cs;
cs.add(1, v.architecture).add(2, v.execCommand).add(3, v.execDateTime).add(4, v.hostname).add(5, v.OS_name) 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); .add(6, v.OS_version).add(7, v.processorsCount).add(8, v.user).add(9, v.build_options);
b << cs.data(); b << cs.data();
return b; return b;
} }
PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ProcessInfo & v) { PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ProcessInfo & v) {
PIByteArray csba; b >> csba; PIByteArray csba; b >> csba;
PIChunkStream cs(csba); PIChunkStream cs(csba);
while (!cs.atEnd()) { while (!cs.atEnd()) {
switch (cs.read()) { switch (cs.read()) {
case 1: cs.get(v.architecture); break; case 1: cs.get(v.architecture); break;
case 2: cs.get(v.execCommand); break; case 2: cs.get(v.execCommand); break;
case 3: cs.get(v.execDateTime); break; case 3: cs.get(v.execDateTime); break;
case 4: cs.get(v.hostname); break; case 4: cs.get(v.hostname); break;
case 5: cs.get(v.OS_name); break; case 5: cs.get(v.OS_name); break;
case 6: cs.get(v.OS_version); break; case 6: cs.get(v.OS_version); break;
case 7: cs.get(v.processorsCount); break; case 7: cs.get(v.processorsCount); break;
case 8: cs.get(v.user); break; case 8: cs.get(v.user); break;
case 9: cs.get(v.build_options); break; case 9: cs.get(v.build_options); break;
default: break; default: break;
} }
} }
return b; return b;
} }
PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ObjectInfo & v) { PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ObjectInfo & v) {
PIChunkStream cs; PIChunkStream cs;
cs.add(1, v.classname).add(2, v.name).add(3, v.parents).add(4, v.properties).add(5, v.queued_events); 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(); b << cs.data();
return b; return b;
} }
PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ObjectInfo & v) { PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ObjectInfo & v) {
PIByteArray csba; b >> csba; PIByteArray csba; b >> csba;
PIChunkStream cs(csba); PIChunkStream cs(csba);
while (!cs.atEnd()) { while (!cs.atEnd()) {
switch (cs.read()) { switch (cs.read()) {
case 1: cs.get(v.classname); break; case 1: cs.get(v.classname); break;
case 2: cs.get(v.name); break; case 2: cs.get(v.name); break;
case 3: cs.get(v.parents); break; case 3: cs.get(v.parents); break;
case 4: cs.get(v.properties); break; case 4: cs.get(v.properties); break;
case 5: cs.get(v.queued_events); break; case 5: cs.get(v.queued_events); break;
default: break; default: break;
} }
} }
return b; return b;
} }
PIByteArray PIIntrospection::packInfo() { PIByteArray PIIntrospection::packInfo() {
PIByteArray ret; PIByteArray ret;
ret << getInfo(); ret << getInfo();
return ret; return ret;
} }
void PIIntrospection::unpackInfo(PIByteArray & ba, PIIntrospection::ProcessInfo & info) { void PIIntrospection::unpackInfo(PIByteArray & ba, PIIntrospection::ProcessInfo & info) {
ba >> info; ba >> info;
} }
PIByteArray PIIntrospection::packProcStat(PISystemMonitor * sm) { PIByteArray PIIntrospection::packProcStat(PISystemMonitor * sm) {
ProcessStat ps; ProcessStat ps;
if (sm) { if (sm) {
ps.proc = sm->statistic(); ps.proc = sm->statistic();
ps.threads = sm->threadsStatistic(); ps.threads = sm->threadsStatistic();
} }
PIByteArray ret; PIByteArray ret;
ret << ps.proc << ps.threads; ret << ps.proc << ps.threads;
return ret; return ret;
} }
void PIIntrospection::unpackProcStat(PIByteArray & ba, PIIntrospection::ProcessStat & info) { void PIIntrospection::unpackProcStat(PIByteArray & ba, PIIntrospection::ProcessStat & info) {
ba >> info.proc >> info.threads; ba >> info.proc >> info.threads;
} }
PIByteArray PIIntrospection::packContainers() { PIByteArray PIIntrospection::packContainers() {
PIByteArray ret; PIByteArray ret;
PIVector<PIIntrospectionContainers::TypeInfo> data; PIVector<PIIntrospectionContainers::TypeInfo> data;
PIIntrospectionContainers * p = 0; PIIntrospectionContainers * p = 0;
#ifdef PIP_INTROSPECTION #ifdef PIP_INTROSPECTION
p = PIINTROSPECTION_CONTAINERS->p; p = PIINTROSPECTION_CONTAINERS->p;
#endif #endif
if (p) { if (p) {
data = p->getInfo(); data = p->getInfo();
} }
ret << data; ret << data;
return ret; return ret;
} }
void PIIntrospection::unpackContainers(PIByteArray & ba, PIVector<PIIntrospectionContainers::TypeInfo> & data) { void PIIntrospection::unpackContainers(PIByteArray & ba, PIVector<PIIntrospectionContainers::TypeInfo> & data) {
data.clear(); data.clear();
ba >> data; ba >> data;
} }
PIByteArray PIIntrospection::packThreads() { PIByteArray PIIntrospection::packThreads() {
PIByteArray ret; PIByteArray ret;
PIIntrospectionThreads * p = 0; PIIntrospectionThreads * p = 0;
#ifdef PIP_INTROSPECTION #ifdef PIP_INTROSPECTION
p = PIINTROSPECTION_THREADS->p; p = PIINTROSPECTION_THREADS->p;
#endif #endif
if (p) { if (p) {
p->mutex.lock(); p->mutex.lock();
PIMap<PIThread*, PIIntrospectionThreads::ThreadInfo> & tm(p->threads); PIMap<PIThread*, PIIntrospectionThreads::ThreadInfo> & tm(p->threads);
auto it = tm.makeIterator(); auto it = tm.makeIterator();
while (it.next()) { while (it.next()) {
it.valueRef().classname = PIStringAscii(it.key()->className()); it.valueRef().classname = PIStringAscii(it.key()->className());
it.valueRef().name = it.key()->name(); it.valueRef().name = it.key()->name();
} }
ret << tm.values(); ret << tm.values();
p->mutex.unlock(); p->mutex.unlock();
} else { } else {
ret << PIVector<PIIntrospectionThreads::ThreadInfo>(); ret << PIVector<PIIntrospectionThreads::ThreadInfo>();
} }
return ret; return ret;
} }
void PIIntrospection::unpackThreads(PIByteArray & ba, PIVector<PIIntrospectionThreads::ThreadInfo> & threads) { void PIIntrospection::unpackThreads(PIByteArray & ba, PIVector<PIIntrospectionThreads::ThreadInfo> & threads) {
threads.clear(); threads.clear();
ba >> threads; ba >> threads;
} }
PIByteArray PIIntrospection::packObjects() { PIByteArray PIIntrospection::packObjects() {
PIByteArray ret; PIByteArray ret;
ret << getObjects(); ret << getObjects();
return ret; return ret;
} }
void PIIntrospection::unpackObjects(PIByteArray & ba, PIVector<PIIntrospection::ObjectInfo> & objects) { void PIIntrospection::unpackObjects(PIByteArray & ba, PIVector<PIIntrospection::ObjectInfo> & objects) {
objects.clear(); objects.clear();
ba >> objects; ba >> objects;
} }

View File

@@ -153,6 +153,7 @@ bool PIBinaryLog::openDevice() {
bool PIBinaryLog::closeDevice() { bool PIBinaryLog::closeDevice() {
stopThreadedRead(); stopThreadedRead();
pausemutex.unlock(); pausemutex.unlock();
logmutex.unlock();
moveIndex(-1); moveIndex(-1);
is_indexed = false; is_indexed = false;
index.clear(); index.clear();

View File

@@ -1,501 +1,501 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Process resource monitor Process resource monitor
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "piincludes_p.h" #include "piincludes_p.h"
#include "pisystemmonitor.h" #include "pisystemmonitor.h"
#include "pisysteminfo.h" #include "pisysteminfo.h"
#include "piprocess.h" #include "piprocess.h"
#include "pidir.h" #include "pidir.h"
#include "pitime_win.h" #include "pitime_win.h"
#ifdef WINDOWS #ifdef WINDOWS
# include <psapi.h> # include <psapi.h>
# include <tlhelp32.h> # include <tlhelp32.h>
#endif #endif
#ifdef MAC_OS #ifdef MAC_OS
struct kqueue_id_t; struct kqueue_id_t;
# include <libproc.h> # include <libproc.h>
# include <sys/proc_info.h> # include <sys/proc_info.h>
#endif #endif
#ifdef ESP_PLATFORM #ifdef ESP_PLATFORM
# include "esp_heap_caps.h" # include "esp_heap_caps.h"
#endif #endif
PISystemMonitor::ProcessStatsFixed::ProcessStatsFixed() { PISystemMonitor::ProcessStatsFixed::ProcessStatsFixed() {
ID = parent_ID = group_ID = session_ID = priority = threads = 0; ID = parent_ID = group_ID = session_ID = priority = threads = 0;
physical_memsize = resident_memsize = share_memsize = virtual_memsize = data_memsize = 0; physical_memsize = resident_memsize = share_memsize = virtual_memsize = data_memsize = 0;
cpu_load_user = cpu_load_system = 0.f; cpu_load_user = cpu_load_system = 0.f;
} }
void PISystemMonitor::ProcessStats::makeStrings() { void PISystemMonitor::ProcessStats::makeStrings() {
physical_memsize_readable.setReadableSize(physical_memsize); physical_memsize_readable.setReadableSize(physical_memsize);
resident_memsize_readable.setReadableSize(resident_memsize); resident_memsize_readable.setReadableSize(resident_memsize);
share_memsize_readable.setReadableSize(share_memsize); share_memsize_readable.setReadableSize(share_memsize);
virtual_memsize_readable.setReadableSize(virtual_memsize); virtual_memsize_readable.setReadableSize(virtual_memsize);
data_memsize_readable.setReadableSize(data_memsize); data_memsize_readable.setReadableSize(data_memsize);
} }
PISystemMonitor::ThreadStatsFixed::ThreadStatsFixed() { PISystemMonitor::ThreadStatsFixed::ThreadStatsFixed() {
id = 0; id = 0;
cpu_load_kernel = cpu_load_user = -1.f; cpu_load_kernel = cpu_load_user = -1.f;
} }
#ifndef FREERTOS #ifndef FREERTOS
PRIVATE_DEFINITION_START(PISystemMonitor) PRIVATE_DEFINITION_START(PISystemMonitor)
#ifndef WINDOWS #ifndef WINDOWS
# ifdef MAC_OS # ifdef MAC_OS
PISystemTime PISystemTime
# else # else
llong llong
# endif # endif
cpu_u_cur, cpu_u_prev, cpu_s_cur, cpu_s_prev; cpu_u_cur, cpu_u_prev, cpu_s_cur, cpu_s_prev;
PIString proc_dir; PIString proc_dir;
PIFile file, filem; PIFile file, filem;
#else #else
HANDLE hProc; HANDLE hProc;
PROCESS_MEMORY_COUNTERS mem_cnt; PROCESS_MEMORY_COUNTERS mem_cnt;
PISystemTime tm_kernel, tm_user; PISystemTime tm_kernel, tm_user;
PITimeMeasurer tm; PITimeMeasurer tm;
#endif #endif
PRIVATE_DEFINITION_END(PISystemMonitor) PRIVATE_DEFINITION_END(PISystemMonitor)
#endif #endif
PISystemMonitor::PISystemMonitor(): PIThread() { PISystemMonitor::PISystemMonitor(): PIThread() {
pID_ = cycle = 0; pID_ = cycle = 0;
cpu_count = PISystemInfo::instance()->processorsCount; cpu_count = PISystemInfo::instance()->processorsCount;
#ifndef FREERTOS #ifndef FREERTOS
#ifndef WINDOWS #ifndef WINDOWS
# ifdef QNX # ifdef QNX
page_size = 4096; page_size = 4096;
# else # else
page_size = getpagesize(); page_size = getpagesize();
# endif # endif
#else #else
PRIVATE->hProc = 0; PRIVATE->hProc = 0;
PRIVATE->mem_cnt.cb = sizeof(PRIVATE->mem_cnt); PRIVATE->mem_cnt.cb = sizeof(PRIVATE->mem_cnt);
#endif #endif
#endif #endif
setName("system_monitor"); setName("system_monitor");
} }
PISystemMonitor::~PISystemMonitor() { PISystemMonitor::~PISystemMonitor() {
stop(); stop();
} }
#ifndef FREERTOS #ifndef FREERTOS
bool PISystemMonitor::startOnProcess(int pID, int interval_ms) { bool PISystemMonitor::startOnProcess(int pID, int interval_ms) {
stop(); stop();
pID_ = pID; pID_ = pID;
Pool::instance()->add(this); Pool::instance()->add(this);
cycle = -1; cycle = -1;
#ifndef WINDOWS #ifndef WINDOWS
# ifndef MAC_OS # ifndef MAC_OS
PRIVATE->proc_dir = PIStringAscii("/proc/") + PIString::fromNumber(pID_) + PIStringAscii("/"); PRIVATE->proc_dir = PIStringAscii("/proc/") + PIString::fromNumber(pID_) + PIStringAscii("/");
PRIVATE->file. open(PRIVATE->proc_dir + "stat", PIIODevice::ReadOnly); PRIVATE->file. open(PRIVATE->proc_dir + "stat", PIIODevice::ReadOnly);
PRIVATE->filem.open(PRIVATE->proc_dir + "statm", PIIODevice::ReadOnly); PRIVATE->filem.open(PRIVATE->proc_dir + "statm", PIIODevice::ReadOnly);
if (!PRIVATE->file.isOpened()) { if (!PRIVATE->file.isOpened()) {
piCoutObj << "Can`t find process with ID = " << pID_ << "!"; piCoutObj << "Can`t find process with ID = " << pID_ << "!";
return false; return false;
} }
# endif # endif
#else #else
PRIVATE->hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pID_); PRIVATE->hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pID_);
if (PRIVATE->hProc == 0) { if (PRIVATE->hProc == 0) {
piCoutObj << "Can`t open process with ID = " << pID_ << "," << errorString(); piCoutObj << "Can`t open process with ID = " << pID_ << "," << errorString();
return false; return false;
} }
PRIVATE->tm.reset(); PRIVATE->tm.reset();
#endif #endif
return start(interval_ms); return start(interval_ms);
} }
#endif #endif
bool PISystemMonitor::startOnSelf(int interval_ms) { bool PISystemMonitor::startOnSelf(int interval_ms) {
#ifndef FREERTOS #ifndef FREERTOS
bool ret = startOnProcess(PIProcess::currentPID(), interval_ms); bool ret = startOnProcess(PIProcess::currentPID(), interval_ms);
cycle = -1; cycle = -1;
#else #else
bool ret = start(interval_ms); bool ret = start(interval_ms);
#endif #endif
return ret; return ret;
} }
PIVector<PISystemMonitor::ThreadStats> PISystemMonitor::threadsStatistic() const { PIVector<PISystemMonitor::ThreadStats> PISystemMonitor::threadsStatistic() const {
mutex_.lock(); mutex_.lock();
PIVector<PISystemMonitor::ThreadStats> ret = cur_ts; PIVector<PISystemMonitor::ThreadStats> ret = cur_ts;
mutex_.unlock(); mutex_.unlock();
return ret; return ret;
} }
void PISystemMonitor::setStatistic(const PISystemMonitor::ProcessStats & s) { void PISystemMonitor::setStatistic(const PISystemMonitor::ProcessStats & s) {
PIMutexLocker _ml(stat_mutex); PIMutexLocker _ml(stat_mutex);
stat = s; stat = s;
stat.makeStrings(); stat.makeStrings();
} }
void PISystemMonitor::stop() { void PISystemMonitor::stop() {
PIThread::stop(); PIThread::stop();
#ifdef WINDOWS #ifdef WINDOWS
if (PRIVATE->hProc != 0) { if (PRIVATE->hProc != 0) {
CloseHandle(PRIVATE->hProc); CloseHandle(PRIVATE->hProc);
PRIVATE->hProc = 0; PRIVATE->hProc = 0;
} }
#endif #endif
Pool::instance()->remove(this); Pool::instance()->remove(this);
} }
PISystemMonitor::ProcessStats PISystemMonitor::statistic() const { PISystemMonitor::ProcessStats PISystemMonitor::statistic() const {
PIMutexLocker _ml(stat_mutex); PIMutexLocker _ml(stat_mutex);
return stat; return stat;
} }
#ifdef MAC_OS #ifdef MAC_OS
PISystemTime uint64toST(uint64_t v) { PISystemTime uint64toST(uint64_t v) {
return PISystemTime(((uint*)&(v))[1], ((uint*)&(v))[0]); return PISystemTime(((uint*)&(v))[1], ((uint*)&(v))[0]);
} }
#endif #endif
void PISystemMonitor::run() { void PISystemMonitor::run() {
cur_tm.clear(); cur_tm.clear();
tbid.clear(); tbid.clear();
__PIThreadCollection * pitc = __PIThreadCollection::instance(); __PIThreadCollection * pitc = __PIThreadCollection::instance();
pitc->lock(); pitc->lock();
PIVector<PIThread * > tv = pitc->threads(); PIVector<PIThread * > tv = pitc->threads();
piForeach (PIThread * t, tv) piForeach (PIThread * t, tv)
if (t->isPIObject()) if (t->isPIObject())
tbid[t->tid()] = t->name(); tbid[t->tid()] = t->name();
pitc->unlock(); pitc->unlock();
//piCout << tbid.keys().toType<uint>(); //piCout << tbid.keys().toType<uint>();
ProcessStats tstat; ProcessStats tstat;
tstat.ID = pID_; tstat.ID = pID_;
#ifdef FREERTOS #ifdef FREERTOS
piForeach (PIThread * t, tv) piForeach (PIThread * t, tv)
if (t->isPIObject()) if (t->isPIObject())
gatherThread(t->tid()); gatherThread(t->tid());
#else #else
#ifndef WINDOWS #ifndef WINDOWS
tbid[pID_] = "main"; tbid[pID_] = "main";
# ifdef MAC_OS # ifdef MAC_OS
rusage_info_current ru; rusage_info_current ru;
proc_pid_rusage(pID_, RUSAGE_INFO_CURRENT, (rusage_info_t*)&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]); //piCout << PISystemTime(((uint*)&(ru.ri_user_time))[1], ((uint*)&(ru.ri_user_time))[0]);
if (cycle < 0) { if (cycle < 0) {
PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur = uint64toST(ru.ri_user_time); 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_s_prev = PRIVATE->cpu_s_cur = uint64toST(ru.ri_system_time);
} }
PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur; PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur;
PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur; PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur;
PRIVATE->cpu_u_cur = uint64toST(ru.ri_user_time); PRIVATE->cpu_u_cur = uint64toST(ru.ri_user_time);
PRIVATE->cpu_s_cur = uint64toST(ru.ri_system_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_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_; tstat.cpu_load_user = 100.f * (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_;
cycle = 0; cycle = 0;
//piCout << (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_; //piCout << (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_;
# else # else
PRIVATE->file.seekToBegin(); PRIVATE->file.seekToBegin();
PIString str(PRIVATE->file.readAll(true)); PIString str(PRIVATE->file.readAll(true));
int si = str.find('(') + 1, fi = 0, cc = 1; int si = str.find('(') + 1, fi = 0, cc = 1;
for (int i = si; i < str.size_s(); ++i) { for (int i = si; i < str.size_s(); ++i) {
if (str[i] == '(') cc++; if (str[i] == '(') cc++;
if (str[i] == ')') cc--; if (str[i] == ')') cc--;
if (cc <= 0) { if (cc <= 0) {
fi = i; fi = i;
break; break;
} }
} }
tstat.exec_name = str.mid(si, fi - si); tstat.exec_name = str.mid(si, fi - si);
str.cutMid(si - 1, fi - si + 3); str.cutMid(si - 1, fi - si + 3);
PIStringList sl = str.split(" "); PIStringList sl = str.split(" ");
if (sl.size_s() < 19) return; if (sl.size_s() < 19) return;
tstat.ID = sl[0].toInt(); tstat.ID = sl[0].toInt();
tstat.state = sl[1]; tstat.state = sl[1];
tstat.parent_ID = sl[2].toInt(); tstat.parent_ID = sl[2].toInt();
tstat.group_ID = sl[3].toInt(); tstat.group_ID = sl[3].toInt();
tstat.session_ID = sl[4].toInt(); tstat.session_ID = sl[4].toInt();
if (cycle < 0) { if (cycle < 0) {
PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur = sl[12].toLLong(); PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur = sl[12].toLLong();
PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur = sl[13].toLLong(); PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur = sl[13].toLLong();
} }
PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur; PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur;
PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur; PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur;
PRIVATE->cpu_u_cur = sl[12].toLLong(); PRIVATE->cpu_u_cur = sl[12].toLLong();
PRIVATE->cpu_s_cur = sl[13].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_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_user = (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev) / (delay_ / 1000.);
tstat.cpu_load_system /= cpu_count; tstat.cpu_load_system /= cpu_count;
tstat.cpu_load_user /= cpu_count; tstat.cpu_load_user /= cpu_count;
cycle = 0; cycle = 0;
tstat.priority = sl[16].toInt(); tstat.priority = sl[16].toInt();
tstat.threads = sl[18].toInt(); tstat.threads = sl[18].toInt();
//piCout << "\n"; //piCout << "\n";
//piCout << sl[0] << sl[12] << sl[13]; //piCout << sl[0] << sl[12] << sl[13];
PRIVATE->filem.seekToBegin(); PRIVATE->filem.seekToBegin();
str = PRIVATE->filem.readAll(true); str = PRIVATE->filem.readAll(true);
sl = str.split(" "); sl = str.split(" ");
if (sl.size_s() < 6) return; if (sl.size_s() < 6) return;
tstat.virtual_memsize = sl[0].toLong() * page_size; tstat.virtual_memsize = sl[0].toLong() * page_size;
tstat.resident_memsize = sl[1].toLong() * page_size; tstat.resident_memsize = sl[1].toLong() * page_size;
tstat.share_memsize = sl[2].toLong() * page_size; tstat.share_memsize = sl[2].toLong() * page_size;
tstat.data_memsize = sl[5].toLong() * page_size; tstat.data_memsize = sl[5].toLong() * page_size;
tstat.physical_memsize = tstat.resident_memsize - tstat.share_memsize; tstat.physical_memsize = tstat.resident_memsize - tstat.share_memsize;
PIVector<PIFile::FileInfo> tld = PIDir(PRIVATE->proc_dir + "task").entries(); PIVector<PIFile::FileInfo> tld = PIDir(PRIVATE->proc_dir + "task").entries();
piForeachC (PIFile::FileInfo & i, tld) { piForeachC (PIFile::FileInfo & i, tld) {
if (i.flags[PIFile::FileInfo::Dot] || i.flags[PIFile::FileInfo::DotDot]) if (i.flags[PIFile::FileInfo::Dot] || i.flags[PIFile::FileInfo::DotDot])
continue; continue;
gatherThread(i.name().toInt()); gatherThread(i.name().toInt());
} }
# endif # endif
#else #else
if (GetProcessMemoryInfo(PRIVATE->hProc, &PRIVATE->mem_cnt, sizeof(PRIVATE->mem_cnt)) != 0) { if (GetProcessMemoryInfo(PRIVATE->hProc, &PRIVATE->mem_cnt, sizeof(PRIVATE->mem_cnt)) != 0) {
tstat.physical_memsize = PRIVATE->mem_cnt.WorkingSetSize; tstat.physical_memsize = PRIVATE->mem_cnt.WorkingSetSize;
} }
tstat.priority = GetPriorityClass(PRIVATE->hProc); tstat.priority = GetPriorityClass(PRIVATE->hProc);
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, pID_); HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, pID_);
int thcnt = 0; int thcnt = 0;
if (snap != 0) { if (snap != 0) {
THREADENTRY32 thread; THREADENTRY32 thread;
thread.dwSize = sizeof(THREADENTRY32); thread.dwSize = sizeof(THREADENTRY32);
if (Thread32First(snap, &thread) == TRUE) { if (Thread32First(snap, &thread) == TRUE) {
if (thread.th32OwnerProcessID == DWORD(pID_)) { if (thread.th32OwnerProcessID == DWORD(pID_)) {
++thcnt; ++thcnt;
gatherThread(thread.th32ThreadID); gatherThread(thread.th32ThreadID);
} }
while (Thread32Next(snap, &thread) == TRUE) { while (Thread32Next(snap, &thread) == TRUE) {
if (thread.th32OwnerProcessID == DWORD(pID_)) { if (thread.th32OwnerProcessID == DWORD(pID_)) {
++thcnt; ++thcnt;
gatherThread(thread.th32ThreadID); gatherThread(thread.th32ThreadID);
} }
//piCout << thread.th32ThreadID; //piCout << thread.th32ThreadID;
} }
} }
tstat.threads = thcnt; tstat.threads = thcnt;
CloseHandle(snap); CloseHandle(snap);
} }
FILETIME ft0, ft1, ft_kernel, ft_user; FILETIME ft0, ft1, ft_kernel, ft_user;
double el_s = PRIVATE->tm.elapsed_s() * cpu_count / 100.; double el_s = PRIVATE->tm.elapsed_s() * cpu_count / 100.;
if (GetProcessTimes(PRIVATE->hProc, &ft0, &ft1, &ft_kernel, &ft_user) != 0) { if (GetProcessTimes(PRIVATE->hProc, &ft0, &ft1, &ft_kernel, &ft_user) != 0) {
PISystemTime tm_kernel_c = FILETIME2PISystemTime(ft_kernel); PISystemTime tm_kernel_c = FILETIME2PISystemTime(ft_kernel);
PISystemTime tm_user_c = FILETIME2PISystemTime(ft_user); PISystemTime tm_user_c = FILETIME2PISystemTime(ft_user);
if (cycle < 0) { if (cycle < 0) {
PRIVATE->tm_kernel = tm_kernel_c; PRIVATE->tm_kernel = tm_kernel_c;
PRIVATE->tm_user = tm_user_c; PRIVATE->tm_user = tm_user_c;
} }
cycle = 0; cycle = 0;
if (el_s <= 0.) { if (el_s <= 0.) {
tstat.cpu_load_system = 0.f; tstat.cpu_load_system = 0.f;
tstat.cpu_load_user = 0.f; tstat.cpu_load_user = 0.f;
} else { } else {
tstat.cpu_load_system = (tm_kernel_c - PRIVATE->tm_kernel).toSeconds() / el_s; 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; tstat.cpu_load_user = (tm_user_c - PRIVATE->tm_user).toSeconds() / el_s;
} }
PRIVATE->tm_kernel = tm_kernel_c; PRIVATE->tm_kernel = tm_kernel_c;
PRIVATE->tm_user = tm_user_c; PRIVATE->tm_user = tm_user_c;
} else { } else {
tstat.cpu_load_system = 0.f; tstat.cpu_load_system = 0.f;
tstat.cpu_load_user = 0.f; tstat.cpu_load_user = 0.f;
} }
PRIVATE->tm.reset(); PRIVATE->tm.reset();
#endif #endif
#endif #endif
tstat.cpu_load_system = piClampf(tstat.cpu_load_system, 0.f, 100.f); 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); tstat.cpu_load_user = piClampf(tstat.cpu_load_user , 0.f, 100.f);
auto i = cur_tm.makeIterator(); auto i = cur_tm.makeIterator();
while (i.next()) { while (i.next()) {
if (!last_tm.contains(i.key())) continue; if (!last_tm.contains(i.key())) continue;
ThreadStats & ts_new(i.valueRef()); ThreadStats & ts_new(i.valueRef());
ThreadStats & ts_old(last_tm[i.key()]); 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_kernel = calcThreadUsage(ts_new.kernel_time, ts_old.kernel_time);
ts_new.cpu_load_user = calcThreadUsage(ts_new.user_time, ts_old.user_time); ts_new.cpu_load_user = calcThreadUsage(ts_new.user_time, ts_old.user_time);
//piCout << ts_new.cpu_load_user; //piCout << ts_new.cpu_load_user;
} }
last_tm = cur_tm; last_tm = cur_tm;
lock(); mutex_.lock();
cur_ts = cur_tm.values(); cur_ts = cur_tm.values();
unlock(); mutex_.unlock();
tstat.ram_total = totalRAM(); tstat.ram_total = totalRAM();
tstat.ram_used = usedRAM(); tstat.ram_used = usedRAM();
tstat.ram_free = freeRAM(); tstat.ram_free = freeRAM();
stat_mutex.lock(); stat_mutex.lock();
stat = tstat; stat = tstat;
stat.makeStrings(); stat.makeStrings();
stat_mutex.unlock(); stat_mutex.unlock();
} }
void PISystemMonitor::gatherThread(llong id) { void PISystemMonitor::gatherThread(llong id) {
PISystemMonitor::ThreadStats ts; PISystemMonitor::ThreadStats ts;
ts.id = id; ts.id = id;
#ifdef FREERTOS #ifdef FREERTOS
ts.name = tbid.value(id, "<PIThread>"); ts.name = tbid.value(id, "<PIThread>");
#else #else
ts.name = tbid.value(id, "<non-PIThread>"); ts.name = tbid.value(id, "<non-PIThread>");
# ifndef WINDOWS # ifndef WINDOWS
PIFile f(PRIVATE->proc_dir + "task/" + PIString::fromNumber(id) + "/stat"); PIFile f(PRIVATE->proc_dir + "task/" + PIString::fromNumber(id) + "/stat");
//piCout << f.path(); //piCout << f.path();
if (!f.open(PIIODevice::ReadOnly)) if (!f.open(PIIODevice::ReadOnly))
return; return;
PIString str = f.readAll(true); PIString str = f.readAll(true);
int si = str.find('(') + 1, fi = 0, cc = 1; int si = str.find('(') + 1, fi = 0, cc = 1;
for (int i = si; i < str.size_s(); ++i) { for (int i = si; i < str.size_s(); ++i) {
if (str[i] == '(') cc++; if (str[i] == '(') cc++;
if (str[i] == ')') cc--; if (str[i] == ')') cc--;
if (cc <= 0) { if (cc <= 0) {
fi = i; fi = i;
break; break;
} }
} }
str.cutMid(si - 1, fi - si + 3); str.cutMid(si - 1, fi - si + 3);
PIStringList sl = str.split(" "); PIStringList sl = str.split(" ");
if (sl.size_s() < 14) return; if (sl.size_s() < 14) return;
//piCout << sl[0] << sl[12] << sl[13]; //piCout << sl[0] << sl[12] << sl[13];
ts.user_time = PISystemTime::fromMilliseconds(sl[12].toInt() * 10.); ts.user_time = PISystemTime::fromMilliseconds(sl[12].toInt() * 10.);
ts.kernel_time = PISystemTime::fromMilliseconds(sl[13].toInt() * 10.); ts.kernel_time = PISystemTime::fromMilliseconds(sl[13].toInt() * 10.);
# else # else
PISystemTime ct = PISystemTime::current(); PISystemTime ct = PISystemTime::current();
FILETIME times[4]; FILETIME times[4];
HANDLE thdl = OpenThread(THREAD_QUERY_INFORMATION, FALSE, DWORD(id)); HANDLE thdl = OpenThread(THREAD_QUERY_INFORMATION, FALSE, DWORD(id));
if (thdl == NULL) { if (thdl == NULL) {
piCout << "[PISystemMonitor] gatherThread(" << id << "):: OpenThread() error:" << errorString(); piCout << "[PISystemMonitor] gatherThread(" << id << "):: OpenThread() error:" << errorString();
return; return;
} }
if (GetThreadTimes(thdl, &(times[0]), &(times[1]), &(times[2]), &(times[3])) == 0) { if (GetThreadTimes(thdl, &(times[0]), &(times[1]), &(times[2]), &(times[3])) == 0) {
piCout << "[PISystemMonitor] gatherThread(" << id << "):: GetThreadTimes() error:" << errorString(); piCout << "[PISystemMonitor] gatherThread(" << id << "):: GetThreadTimes() error:" << errorString();
return; return;
} }
CloseHandle(thdl); CloseHandle(thdl);
ts.created = FILETIME2PIDateTime(times[0]); ts.created = FILETIME2PIDateTime(times[0]);
ts.work_time = ct - ts.created.toSystemTime(); ts.work_time = ct - ts.created.toSystemTime();
ts.kernel_time = FILETIME2PISystemTime(times[2]); ts.kernel_time = FILETIME2PISystemTime(times[2]);
ts.user_time = FILETIME2PISystemTime(times[3]); ts.user_time = FILETIME2PISystemTime(times[3]);
# endif # endif
#endif #endif
cur_tm[id] = ts; cur_tm[id] = ts;
} }
float PISystemMonitor::calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old) { float PISystemMonitor::calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old) {
if (delay_ <= 0) return -1.; if (delay_ <= 0) return -1.;
return piClampf(100. * ((t_new - t_old).toMilliseconds() / delay_), 0.f, 100.f); return piClampf(100. * ((t_new - t_old).toMilliseconds() / delay_), 0.f, 100.f);
} }
ullong PISystemMonitor::totalRAM() { ullong PISystemMonitor::totalRAM() {
#ifdef ESP_PLATFORM #ifdef ESP_PLATFORM
multi_heap_info_t heap_info; multi_heap_info_t heap_info;
memset(&heap_info, 0, sizeof(multi_heap_info_t)); memset(&heap_info, 0, sizeof(multi_heap_info_t));
heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT); heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
return heap_info.total_allocated_bytes + heap_info.total_free_bytes; return heap_info.total_allocated_bytes + heap_info.total_free_bytes;
#endif #endif
return 0; return 0;
} }
ullong PISystemMonitor::freeRAM() { ullong PISystemMonitor::freeRAM() {
#ifdef ESP_PLATFORM #ifdef ESP_PLATFORM
multi_heap_info_t heap_info; multi_heap_info_t heap_info;
memset(&heap_info, 0, sizeof(multi_heap_info_t)); memset(&heap_info, 0, sizeof(multi_heap_info_t));
heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT); heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
return heap_info.total_free_bytes; return heap_info.total_free_bytes;
#endif #endif
return 0; return 0;
} }
ullong PISystemMonitor::usedRAM() { ullong PISystemMonitor::usedRAM() {
#ifdef ESP_PLATFORM #ifdef ESP_PLATFORM
multi_heap_info_t heap_info; multi_heap_info_t heap_info;
memset(&heap_info, 0, sizeof(multi_heap_info_t)); memset(&heap_info, 0, sizeof(multi_heap_info_t));
heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT); heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
return heap_info.total_allocated_bytes; return heap_info.total_allocated_bytes;
#endif #endif
return 0; return 0;
} }
PISystemMonitor::Pool * PISystemMonitor::Pool::instance() { PISystemMonitor::Pool * PISystemMonitor::Pool::instance() {
static Pool ret; static Pool ret;
return &ret; return &ret;
} }
PISystemMonitor * PISystemMonitor::Pool::getByPID(int pID) { PISystemMonitor * PISystemMonitor::Pool::getByPID(int pID) {
PIMutexLocker _ml(mutex); PIMutexLocker _ml(mutex);
return sysmons.value(pID, 0); return sysmons.value(pID, 0);
} }
void PISystemMonitor::Pool::add(PISystemMonitor * sm) { void PISystemMonitor::Pool::add(PISystemMonitor * sm) {
PIMutexLocker _ml(mutex); PIMutexLocker _ml(mutex);
sysmons[sm->pID()] = sm; sysmons[sm->pID()] = sm;
} }
void PISystemMonitor::Pool::remove(PISystemMonitor * sm) { void PISystemMonitor::Pool::remove(PISystemMonitor * sm) {
PIMutexLocker _ml(mutex); PIMutexLocker _ml(mutex);
sysmons.remove(sm->pID()); sysmons.remove(sm->pID());
} }
PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ProcessStats & v) { PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ProcessStats & v) {
s << PIByteArray::RawData(&v, sizeof(PISystemMonitor::ProcessStatsFixed)) s << PIByteArray::RawData(&v, sizeof(PISystemMonitor::ProcessStatsFixed))
<< v.exec_name << v.state; << v.exec_name << v.state;
return s; return s;
} }
PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ProcessStats & v) { PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ProcessStats & v) {
s >> PIByteArray::RawData(&v, sizeof(PISystemMonitor::ProcessStatsFixed)) s >> PIByteArray::RawData(&v, sizeof(PISystemMonitor::ProcessStatsFixed))
>> v.exec_name >> v.state; >> v.exec_name >> v.state;
v.makeStrings(); v.makeStrings();
return s; return s;
} }
PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ThreadStats & v) { PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ThreadStats & v) {
s << PIByteArray::RawData(&v, sizeof(PISystemMonitor::ThreadStatsFixed)) s << PIByteArray::RawData(&v, sizeof(PISystemMonitor::ThreadStatsFixed))
<< v.name << v.created; << v.name;
return s; return s;
} }
PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ThreadStats & v) { PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ThreadStats & v) {
s >> PIByteArray::RawData(&v, sizeof(PISystemMonitor::ThreadStatsFixed)) s >> PIByteArray::RawData(&v, sizeof(PISystemMonitor::ThreadStatsFixed))
>> v.name >> v.created; >> v.name;
return s; return s;
} }

View File

@@ -1,144 +1,144 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Process resource monitor Process resource monitor
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PISYSTEMMONITOR_H #ifndef PISYSTEMMONITOR_H
#define PISYSTEMMONITOR_H #define PISYSTEMMONITOR_H
#include "pithread.h" #include "pithread.h"
#include "pifile.h" #include "pifile.h"
class PIP_EXPORT PISystemMonitor: public PIThread class PIP_EXPORT PISystemMonitor: public PIThread
{ {
PIOBJECT_SUBCLASS(PISystemMonitor, PIThread) PIOBJECT_SUBCLASS(PISystemMonitor, PIThread)
friend class PIIntrospectionServer; friend class PIIntrospectionServer;
public: public:
PISystemMonitor(); PISystemMonitor();
~PISystemMonitor(); ~PISystemMonitor();
#pragma pack(push, 1) #pragma pack(push, 1)
struct PIP_EXPORT ProcessStatsFixed { struct PIP_EXPORT ProcessStatsFixed {
ProcessStatsFixed(); ProcessStatsFixed();
int ID; int ID;
int parent_ID; int parent_ID;
int group_ID; int group_ID;
int session_ID; int session_ID;
int priority; int priority;
int threads; int threads;
ullong physical_memsize; ullong physical_memsize;
ullong resident_memsize; ullong resident_memsize;
ullong share_memsize; ullong share_memsize;
ullong virtual_memsize; ullong virtual_memsize;
ullong data_memsize; ullong data_memsize;
ullong ram_total; ullong ram_total;
ullong ram_free; ullong ram_free;
ullong ram_used; ullong ram_used;
float cpu_load_system; float cpu_load_system;
float cpu_load_user; float cpu_load_user;
}; };
struct PIP_EXPORT ThreadStatsFixed { struct PIP_EXPORT ThreadStatsFixed {
ThreadStatsFixed(); ThreadStatsFixed();
llong id; llong id;
PISystemTime work_time; PISystemTime work_time;
PISystemTime kernel_time; PISystemTime kernel_time;
PISystemTime user_time; PISystemTime user_time;
float cpu_load_kernel; float cpu_load_kernel;
float cpu_load_user; float cpu_load_user;
}; PIDateTime created;
#pragma pack(pop) };
#pragma pack(pop)
struct PIP_EXPORT ProcessStats: ProcessStatsFixed {
void makeStrings(); struct PIP_EXPORT ProcessStats: ProcessStatsFixed {
PIString exec_name; void makeStrings();
PIString state; PIString exec_name;
PIString physical_memsize_readable; PIString state;
PIString resident_memsize_readable; PIString physical_memsize_readable;
PIString share_memsize_readable; PIString resident_memsize_readable;
PIString virtual_memsize_readable; PIString share_memsize_readable;
PIString data_memsize_readable; PIString virtual_memsize_readable;
}; PIString data_memsize_readable;
};
struct PIP_EXPORT ThreadStats: ThreadStatsFixed {
PIString name; struct PIP_EXPORT ThreadStats: ThreadStatsFixed {
PIDateTime created; PIString name;
}; };
#ifndef FREERTOS #ifndef FREERTOS
bool startOnProcess(int pID, int interval_ms = 1000); bool startOnProcess(int pID, int interval_ms = 1000);
#endif #endif
bool startOnSelf(int interval_ms = 1000); bool startOnSelf(int interval_ms = 1000);
void stop(); void stop();
int pID() const {return pID_;} int pID() const {return pID_;}
ProcessStats statistic() const; ProcessStats statistic() const;
PIVector<ThreadStats> threadsStatistic() const; PIVector<ThreadStats> threadsStatistic() const;
void setStatistic(const ProcessStats & s); void setStatistic(const ProcessStats & s);
static ullong totalRAM(); static ullong totalRAM();
static ullong freeRAM(); static ullong freeRAM();
static ullong usedRAM(); static ullong usedRAM();
private: private:
void run(); void run();
void gatherThread(llong id); void gatherThread(llong id);
float calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old); float calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old);
ProcessStats stat; ProcessStats stat;
PIVector<ThreadStats> cur_ts; PIVector<ThreadStats> cur_ts;
PIMap<llong, ThreadStats> last_tm, cur_tm; PIMap<llong, ThreadStats> last_tm, cur_tm;
PIMap<llong, PIString> tbid; PIMap<llong, PIString> tbid;
mutable PIMutex stat_mutex; mutable PIMutex stat_mutex;
int pID_, page_size, cpu_count, cycle; int pID_, page_size, cpu_count, cycle;
#ifndef FREERTOS #ifndef FREERTOS
PRIVATE_DECLARATION(PIP_EXPORT) PRIVATE_DECLARATION(PIP_EXPORT)
#endif #endif
class PIP_EXPORT Pool { class PIP_EXPORT Pool {
friend class PISystemMonitor; friend class PISystemMonitor;
public: public:
static Pool * instance(); static Pool * instance();
PISystemMonitor * getByPID(int pID); PISystemMonitor * getByPID(int pID);
private: private:
void add(PISystemMonitor * sm); void add(PISystemMonitor * sm);
void remove(PISystemMonitor * sm); void remove(PISystemMonitor * sm);
PIMap<int, PISystemMonitor*> sysmons; PIMap<int, PISystemMonitor*> sysmons;
PIMutex mutex; PIMutex mutex;
}; };
}; };
inline PICout operator <<(PICout s, const PISystemMonitor::ThreadStats & v) { inline PICout operator <<(PICout s, const PISystemMonitor::ThreadStats & v) {
s.setControl(0, true); s.setControl(0, true);
s << "ThreadInfo(\"" << v.name << "\", created " << v.created s << "ThreadInfo(\"" << v.name << "\", created " << v.created
<< ", work " << v.work_time.toMilliseconds() << " ms" << ", work " << v.work_time.toMilliseconds() << " ms"
<< ", kernel " << v.kernel_time.toMilliseconds() << " ms" << ", kernel " << v.kernel_time.toMilliseconds() << " ms"
<< ", user " << v.user_time.toMilliseconds() << " ms" << ", user " << v.user_time.toMilliseconds() << " ms"
<< ")\n"; << ")\n";
s.restoreControl(); s.restoreControl();
return s; return s;
} }
PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ProcessStats & v); 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, PISystemMonitor::ProcessStats & v);
PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ThreadStats & v); PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ThreadStats & v);
PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ThreadStats & v); PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ThreadStats & v);
#endif // PISYSTEMMONITOR_H #endif // PISYSTEMMONITOR_H

View File

@@ -332,7 +332,7 @@ void usage() {
int main(int argc, char * argv[]) { int main(int argc, char * argv[]) {
sys_mon.startOnSelf(); sys_mon.startOnSelf();
PIINTROSPECTION_START PIINTROSPECTION_START(pisd)
//piDebug = false; //piDebug = false;
PICLI cli(argc, argv); PICLI cli(argc, argv);
cli.addArgument("help"); cli.addArgument("help");