diff --git a/libs/main/core/pibytearray.h b/libs/main/core/pibytearray.h
index 687a4d76..f9c81938 100644
--- a/libs/main/core/pibytearray.h
+++ b/libs/main/core/pibytearray.h
@@ -1,520 +1,556 @@
-/*! \file pibytearray.h
- * \brief Byte array
-*/
-/*
- PIP - Platform Independent Primitives
- Byte array
- Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see .
-*/
-
-#ifndef PIBYTEARRAY_H
-#define PIBYTEARRAY_H
-
-#include "pichar.h"
-#include "pibitarray.h"
-#include "pimap.h"
-#include "pivector2d.h"
-
-class PIString;
-class PIByteArray;
-
-
-class PIP_EXPORT PIByteArray: public PIDeque
-{
-public:
-
- //! Constructs an empty byte array
- PIByteArray() {;}
-
- PIByteArray(const PIByteArray & o): PIDeque(o) {}
-
- PIByteArray(PIByteArray && o): PIDeque(std::move(o)) {}
-
- //! Constructs 0-filled byte array with size "size"
- PIByteArray(const uint size) {resize(size);}
-
- //! Constructs byte array from data "data" and size "size"
- PIByteArray(const void * data, const uint size): PIDeque((const uchar*)data, size_t(size)) {}
-
- //! Constructs byte array with size "size" filled by "t"
- PIByteArray(const uint size, uchar t): PIDeque(size, t) {}
-
-
- //! Help struct to store/restore custom blocks of data to/from PIByteArray
- struct RawData {
- friend PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v);
- friend PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v);
- public:
- //! Constructs data block
- RawData(void * data = 0, int size = 0) {d = data; s = size;}
- RawData(const RawData & o) {d = o.d; s = o.s;}
- //! Constructs data block
- RawData(const void * data, const int size) {d = const_cast(data); s = size;}
- RawData & operator =(const RawData & o) {d = o.d; s = o.s; return *this;}
- private:
- void * d;
- int s;
- };
-
- //! Return resized byte array
- PIByteArray resized(uint new_size) const {PIByteArray ret(new_size); memcpy(ret.data(), data(), new_size); return ret;}
-
- //! Convert data to Base 64 and return this byte array
- PIByteArray & convertToBase64();
-
- //! Convert data from Base 64 and return this byte array
- PIByteArray & convertFromBase64();
-
- //! Return converted to Base 64 data
- PIByteArray toBase64() const;
-
- //! Return converted from Base 64 data
-
- PIByteArray & compressRLE(uchar threshold = 192);
- PIByteArray & decompressRLE(uchar threshold = 192);
- PIByteArray compressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.compressRLE(threshold); return ba;}
- PIByteArray decompressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.decompressRLE(threshold); return ba;}
-
- PIString toString(int base = 16) const;
- PIString toHex() const;
-
- //! Add to the end data "data" with size "size"
- PIByteArray & append(const void * data_, int size_) {uint ps = size(); enlarge(size_); memcpy(data(ps), data_, size_); return *this;}
-
- //! Add to the end byte array "data"
- PIByteArray & append(const PIByteArray & data_) {uint ps = size(); enlarge(data_.size_s()); memcpy(data(ps), data_.data(), data_.size()); return *this;}
-
- //! Add to the end "t"
- PIByteArray & append(uchar t) {push_back(t); return *this;}
-
- //! Returns plain 8-bit checksum
- uchar checksumPlain8() const;
-
- //! Returns plain 32-bit checksum
- uint checksumPlain32() const;
-
- //! Returns hash
- uint hash() const;
-
- void operator =(const PIDeque & d) {resize(d.size()); memcpy(data(), d.data(), d.size());}
-
- PIByteArray & operator =(const PIByteArray & o) {if (this == &o) return *this; clear(); append(o); return *this;}
-
- PIByteArray & operator =(PIByteArray && o) {swap(o); return *this;}
-
- static PIByteArray fromUserInput(PIString str);
- static PIByteArray fromHex(PIString str);
- static PIByteArray fromBase64(const PIByteArray & base64);
- static PIByteArray fromBase64(const PIString & base64);
-
-
- class StreamRef {
- public:
- StreamRef(PIByteArray & s): ba(s) {}
- operator PIByteArray&() {return ba;}
- private:
- PIByteArray & ba;
- };
-
-};
-
-//! \relatesalso PIByteArray \brief Byte arrays compare operator
-inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) {
- if (v0.size() == v1.size()) {
- for (uint i = 0; i < v0.size(); ++i)
- if (v0[i] != v1[i])
- return v0[i] < v1[i];
- return false;
- }
- return v0.size() < v1.size();
-}
-
-//! \relatesalso PIByteArray \brief Byte arrays compare operator
-inline bool operator ==(PIByteArray & f, PIByteArray & s) {
- if (f.size_s() != s.size_s())
- return false;
- for (int i = 0; i < f.size_s(); ++i)
- if (f[i] != s[i])
- return false;
- return true;
-}
-
-//! \relatesalso PIByteArray \brief Byte arrays compare operator
-inline bool operator !=(PIByteArray & f, PIByteArray & s) {
- if (f.size_s() != s.size_s())
- return true;
- for (int i = 0; i < f.size_s(); ++i)
- if (f[i] != s[i])
- return true;
- return false;
-}
-
-#ifdef PIP_STD_IOSTREAM
-//! \relatesalso PIByteArray \brief Output to std::ostream operator
-inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba);
-#endif
-
-//! \relatesalso PIByteArray \brief Output to PICout operator
-PIP_EXPORT PICout operator <<(PICout s, const PIByteArray & ba);
-
-
-
-
-// store operators for basic types
-
-
-//! \relatesalso PIByteArray \brief Store operator
-inline PIByteArray & operator <<(PIByteArray & s, const bool v) {s.push_back(v); return s;}
-
-//! \relatesalso PIByteArray \brief Store operator
-inline PIByteArray & operator <<(PIByteArray & s, const char v) {s.push_back(v); return s;}
-
-//! \relatesalso PIByteArray \brief Store operator
-inline PIByteArray & operator <<(PIByteArray & s, const uchar v) {s.push_back(v); return s;}
-
-//! \relatesalso PIByteArray \brief Store operator for any trivial copyable type
-template::value, int>::type = 0>
-inline PIByteArray::StreamRef operator <<(PIByteArray & s, const T & v) {
- int os = s.size_s();
- s.enlarge(sizeof(v));
- memcpy(s.data(os), &v, sizeof(v));
- return s;
-}
-
-//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details
-PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v);
-
-//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details
-inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {
- int os = s.size_s();
- if (v.s > 0) {
- s.enlarge(v.s);
- memcpy(s.data(os), v.d, v.s);
- }
- return s;
-}
-
-//! \relatesalso PIByteArray \brief Store operator for PIVector of any trivial copyable type
-template::value, int>::type = 0,
- typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
-inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) {
- s << int(v.size_s());
- int os = s.size_s();
- if (v.size_s() > 0) {
- s.enlarge(v.size_s()*sizeof(T));
- memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
- }
- return s;
-}
-template::value, int>::type = 0,
- typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
-inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) {
- s << int(v.size_s());
- for (uint i = 0; i < v.size(); ++i) s << v[i];
- return s;
-}
-
-//! \relatesalso PIByteArray \brief Store operator for PIDeque of any trivial copyable type
-template::value, int>::type = 0,
- typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
-inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) {
- s << int(v.size_s());
- int os = s.size_s();
- if (v.size_s() > 0) {
- s.enlarge(v.size_s()*sizeof(T));
- memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
- }
- return s;
-}
-template::value, int>::type = 0,
- typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
-inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) {
- s << int(v.size_s());
- for (uint i = 0; i < v.size(); ++i) s << v[i];
- return s;
-}
-
-//! \relatesalso PIByteArray \brief Store operator for PIVector2D of any trivial copyable type
-template::value, int>::type = 0,
- typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
-inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D & v) {
- s << int(v.rows()) << int(v.cols());
- int os = s.size_s();
- if (v.size_s() > 0) {
- s.enlarge(v.size_s()*sizeof(T));
- memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
- }
- return s;
-}
-template::value, int>::type = 0,
- typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
-inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D & v) {
- s << int(v.rows()) << int(v.cols()) << v.toPlainVector();
- return s;
-}
-
-//! \relatesalso PIByteArray \brief Store operator
-inline PIByteArray & operator <<(PIByteArray & s, const PIBitArray & v) {s << v.size_ << v.data_; return s;}
-
-//! \relatesalso PIPair \brief Store operator
-template
-inline PIByteArray & operator <<(PIByteArray & s, const PIPair & v) {s << v.first << v.second; return s;}
-
-
-
-
-// restore operators for basic types
-
-
-//! \relatesalso PIByteArray \brief Restore operator
-inline PIByteArray & operator >>(PIByteArray & s, bool & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
-
-//! \relatesalso PIByteArray \brief Restore operator
-inline PIByteArray & operator >>(PIByteArray & s, char & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
-
-//! \relatesalso PIByteArray \brief Restore operator
-inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
-
-//! \relatesalso PIByteArray \brief Restore operator for any trivial copyable type
-template::value, int>::type = 0>
-inline PIByteArray::StreamRef operator >>(PIByteArray & s, T & v) {
- assert(s.size() >= sizeof(v));
- memcpy((void*)(&v), s.data(), sizeof(v));
- s.remove(0, sizeof(v));
- return s;
-}
-
-//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
-PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIByteArray & v);
-
-//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
-inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {
- assert(s.size_s() >= v.s);
- if (v.s > 0) {
- memcpy((void*)(v.d), s.data(), v.s);
- s.remove(0, v.s);
- }
- return s;
-}
-
-//! \relatesalso PIByteArray \brief Restore operator for PIVector of any trivial copyable type
-template::value, int>::type = 0,
- typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
-inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) {
- assert(s.size_s() >= 4);
- int sz; s >> sz;
- v._resizeRaw(sz);
- if (sz > 0) {
- memcpy(v.data(), s.data(), sz*sizeof(T));
- s.remove(0, sz*sizeof(T));
- }
- return s;
-}
-template::value, int>::type = 0,
- typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
-inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) {
- assert(s.size_s() >= 4);
- int sz; s >> sz;
- v.resize(sz);
- for (int i = 0; i < sz; ++i) s >> v[i];
- return s;
-}
-
-//! \relatesalso PIByteArray \brief Restore operator for PIDeque of any trivial copyable type
-template::value, int>::type = 0,
- typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
-inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) {
- assert(s.size_s() >= 4);
- int sz; s >> sz;
- v._resizeRaw(sz);
- if (sz > 0) {
- memcpy(v.data(), s.data(), sz*sizeof(T));
- s.remove(0, sz*sizeof(T));
- }
- return s;
-}
-template::value, int>::type = 0,
- typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
-inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) {
- assert(s.size_s() >= 4);
- int sz; s >> sz;
- v.resize(sz);
- for (int i = 0; i < sz; ++i) s >> v[i];
- return s;
-}
-
-//! \relatesalso PIByteArray \brief Restore operator for PIVector2D of any trivial copyable type
-template::value, int>::type = 0,
- typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
-inline PIByteArray & operator >>(PIByteArray & s, PIVector2D & v) {
- assert(s.size_s() >= 8);
- int r, c; s >> r >> c;
- v._resizeRaw(r, c);
- int sz = r*c;
- if (sz > 0) {
- memcpy(v.data(), s.data(), sz*sizeof(T));
- s.remove(0, sz*sizeof(T));
- }
- return s;
-}
-template::value, int>::type = 0,
- typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
-inline PIByteArray & operator >>(PIByteArray & s, PIVector2D & v) {
- assert(s.size_s() >= 8);
- int r,c;
- PIVector tmp;
- s >> r >> c >> tmp;
- v = PIVector2D(r, c, tmp);
- return s;
-}
-
-//! \relatesalso PIByteArray \brief Restore operator
-inline PIByteArray & operator >>(PIByteArray & s, PIBitArray & v) {assert(s.size_s() >= 8); s >> v.size_ >> v.data_; return s;}
-
-//! \relatesalso PIPair \brief Restore operator
-template
-inline PIByteArray & operator >>(PIByteArray & s, PIPair & v) {s >> v.first >> v.second; return s;}
-
-
-
-
-// store operators for complex types
-
-
-//! \relatesalso PIByteArray \brief Store operator for PIVector of any compound type
-template::value, int>::type = 0>
-inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) {
- s << int(v.size_s());
- for (uint i = 0; i < v.size(); ++i) s << v[i];
- return s;
-}
-
-//! \relatesalso PIByteArray \brief Store operator for PIDeque of any compound type
-template::value, int>::type = 0>
-inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) {
- s << int(v.size_s());
- for (uint i = 0; i < v.size(); ++i) s << v[i];
- return s;
-}
-
-//! \relatesalso PIByteArray \brief Store operator for PIVector2D of any compound type
-template::value, int>::type = 0>
-inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D & v) {
- s << int(v.rows()) << int(v.cols()) << v.toPlainVector();
- return s;
-}
-
-
-
-
-// restore operators for complex types
-
-
-//! \relatesalso PIByteArray \brief Restore operator for PIVector of any compound type
-template::value, int>::type = 0>
-inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) {
- assert(s.size_s() >= 4);
- int sz; s >> sz;
- v.resize(sz);
- for (int i = 0; i < sz; ++i) s >> v[i];
- return s;
-}
-
-//! \relatesalso PIByteArray \brief Restore operator for PIDeque of any compound type
-template::value, int>::type = 0>
-inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) {
- assert(s.size_s() >= 4);
- int sz; s >> sz;
- v.resize(sz);
- for (int i = 0; i < sz; ++i) s >> v[i];
- return s;
-}
-
-//! \relatesalso PIByteArray \brief Restore operator for PIVector2D of any compound type
-template::value, int>::type = 0>
-inline PIByteArray & operator >>(PIByteArray & s, PIVector2D & v) {
- assert(s.size_s() >= 8);
- int r,c;
- PIVector tmp;
- s >> r >> c >> tmp;
- v = PIVector2D(r, c, tmp);
- return s;
-}
-
-
-
-
-// other types
-
-
-template
-inline PIByteArray & operator <<(PIByteArray & s, const PIMap & v) {
- s << int(v.pim_index.size_s());
- for (uint i = 0; i < v.size(); ++i)
- s << int(v.pim_index[i].index) << v.pim_index[i].key;
- s << v.pim_content;
- return s;
-}
-
-
-template
-inline PIByteArray & operator >>(PIByteArray & s, PIMap & v) {
- assert(s.size_s() >= 4);
- int sz; s >> sz; v.pim_index.resize(sz);
- int ind = 0;
- for (int i = 0; i < sz; ++i) {
- s >> ind >> v.pim_index[i].key;
- v.pim_index[i].index = ind;
- }
- s >> v.pim_content;
- if (v.pim_content.size_s() != v.pim_index.size_s()) {
- piCout << "Warning: loaded invalid PIMap, clear";
- v.clear();
- }
- return s;
-}
-
-
-
-template::value, int>::type = 0>
-inline PIByteArray & operator <<(PIByteArray & s, const T & ) {
- static_assert(std::is_trivially_copyable::value, "[PIByteArray] Error: using undeclared operator << for complex type!");
- return s;
-}
-
-template::value, int>::type = 0>
-inline PIByteArray & operator >>(PIByteArray & s, T & ) {
- static_assert(std::is_trivially_copyable::value, "[PIByteArray] Error: using undeclared operator >> for complex type!");
- return s;
-}
-
-template<> inline uint piHash(const PIByteArray & ba) {return ba.hash();}
-template<> inline void piSwap(PIByteArray & f, PIByteArray & s) {f.swap(s);}
-
-
-#endif // PIBYTEARRAY_H
+/*! \file pibytearray.h
+ * \brief Byte array
+*/
+/*
+ PIP - Platform Independent Primitives
+ Byte array
+ Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef PIBYTEARRAY_H
+#define PIBYTEARRAY_H
+
+#include "pichar.h"
+#include "pibitarray.h"
+#include "pimap.h"
+#include "pivector2d.h"
+
+class PIString;
+class PIByteArray;
+
+
+class PIP_EXPORT PIByteArray: public PIDeque
+{
+public:
+
+ //! Constructs an empty byte array
+ PIByteArray() {;}
+
+ PIByteArray(const PIByteArray & o): PIDeque(o) {}
+
+ PIByteArray(PIByteArray && o): PIDeque(std::move(o)) {}
+
+ //! Constructs 0-filled byte array with size "size"
+ PIByteArray(const uint size) {resize(size);}
+
+ //! Constructs byte array from data "data" and size "size"
+ PIByteArray(const void * data, const uint size): PIDeque((const uchar*)data, size_t(size)) {}
+
+ //! Constructs byte array with size "size" filled by "t"
+ PIByteArray(const uint size, uchar t): PIDeque(size, t) {}
+
+
+ //! Help struct to store/restore custom blocks of data to/from PIByteArray
+ struct RawData {
+ friend PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v);
+ friend PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v);
+ public:
+ //! Constructs data block
+ RawData(void * data = 0, int size = 0) {d = data; s = size;}
+ RawData(const RawData & o) {d = o.d; s = o.s;}
+ //! Constructs data block
+ RawData(const void * data, const int size) {d = const_cast(data); s = size;}
+ RawData & operator =(const RawData & o) {d = o.d; s = o.s; return *this;}
+ private:
+ void * d;
+ int s;
+ };
+
+ //! Return resized byte array
+ PIByteArray resized(uint new_size) const {PIByteArray ret(new_size); memcpy(ret.data(), data(), new_size); return ret;}
+
+ //! Convert data to Base 64 and return this byte array
+ PIByteArray & convertToBase64();
+
+ //! Convert data from Base 64 and return this byte array
+ PIByteArray & convertFromBase64();
+
+ //! Return converted to Base 64 data
+ PIByteArray toBase64() const;
+
+ //! Return converted from Base 64 data
+
+ PIByteArray & compressRLE(uchar threshold = 192);
+ PIByteArray & decompressRLE(uchar threshold = 192);
+ PIByteArray compressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.compressRLE(threshold); return ba;}
+ PIByteArray decompressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.decompressRLE(threshold); return ba;}
+
+ PIString toString(int base = 16) const;
+ PIString toHex() const;
+
+ //! Add to the end data "data" with size "size"
+ PIByteArray & append(const void * data_, int size_) {uint ps = size(); enlarge(size_); memcpy(data(ps), data_, size_); return *this;}
+
+ //! Add to the end byte array "data"
+ PIByteArray & append(const PIByteArray & data_) {uint ps = size(); enlarge(data_.size_s()); memcpy(data(ps), data_.data(), data_.size()); return *this;}
+
+ //! Add to the end "t"
+ PIByteArray & append(uchar t) {push_back(t); return *this;}
+
+ //! Returns plain 8-bit checksum
+ uchar checksumPlain8() const;
+
+ //! Returns plain 32-bit checksum
+ uint checksumPlain32() const;
+
+ //! Returns hash
+ uint hash() const;
+
+ void operator =(const PIDeque & d) {resize(d.size()); memcpy(data(), d.data(), d.size());}
+
+ PIByteArray & operator =(const PIByteArray & o) {if (this == &o) return *this; clear(); append(o); return *this;}
+
+ PIByteArray & operator =(PIByteArray && o) {swap(o); return *this;}
+
+ static PIByteArray fromUserInput(PIString str);
+ static PIByteArray fromHex(PIString str);
+ static PIByteArray fromBase64(const PIByteArray & base64);
+ static PIByteArray fromBase64(const PIString & base64);
+
+
+ class StreamRef {
+ public:
+ StreamRef(PIByteArray & s): ba(s) {}
+ operator PIByteArray&() {return ba;}
+ private:
+ PIByteArray & ba;
+ };
+
+};
+
+//! \relatesalso PIByteArray \brief Byte arrays compare operator
+inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) {
+ if (v0.size() == v1.size()) {
+ for (uint i = 0; i < v0.size(); ++i)
+ if (v0[i] != v1[i])
+ return v0[i] < v1[i];
+ return false;
+ }
+ return v0.size() < v1.size();
+}
+
+//! \relatesalso PIByteArray \brief Byte arrays compare operator
+inline bool operator ==(PIByteArray & f, PIByteArray & s) {
+ if (f.size_s() != s.size_s())
+ return false;
+ for (int i = 0; i < f.size_s(); ++i)
+ if (f[i] != s[i])
+ return false;
+ return true;
+}
+
+//! \relatesalso PIByteArray \brief Byte arrays compare operator
+inline bool operator !=(PIByteArray & f, PIByteArray & s) {
+ if (f.size_s() != s.size_s())
+ return true;
+ for (int i = 0; i < f.size_s(); ++i)
+ if (f[i] != s[i])
+ return true;
+ return false;
+}
+
+#ifdef PIP_STD_IOSTREAM
+//! \relatesalso PIByteArray \brief Output to std::ostream operator
+inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba);
+#endif
+
+//! \relatesalso PIByteArray \brief Output to PICout operator
+PIP_EXPORT PICout operator <<(PICout s, const PIByteArray & ba);
+
+
+
+
+// store operators for basic types
+
+
+//! \relatesalso PIByteArray \brief Store operator
+inline PIByteArray & operator <<(PIByteArray & s, const bool v) {s.push_back(v); return s;}
+
+//! \relatesalso PIByteArray \brief Store operator
+inline PIByteArray & operator <<(PIByteArray & s, const char v) {s.push_back(v); return s;}
+
+//! \relatesalso PIByteArray \brief Store operator
+inline PIByteArray & operator <<(PIByteArray & s, const uchar v) {s.push_back(v); return s;}
+
+//! \relatesalso PIByteArray \brief Store operator for any trivial copyable type
+template::value, int>::type = 0>
+inline PIByteArray::StreamRef operator <<(PIByteArray & s, const T & v) {
+ int os = s.size_s();
+ s.enlarge(sizeof(v));
+ memcpy(s.data(os), &v, sizeof(v));
+ return s;
+}
+
+//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details
+PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v);
+
+//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details
+inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {
+ int os = s.size_s();
+ if (v.s > 0) {
+ s.enlarge(v.s);
+ memcpy(s.data(os), v.d, v.s);
+ }
+ return s;
+}
+
+//! \relatesalso PIByteArray \brief Store operator for PIVector of any trivial copyable type
+template::value, int>::type = 0,
+ typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
+inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) {
+ s << int(v.size_s());
+ int os = s.size_s();
+ if (v.size_s() > 0) {
+ s.enlarge(v.size_s()*sizeof(T));
+ memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
+ }
+ return s;
+}
+template::value, int>::type = 0,
+ typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
+inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) {
+ s << int(v.size_s());
+ for (uint i = 0; i < v.size(); ++i) s << v[i];
+ return s;
+}
+
+//! \relatesalso PIByteArray \brief Store operator for PIDeque of any trivial copyable type
+template::value, int>::type = 0,
+ typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
+inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) {
+ s << int(v.size_s());
+ int os = s.size_s();
+ if (v.size_s() > 0) {
+ s.enlarge(v.size_s()*sizeof(T));
+ memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
+ }
+ return s;
+}
+template::value, int>::type = 0,
+ typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
+inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) {
+ s << int(v.size_s());
+ for (uint i = 0; i < v.size(); ++i) s << v[i];
+ return s;
+}
+
+//! \relatesalso PIByteArray \brief Store operator for PIVector2D of any trivial copyable type
+template::value, int>::type = 0,
+ typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
+inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D & v) {
+ s << int(v.rows()) << int(v.cols());
+ int os = s.size_s();
+ if (v.size_s() > 0) {
+ s.enlarge(v.size_s()*sizeof(T));
+ memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
+ }
+ return s;
+}
+template::value, int>::type = 0,
+ typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
+inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D & v) {
+ s << int(v.rows()) << int(v.cols()) << v.toPlainVector();
+ return s;
+}
+
+//! \relatesalso PIByteArray \brief Store operator
+inline PIByteArray & operator <<(PIByteArray & s, const PIBitArray & v) {s << v.size_ << v.data_; return s;}
+
+//! \relatesalso PIPair \brief Store operator
+template
+inline PIByteArray & operator <<(PIByteArray & s, const PIPair & v) {s << v.first << v.second; return s;}
+
+
+
+
+// restore operators for basic types
+
+
+//! \relatesalso PIByteArray \brief Restore operator
+inline PIByteArray & operator >>(PIByteArray & s, bool & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
+
+//! \relatesalso PIByteArray \brief Restore operator
+inline PIByteArray & operator >>(PIByteArray & s, char & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
+
+//! \relatesalso PIByteArray \brief Restore operator
+inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
+
+//! \relatesalso PIByteArray \brief Restore operator for any trivial copyable type
+template::value, int>::type = 0>
+inline PIByteArray::StreamRef operator >>(PIByteArray & s, T & v) {
+ if (s.size() < sizeof(v)) {
+ printf("error with %s\n", typeid(T).name());
+ assert(s.size() >= sizeof(v));
+ }
+ memcpy((void*)(&v), s.data(), sizeof(v));
+ s.remove(0, sizeof(v));
+ return s;
+}
+
+//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
+PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIByteArray & v);
+
+//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
+inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {
+ if (s.size_s() < v.s) {
+ printf("error with RawData %d < %d\n", (int)s.size_s(), v.s);
+ assert(s.size_s() >= v.s);
+ }
+ if (v.s > 0) {
+ memcpy((void*)(v.d), s.data(), v.s);
+ s.remove(0, v.s);
+ }
+ return s;
+}
+
+//! \relatesalso PIByteArray \brief Restore operator for PIVector of any trivial copyable type
+template::value, int>::type = 0,
+ typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
+inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) {
+ if (s.size_s() < 4) {
+ printf("error with PIVector<%s>\n", typeid(T).name());
+ assert(s.size_s() >= 4);
+ }
+ int sz; s >> sz;
+ v._resizeRaw(sz);
+ if (sz > 0) {
+ memcpy(v.data(), s.data(), sz*sizeof(T));
+ s.remove(0, sz*sizeof(T));
+ }
+ return s;
+}
+template::value, int>::type = 0,
+ typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
+inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) {
+ if (s.size_s() < 4) {
+ printf("error with PIVector<%s>\n", typeid(T).name());
+ assert(s.size_s() >= 4);
+ }
+ int sz; s >> sz;
+ v.resize(sz);
+ for (int i = 0; i < sz; ++i) s >> v[i];
+ return s;
+}
+
+//! \relatesalso PIByteArray \brief Restore operator for PIDeque of any trivial copyable type
+template::value, int>::type = 0,
+ typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
+inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) {
+ if (s.size_s() < 4) {
+ printf("error with PIDeque<%s>\n", typeid(T).name());
+ assert(s.size_s() >= 4);
+ }
+ int sz; s >> sz;
+ v._resizeRaw(sz);
+ if (sz > 0) {
+ memcpy(v.data(), s.data(), sz*sizeof(T));
+ s.remove(0, sz*sizeof(T));
+ }
+ return s;
+}
+template::value, int>::type = 0,
+ typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
+inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) {
+ if (s.size_s() < 4) {
+ printf("error with PIDeque<%s>\n", typeid(T).name());
+ assert(s.size_s() >= 4);
+ }
+ int sz; s >> sz;
+ v.resize(sz);
+ for (int i = 0; i < sz; ++i) s >> v[i];
+ return s;
+}
+
+//! \relatesalso PIByteArray \brief Restore operator for PIVector2D of any trivial copyable type
+template::value, int>::type = 0,
+ typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
+inline PIByteArray & operator >>(PIByteArray & s, PIVector2D & v) {
+ if (s.size_s() < 8) {
+ printf("error with PIVecto2Dr<%s>\n", typeid(T).name());
+ assert(s.size_s() >= 8);
+ }
+ int r, c; s >> r >> c;
+ v._resizeRaw(r, c);
+ int sz = r*c;
+ if (sz > 0) {
+ memcpy(v.data(), s.data(), sz*sizeof(T));
+ s.remove(0, sz*sizeof(T));
+ }
+ return s;
+}
+template::value, int>::type = 0,
+ typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0>
+inline PIByteArray & operator >>(PIByteArray & s, PIVector2D & v) {
+ if (s.size_s() < 8) {
+ printf("error with PIVecto2Dr<%s>\n", typeid(T).name());
+ assert(s.size_s() >= 8);
+ }
+ int r,c;
+ PIVector tmp;
+ s >> r >> c >> tmp;
+ v = PIVector2D(r, c, tmp);
+ return s;
+}
+
+//! \relatesalso PIByteArray \brief Restore operator
+inline PIByteArray & operator >>(PIByteArray & s, PIBitArray & v) {assert(s.size_s() >= 8); s >> v.size_ >> v.data_; return s;}
+
+//! \relatesalso PIPair \brief Restore operator
+template
+inline PIByteArray & operator >>(PIByteArray & s, PIPair & v) {s >> v.first >> v.second; return s;}
+
+
+
+
+// store operators for complex types
+
+
+//! \relatesalso PIByteArray \brief Store operator for PIVector of any compound type
+template::value, int>::type = 0>
+inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) {
+ s << int(v.size_s());
+ for (uint i = 0; i < v.size(); ++i) s << v[i];
+ return s;
+}
+
+//! \relatesalso PIByteArray \brief Store operator for PIDeque of any compound type
+template::value, int>::type = 0>
+inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) {
+ s << int(v.size_s());
+ for (uint i = 0; i < v.size(); ++i) s << v[i];
+ return s;
+}
+
+//! \relatesalso PIByteArray \brief Store operator for PIVector2D of any compound type
+template::value, int>::type = 0>
+inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D & v) {
+ s << int(v.rows()) << int(v.cols()) << v.toPlainVector();
+ return s;
+}
+
+
+
+
+// restore operators for complex types
+
+
+//! \relatesalso PIByteArray \brief Restore operator for PIVector of any compound type
+template::value, int>::type = 0>
+inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) {
+ if (s.size_s() < 4) {
+ printf("error with PIVector<%s>\n", typeid(T).name());
+ assert(s.size_s() >= 4);
+ }
+ int sz; s >> sz;
+ v.resize(sz);
+ for (int i = 0; i < sz; ++i) s >> v[i];
+ return s;
+}
+
+//! \relatesalso PIByteArray \brief Restore operator for PIDeque of any compound type
+template::value, int>::type = 0>
+inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) {
+ if (s.size_s() < 4) {
+ printf("error with PIDeque<%s>\n", typeid(T).name());
+ assert(s.size_s() >= 4);
+ }
+ int sz; s >> sz;
+ v.resize(sz);
+ for (int i = 0; i < sz; ++i) s >> v[i];
+ return s;
+}
+
+//! \relatesalso PIByteArray \brief Restore operator for PIVector2D of any compound type
+template::value, int>::type = 0>
+inline PIByteArray & operator >>(PIByteArray & s, PIVector2D & v) {
+ if (s.size_s() < 8) {
+ printf("error with PIVecto2Dr<%s>\n", typeid(T).name());
+ assert(s.size_s() >= 8);
+ }
+ int r,c;
+ PIVector tmp;
+ s >> r >> c >> tmp;
+ v = PIVector2D(r, c, tmp);
+ return s;
+}
+
+
+
+
+// other types
+
+
+template
+inline PIByteArray & operator <<(PIByteArray & s, const PIMap & v) {
+ s << int(v.pim_index.size_s());
+ for (uint i = 0; i < v.size(); ++i)
+ s << int(v.pim_index[i].index) << v.pim_index[i].key;
+ s << v.pim_content;
+ return s;
+}
+
+
+template
+inline PIByteArray & operator >>(PIByteArray & s, PIMap & v) {
+ if (s.size_s() < 4) {
+ printf("error with PIMap<%s, %s>\n", typeid(Key).name(), typeid(T).name());
+ assert(s.size_s() >= 4);
+ }
+ int sz; s >> sz; v.pim_index.resize(sz);
+ int ind = 0;
+ for (int i = 0; i < sz; ++i) {
+ s >> ind >> v.pim_index[i].key;
+ v.pim_index[i].index = ind;
+ }
+ s >> v.pim_content;
+ if (v.pim_content.size_s() != v.pim_index.size_s()) {
+ piCout << "Warning: loaded invalid PIMap, clear";
+ v.clear();
+ }
+ return s;
+}
+
+
+
+template::value, int>::type = 0>
+inline PIByteArray & operator <<(PIByteArray & s, const T & ) {
+ static_assert(std::is_trivially_copyable::value, "[PIByteArray] Error: using undeclared operator << for complex type!");
+ return s;
+}
+
+template::value, int>::type = 0>
+inline PIByteArray & operator >>(PIByteArray & s, T & ) {
+ static_assert(std::is_trivially_copyable::value, "[PIByteArray] Error: using undeclared operator >> for complex type!");
+ return s;
+}
+
+template<> inline uint piHash(const PIByteArray & ba) {return ba.hash();}
+template<> inline void piSwap(PIByteArray & f, PIByteArray & s) {f.swap(s);}
+
+
+#endif // PIBYTEARRAY_H
diff --git a/libs/main/introspection/piintrospection_server.cpp b/libs/main/introspection/piintrospection_server.cpp
index 2ea2a85f..6275d91d 100644
--- a/libs/main/introspection/piintrospection_server.cpp
+++ b/libs/main/introspection/piintrospection_server.cpp
@@ -1,104 +1,111 @@
-/*
- PIP - Platform Independent Primitives
- Introspection module
- Ivan Pelipenko peri4ko@yandex.ru
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see .
-*/
-
-#ifdef PIP_INTROSPECTION
-
-#include "piintrospection_server.h"
-#include "piintrospection_server_p.h"
-#include "piprocess.h"
-#include "pichunkstream.h"
-
-
-PRIVATE_DEFINITION_START(PIIntrospectionServer)
- PIIntrospection::ProcessInfo process_info;
-PRIVATE_DEFINITION_END(PIIntrospectionServer)
-
-
-PIIntrospectionServer::PIIntrospectionServer(): PIPeer(genName()) {
- PRIVATE->process_info = PIIntrospection::getInfo();
- sysmon = 0;
-}
-
-
-PIIntrospectionServer::~PIIntrospectionServer() {
- PIPeer::stop();
- if (sysmon)
- if (sysmon->property("__iserver__").toBool())
- delete sysmon;
- sysmon = 0;
-}
-
-
-void PIIntrospectionServer::start() {
- if (!sysmon) {
- sysmon = PISystemMonitor::Pool::instance()->getByPID(PIProcess::currentPID());
- if (sysmon) {
- piCoutObj << "using existing sysmon";
- CONNECTU(sysmon, deleted, this, sysmonDeleted);
- } else {
- piCoutObj << "create own sysmon";
- sysmon = new PISystemMonitor();
- sysmon->setProperty("__iserver__", true);
- sysmon->startOnSelf();
- }
- }
- PIPeer::start();
-}
-
-
-PIString PIIntrospectionServer::genName() {
- randomize();
- return "__introspection__server_" + PIString::fromNumber(randomi() % 1000);
-}
-
-
-void PIIntrospectionServer::dataReceived(const PIString & from, const PIByteArray & data) {
- if (data.size() < 8) return;
- PIByteArray rba(data);
- uint _sign(0); rba >> _sign;
- if (_sign != PIIntrospection::sign) return;
- PIIntrospection::RequiredInfo ri;
- rba >> ri;
- PIChunkStream cs;
- if (ri.types[PIIntrospection::itInfo])
- cs.add(PIIntrospection::itInfo, PIIntrospection::packInfo());
- if (ri.types[PIIntrospection::itProcStat]) {
- sysmon_mutex.lock();
- cs.add(PIIntrospection::itProcStat, PIIntrospection::packProcStat(sysmon));
- sysmon_mutex.unlock();
- }
- if (ri.types[PIIntrospection::itContainers])
- cs.add(PIIntrospection::itContainers, PIIntrospection::packContainers());
- if (ri.types[PIIntrospection::itObjects])
- cs.add(PIIntrospection::itObjects, PIIntrospection::packObjects());
- if (ri.types[PIIntrospection::itThreads])
- cs.add(PIIntrospection::itThreads, PIIntrospection::packThreads());
- PIByteArray ba;
- ba << PIIntrospection::sign;
- ba.append(cs.data());
- send(from, ba);
-}
-
-
-void PIIntrospectionServer::sysmonDeleted() {
- PIMutexLocker _ml(sysmon_mutex);
- sysmon = 0;
-}
-
-#endif // PIP_INTROSPECTION
+/*
+ PIP - Platform Independent Primitives
+ Introspection module
+ Ivan Pelipenko peri4ko@yandex.ru
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#ifdef PIP_INTROSPECTION
+
+#include "piintrospection_server.h"
+#include "piintrospection_server_p.h"
+#include "piprocess.h"
+#include "pichunkstream.h"
+
+
+PRIVATE_DEFINITION_START(PIIntrospectionServer)
+ PIIntrospection::ProcessInfo process_info;
+PRIVATE_DEFINITION_END(PIIntrospectionServer)
+
+
+PIIntrospectionServer::PIIntrospectionServer(): PIPeer(genName()) {
+ PRIVATE->process_info = PIIntrospection::getInfo();
+ sysmon = 0;
+}
+
+
+PIIntrospectionServer::~PIIntrospectionServer() {
+ PIPeer::stop();
+ if (sysmon)
+ if (sysmon->property("__iserver__").toBool())
+ delete sysmon;
+ sysmon = 0;
+}
+
+
+PIIntrospectionServer * PIIntrospectionServer::instance() {
+ static PIIntrospectionServer ret;
+ return &ret;
+}
+
+
+void PIIntrospectionServer::start(const PIString & server_name) {
+ if (!sysmon) {
+ sysmon = PISystemMonitor::Pool::instance()->getByPID(PIProcess::currentPID());
+ if (sysmon) {
+ piCoutObj << "using existing sysmon";
+ CONNECTU(sysmon, deleted, this, sysmonDeleted);
+ } else {
+ piCoutObj << "create own sysmon";
+ sysmon = new PISystemMonitor();
+ sysmon->setProperty("__iserver__", true);
+ sysmon->startOnSelf();
+ }
+ }
+ changeName(server_name + genName());
+ PIPeer::start();
+}
+
+
+PIString PIIntrospectionServer::genName() {
+ randomize();
+ return "__introspection__server_" + PIString::fromNumber(randomi() % 1000);
+}
+
+
+void PIIntrospectionServer::dataReceived(const PIString & from, const PIByteArray & data) {
+ if (data.size() < 8) return;
+ PIByteArray rba(data);
+ uint _sign(0); rba >> _sign;
+ if (_sign != PIIntrospection::sign) return;
+ PIIntrospection::RequiredInfo ri;
+ rba >> ri;
+ PIChunkStream cs;
+ if (ri.types[PIIntrospection::itInfo])
+ cs.add(PIIntrospection::itInfo, PIIntrospection::packInfo());
+ if (ri.types[PIIntrospection::itProcStat]) {
+ sysmon_mutex.lock();
+ cs.add(PIIntrospection::itProcStat, PIIntrospection::packProcStat(sysmon));
+ sysmon_mutex.unlock();
+ }
+ if (ri.types[PIIntrospection::itContainers])
+ cs.add(PIIntrospection::itContainers, PIIntrospection::packContainers());
+ if (ri.types[PIIntrospection::itObjects])
+ cs.add(PIIntrospection::itObjects, PIIntrospection::packObjects());
+ if (ri.types[PIIntrospection::itThreads])
+ cs.add(PIIntrospection::itThreads, PIIntrospection::packThreads());
+ PIByteArray ba;
+ ba << PIIntrospection::sign;
+ ba.append(cs.data());
+ send(from, ba);
+}
+
+
+void PIIntrospectionServer::sysmonDeleted() {
+ PIMutexLocker _ml(sysmon_mutex);
+ sysmon = 0;
+}
+
+#endif // PIP_INTROSPECTION
diff --git a/libs/main/introspection/piintrospection_server.h b/libs/main/introspection/piintrospection_server.h
index 19b5f655..31b2620a 100644
--- a/libs/main/introspection/piintrospection_server.h
+++ b/libs/main/introspection/piintrospection_server.h
@@ -1,61 +1,61 @@
-/*
- PIP - Platform Independent Primitives
- Introspection module
- Ivan Pelipenko peri4ko@yandex.ru
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see .
-*/
-
-#ifndef PIINTROSPECTION_SERVER_H
-#define PIINTROSPECTION_SERVER_H
-
-
-#include "pipeer.h"
-
-#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
-
-class PIIntrospectionServer;
-class PISystemMonitor;
-
-# define PIINTROSPECTION_SERVER (PIIntrospectionServer::instance())
-# define PIINTROSPECTION_START PIINTROSPECTION_SERVER->start();
-
-class PIP_EXPORT PIIntrospectionServer: public PIPeer {
- PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer)
-public:
- static PIIntrospectionServer * instance() {static PIIntrospectionServer ret; return &ret;}
-
- void start();
-
-private:
- PIIntrospectionServer();
- ~PIIntrospectionServer();
- NO_COPY_CLASS(PIIntrospectionServer)
-
- PIString genName();
- virtual void dataReceived(const PIString & from, const PIByteArray & data);
- EVENT_HANDLER(void, sysmonDeleted);
-
- PRIVATE_DECLARATION
- PITimer itimer;
- PISystemMonitor * sysmon;
- PIMutex sysmon_mutex;
-
-};
-
-#else
-# define PIINTROSPECTION_START
-#endif
-
-#endif // PIINTROSPECTION_SERVER_H
+/*
+ PIP - Platform Independent Primitives
+ Introspection module
+ Ivan Pelipenko peri4ko@yandex.ru
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef PIINTROSPECTION_SERVER_H
+#define PIINTROSPECTION_SERVER_H
+
+
+#include "pipeer.h"
+
+#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
+
+class PIIntrospectionServer;
+class PISystemMonitor;
+
+# define PIINTROSPECTION_SERVER (PIIntrospectionServer::instance())
+# define PIINTROSPECTION_START(name) PIINTROSPECTION_SERVER->start(#name);
+
+class PIP_EXPORT PIIntrospectionServer: public PIPeer {
+ PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer)
+public:
+ static PIIntrospectionServer * instance();
+
+ void start(const PIString & server_name);
+
+private:
+ PIIntrospectionServer();
+ ~PIIntrospectionServer();
+ NO_COPY_CLASS(PIIntrospectionServer)
+
+ PIString genName();
+ virtual void dataReceived(const PIString & from, const PIByteArray & data);
+ EVENT_HANDLER(void, sysmonDeleted);
+
+ PRIVATE_DECLARATION(PIP_EXPORT)
+ PITimer itimer;
+ PISystemMonitor * sysmon;
+ PIMutex sysmon_mutex;
+
+};
+
+#else
+# define PIINTROSPECTION_START(name)
+#endif
+
+#endif // PIINTROSPECTION_SERVER_H
diff --git a/libs/main/introspection/piintrospection_server_p.cpp b/libs/main/introspection/piintrospection_server_p.cpp
index f0aee35c..bcdcd6d8 100644
--- a/libs/main/introspection/piintrospection_server_p.cpp
+++ b/libs/main/introspection/piintrospection_server_p.cpp
@@ -1,247 +1,247 @@
-/*
- PIP - Platform Independent Primitives
- Introspection module - Base server structs
- Ivan Pelipenko peri4ko@yandex.ru
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see .
-*/
-
-#include "piintrospection_server_p.h"
-#include "pichunkstream.h"
-#include "piinit.h"
-#include "pisysteminfo.h"
-#include "piobject.h"
-
-
-const uint PIIntrospection::sign = 0x0F1C2B3A;
-
-
-PIIntrospection::RequiredInfo::RequiredInfo() {
- types = itInfo;
-}
-
-
-PIIntrospection::ProcessInfo::ProcessInfo() {
- processorsCount = 0;
-}
-
-
-PIIntrospection::ObjectInfo::ObjectInfo() {
- queued_events = 0;
-}
-
-
-PIIntrospection::ProcessInfo PIIntrospection::getInfo() {
- PIIntrospection::ProcessInfo ret;
- PISystemInfo * si = PISystemInfo::instance();
- ret.architecture = si->architecture;
- ret.execCommand = si->execCommand;
- ret.execDateTime = si->execDateTime;
- ret.hostname = si->hostname;
- ret.OS_name = si->OS_name;
- ret.OS_version = si->OS_version;
- ret.processorsCount = si->processorsCount;
- ret.user = si->user;
- ret.build_options = PIInit::buildOptions();
- return ret;
-}
-
-
-PIVector PIIntrospection::getObjects() {
- PIVector ret;
- PIObject::mutexObjects().lock();
- const PIVector & ao(PIObject::objects());
- ret.resize(ao.size());
- for (int i = 0; i < ao.size_s(); ++i) {
- ret[i].classname = PIStringAscii(ao[i]->className());
- ret[i].name = ao[i]->name();
- ret[i].properties = ao[i]->properties();
- ret[i].parents = ao[i]->scopeList();
- ao[i]->mutex_queue.lock();
- ret[i].queued_events = ao[i]->events_queue.size_s();
- ao[i]->mutex_queue.unlock();
- }
- PIObject::mutexObjects().unlock();
- return ret;
-}
-
-
-PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::RequiredInfo & v) {
- PIChunkStream cs;
- cs.add(1, v.types);
- b << cs.data();
- return b;
-}
-
-
-PIByteArray & operator >>(PIByteArray & b, PIIntrospection::RequiredInfo & v) {
- PIByteArray csba; b >> csba;
- PIChunkStream cs(csba);
- while (!cs.atEnd()) {
- switch (cs.read()) {
- case 1: cs.get(v.types); break;
- default: break;
- }
- }
- return b;
-}
-
-
-PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ProcessInfo & v) {
- PIChunkStream cs;
- cs.add(1, v.architecture).add(2, v.execCommand).add(3, v.execDateTime).add(4, v.hostname).add(5, v.OS_name)
- .add(6, v.OS_version).add(7, v.processorsCount).add(8, v.user).add(9, v.build_options);
- b << cs.data();
- return b;
-}
-
-
-PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ProcessInfo & v) {
- PIByteArray csba; b >> csba;
- PIChunkStream cs(csba);
- while (!cs.atEnd()) {
- switch (cs.read()) {
- case 1: cs.get(v.architecture); break;
- case 2: cs.get(v.execCommand); break;
- case 3: cs.get(v.execDateTime); break;
- case 4: cs.get(v.hostname); break;
- case 5: cs.get(v.OS_name); break;
- case 6: cs.get(v.OS_version); break;
- case 7: cs.get(v.processorsCount); break;
- case 8: cs.get(v.user); break;
- case 9: cs.get(v.build_options); break;
- default: break;
- }
- }
- return b;
-}
-
-
-PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ObjectInfo & v) {
- PIChunkStream cs;
- cs.add(1, v.classname).add(2, v.name).add(3, v.parents).add(4, v.properties).add(5, v.queued_events);
- b << cs.data();
- return b;
-}
-
-
-PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ObjectInfo & v) {
- PIByteArray csba; b >> csba;
- PIChunkStream cs(csba);
- while (!cs.atEnd()) {
- switch (cs.read()) {
- case 1: cs.get(v.classname); break;
- case 2: cs.get(v.name); break;
- case 3: cs.get(v.parents); break;
- case 4: cs.get(v.properties); break;
- case 5: cs.get(v.queued_events); break;
- default: break;
- }
- }
- return b;
-}
-
-
-
-
-PIByteArray PIIntrospection::packInfo() {
- PIByteArray ret;
- ret << getInfo();
- return ret;
-}
-
-
-void PIIntrospection::unpackInfo(PIByteArray & ba, PIIntrospection::ProcessInfo & info) {
- ba >> info;
-}
-
-
-PIByteArray PIIntrospection::packProcStat(PISystemMonitor * sm) {
- ProcessStat ps;
- if (sm) {
- ps.proc = sm->statistic();
- ps.threads = sm->threadsStatistic();
- }
- PIByteArray ret;
- ret << ps.proc << ps.threads;
- return ret;
-}
-
-
-void PIIntrospection::unpackProcStat(PIByteArray & ba, PIIntrospection::ProcessStat & info) {
- ba >> info.proc >> info.threads;
-}
-
-
-PIByteArray PIIntrospection::packContainers() {
- PIByteArray ret;
- PIVector data;
- PIIntrospectionContainers * p = 0;
-#ifdef PIP_INTROSPECTION
- p = PIINTROSPECTION_CONTAINERS->p;
-#endif
- if (p) {
- data = p->getInfo();
- }
- ret << data;
- return ret;
-}
-
-
-void PIIntrospection::unpackContainers(PIByteArray & ba, PIVector & data) {
- data.clear();
- ba >> data;
-}
-
-
-PIByteArray PIIntrospection::packThreads() {
- PIByteArray ret;
- PIIntrospectionThreads * p = 0;
-#ifdef PIP_INTROSPECTION
- p = PIINTROSPECTION_THREADS->p;
-#endif
- if (p) {
- p->mutex.lock();
- PIMap & tm(p->threads);
- auto it = tm.makeIterator();
- while (it.next()) {
- it.valueRef().classname = PIStringAscii(it.key()->className());
- it.valueRef().name = it.key()->name();
- }
- ret << tm.values();
- p->mutex.unlock();
- } else {
- ret << PIVector();
- }
- return ret;
-}
-
-
-void PIIntrospection::unpackThreads(PIByteArray & ba, PIVector & threads) {
- threads.clear();
- ba >> threads;
-}
-
-
-PIByteArray PIIntrospection::packObjects() {
- PIByteArray ret;
- ret << getObjects();
- return ret;
-}
-
-
-void PIIntrospection::unpackObjects(PIByteArray & ba, PIVector & objects) {
- objects.clear();
- ba >> objects;
-}
+/*
+ PIP - Platform Independent Primitives
+ Introspection module - Base server structs
+ Ivan Pelipenko peri4ko@yandex.ru
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#include "piintrospection_server_p.h"
+#include "pichunkstream.h"
+#include "piinit.h"
+#include "pisysteminfo.h"
+#include "piobject.h"
+
+
+const uint PIIntrospection::sign = 0x0F1C2B3A;
+
+
+PIIntrospection::RequiredInfo::RequiredInfo() {
+ types = itInfo;
+}
+
+
+PIIntrospection::ProcessInfo::ProcessInfo() {
+ processorsCount = 0;
+}
+
+
+PIIntrospection::ObjectInfo::ObjectInfo() {
+ queued_events = 0;
+}
+
+
+PIIntrospection::ProcessInfo PIIntrospection::getInfo() {
+ PIIntrospection::ProcessInfo ret;
+ PISystemInfo * si = PISystemInfo::instance();
+ ret.architecture = si->architecture;
+ ret.execCommand = si->execCommand;
+ ret.execDateTime = si->execDateTime;
+ ret.hostname = si->hostname;
+ ret.OS_name = si->OS_name;
+ ret.OS_version = si->OS_version;
+ ret.processorsCount = si->processorsCount;
+ ret.user = si->user;
+ ret.build_options = PIInit::buildOptions();
+ return ret;
+}
+
+
+PIVector PIIntrospection::getObjects() {
+ PIVector ret;
+ PIObject::mutexObjects().lock();
+ const PIVector & ao(PIObject::objects());
+ ret.resize(ao.size());
+ for (int i = 0; i < ao.size_s(); ++i) {
+ ret[i].classname = PIStringAscii(ao[i]->className());
+ ret[i].name = ao[i]->name();
+ ret[i].properties = ao[i]->properties();
+ ret[i].parents = ao[i]->scopeList();
+ ao[i]->mutex_queue.lock();
+ ret[i].queued_events = ao[i]->events_queue.size_s();
+ ao[i]->mutex_queue.unlock();
+ }
+ PIObject::mutexObjects().unlock();
+ return ret;
+}
+
+
+PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::RequiredInfo & v) {
+ PIChunkStream cs;
+ cs.add(1, v.types);
+ b << cs.data();
+ return b;
+}
+
+
+PIByteArray & operator >>(PIByteArray & b, PIIntrospection::RequiredInfo & v) {
+ PIByteArray csba; b >> csba;
+ PIChunkStream cs(csba);
+ while (!cs.atEnd()) {
+ switch (cs.read()) {
+ case 1: cs.get(v.types); break;
+ default: break;
+ }
+ }
+ return b;
+}
+
+
+PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ProcessInfo & v) {
+ PIChunkStream cs;
+ cs.add(1, v.architecture).add(2, v.execCommand).add(3, v.execDateTime).add(4, v.hostname).add(5, v.OS_name)
+ .add(6, v.OS_version).add(7, v.processorsCount).add(8, v.user).add(9, v.build_options);
+ b << cs.data();
+ return b;
+}
+
+
+PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ProcessInfo & v) {
+ PIByteArray csba; b >> csba;
+ PIChunkStream cs(csba);
+ while (!cs.atEnd()) {
+ switch (cs.read()) {
+ case 1: cs.get(v.architecture); break;
+ case 2: cs.get(v.execCommand); break;
+ case 3: cs.get(v.execDateTime); break;
+ case 4: cs.get(v.hostname); break;
+ case 5: cs.get(v.OS_name); break;
+ case 6: cs.get(v.OS_version); break;
+ case 7: cs.get(v.processorsCount); break;
+ case 8: cs.get(v.user); break;
+ case 9: cs.get(v.build_options); break;
+ default: break;
+ }
+ }
+ return b;
+}
+
+
+PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ObjectInfo & v) {
+ PIChunkStream cs;
+ cs.add(1, v.classname).add(2, v.name).add(3, v.parents).add(4, v.properties).add(5, v.queued_events);
+ b << cs.data();
+ return b;
+}
+
+
+PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ObjectInfo & v) {
+ PIByteArray csba; b >> csba;
+ PIChunkStream cs(csba);
+ while (!cs.atEnd()) {
+ switch (cs.read()) {
+ case 1: cs.get(v.classname); break;
+ case 2: cs.get(v.name); break;
+ case 3: cs.get(v.parents); break;
+ case 4: cs.get(v.properties); break;
+ case 5: cs.get(v.queued_events); break;
+ default: break;
+ }
+ }
+ return b;
+}
+
+
+
+
+PIByteArray PIIntrospection::packInfo() {
+ PIByteArray ret;
+ ret << getInfo();
+ return ret;
+}
+
+
+void PIIntrospection::unpackInfo(PIByteArray & ba, PIIntrospection::ProcessInfo & info) {
+ ba >> info;
+}
+
+
+PIByteArray PIIntrospection::packProcStat(PISystemMonitor * sm) {
+ ProcessStat ps;
+ if (sm) {
+ ps.proc = sm->statistic();
+ ps.threads = sm->threadsStatistic();
+ }
+ PIByteArray ret;
+ ret << ps.proc << ps.threads;
+ return ret;
+}
+
+
+void PIIntrospection::unpackProcStat(PIByteArray & ba, PIIntrospection::ProcessStat & info) {
+ ba >> info.proc >> info.threads;
+}
+
+
+PIByteArray PIIntrospection::packContainers() {
+ PIByteArray ret;
+ PIVector data;
+ PIIntrospectionContainers * p = 0;
+#ifdef PIP_INTROSPECTION
+ p = PIINTROSPECTION_CONTAINERS->p;
+#endif
+ if (p) {
+ data = p->getInfo();
+ }
+ ret << data;
+ return ret;
+}
+
+
+void PIIntrospection::unpackContainers(PIByteArray & ba, PIVector & data) {
+ data.clear();
+ ba >> data;
+}
+
+
+PIByteArray PIIntrospection::packThreads() {
+ PIByteArray ret;
+ PIIntrospectionThreads * p = 0;
+#ifdef PIP_INTROSPECTION
+ p = PIINTROSPECTION_THREADS->p;
+#endif
+ if (p) {
+ p->mutex.lock();
+ PIMap & tm(p->threads);
+ auto it = tm.makeIterator();
+ while (it.next()) {
+ it.valueRef().classname = PIStringAscii(it.key()->className());
+ it.valueRef().name = it.key()->name();
+ }
+ ret << tm.values();
+ p->mutex.unlock();
+ } else {
+ ret << PIVector();
+ }
+ return ret;
+}
+
+
+void PIIntrospection::unpackThreads(PIByteArray & ba, PIVector & threads) {
+ threads.clear();
+ ba >> threads;
+}
+
+
+PIByteArray PIIntrospection::packObjects() {
+ PIByteArray ret;
+ ret << getObjects();
+ return ret;
+}
+
+
+void PIIntrospection::unpackObjects(PIByteArray & ba, PIVector & objects) {
+ objects.clear();
+ ba >> objects;
+}
diff --git a/libs/main/io_devices/pibinarylog.cpp b/libs/main/io_devices/pibinarylog.cpp
index 1a8472dc..d79fddc1 100644
--- a/libs/main/io_devices/pibinarylog.cpp
+++ b/libs/main/io_devices/pibinarylog.cpp
@@ -153,6 +153,7 @@ bool PIBinaryLog::openDevice() {
bool PIBinaryLog::closeDevice() {
stopThreadedRead();
pausemutex.unlock();
+ logmutex.unlock();
moveIndex(-1);
is_indexed = false;
index.clear();
diff --git a/libs/main/system/pisystemmonitor.cpp b/libs/main/system/pisystemmonitor.cpp
index 98e259a6..1e2e39e2 100644
--- a/libs/main/system/pisystemmonitor.cpp
+++ b/libs/main/system/pisystemmonitor.cpp
@@ -1,501 +1,501 @@
-/*
- PIP - Platform Independent Primitives
- Process resource monitor
- Ivan Pelipenko peri4ko@yandex.ru
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see .
-*/
-
-#include "piincludes_p.h"
-#include "pisystemmonitor.h"
-#include "pisysteminfo.h"
-#include "piprocess.h"
-#include "pidir.h"
-#include "pitime_win.h"
-#ifdef WINDOWS
-# include
-# include
-#endif
-#ifdef MAC_OS
- struct kqueue_id_t;
-# include
-# include
-#endif
-#ifdef ESP_PLATFORM
-# include "esp_heap_caps.h"
-#endif
-
-
-PISystemMonitor::ProcessStatsFixed::ProcessStatsFixed() {
- ID = parent_ID = group_ID = session_ID = priority = threads = 0;
- physical_memsize = resident_memsize = share_memsize = virtual_memsize = data_memsize = 0;
- cpu_load_user = cpu_load_system = 0.f;
-}
-
-
-void PISystemMonitor::ProcessStats::makeStrings() {
- physical_memsize_readable.setReadableSize(physical_memsize);
- resident_memsize_readable.setReadableSize(resident_memsize);
- share_memsize_readable.setReadableSize(share_memsize);
- virtual_memsize_readable.setReadableSize(virtual_memsize);
- data_memsize_readable.setReadableSize(data_memsize);
-}
-
-
-PISystemMonitor::ThreadStatsFixed::ThreadStatsFixed() {
- id = 0;
- cpu_load_kernel = cpu_load_user = -1.f;
-}
-
-
-#ifndef FREERTOS
-PRIVATE_DEFINITION_START(PISystemMonitor)
-#ifndef WINDOWS
-# ifdef MAC_OS
- PISystemTime
-# else
- llong
-# endif
- cpu_u_cur, cpu_u_prev, cpu_s_cur, cpu_s_prev;
- PIString proc_dir;
- PIFile file, filem;
-#else
- HANDLE hProc;
- PROCESS_MEMORY_COUNTERS mem_cnt;
- PISystemTime tm_kernel, tm_user;
- PITimeMeasurer tm;
-#endif
-PRIVATE_DEFINITION_END(PISystemMonitor)
-#endif
-
-
-PISystemMonitor::PISystemMonitor(): PIThread() {
- pID_ = cycle = 0;
- cpu_count = PISystemInfo::instance()->processorsCount;
-#ifndef FREERTOS
-#ifndef WINDOWS
-# ifdef QNX
- page_size = 4096;
-# else
- page_size = getpagesize();
-# endif
-#else
- PRIVATE->hProc = 0;
- PRIVATE->mem_cnt.cb = sizeof(PRIVATE->mem_cnt);
-#endif
-#endif
- setName("system_monitor");
-}
-
-
-PISystemMonitor::~PISystemMonitor() {
- stop();
-}
-
-
-#ifndef FREERTOS
-bool PISystemMonitor::startOnProcess(int pID, int interval_ms) {
- stop();
- pID_ = pID;
- Pool::instance()->add(this);
- cycle = -1;
-#ifndef WINDOWS
-# ifndef MAC_OS
- PRIVATE->proc_dir = PIStringAscii("/proc/") + PIString::fromNumber(pID_) + PIStringAscii("/");
- PRIVATE->file. open(PRIVATE->proc_dir + "stat", PIIODevice::ReadOnly);
- PRIVATE->filem.open(PRIVATE->proc_dir + "statm", PIIODevice::ReadOnly);
- if (!PRIVATE->file.isOpened()) {
- piCoutObj << "Can`t find process with ID = " << pID_ << "!";
- return false;
- }
-# endif
-#else
- PRIVATE->hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pID_);
- if (PRIVATE->hProc == 0) {
- piCoutObj << "Can`t open process with ID = " << pID_ << "," << errorString();
- return false;
- }
- PRIVATE->tm.reset();
-#endif
- return start(interval_ms);
-}
-#endif
-
-
-bool PISystemMonitor::startOnSelf(int interval_ms) {
-#ifndef FREERTOS
- bool ret = startOnProcess(PIProcess::currentPID(), interval_ms);
- cycle = -1;
-#else
- bool ret = start(interval_ms);
-#endif
- return ret;
-}
-
-
-PIVector PISystemMonitor::threadsStatistic() const {
- mutex_.lock();
- PIVector ret = cur_ts;
- mutex_.unlock();
- return ret;
-}
-
-
-void PISystemMonitor::setStatistic(const PISystemMonitor::ProcessStats & s) {
- PIMutexLocker _ml(stat_mutex);
- stat = s;
- stat.makeStrings();
-}
-
-
-void PISystemMonitor::stop() {
- PIThread::stop();
-#ifdef WINDOWS
- if (PRIVATE->hProc != 0) {
- CloseHandle(PRIVATE->hProc);
- PRIVATE->hProc = 0;
- }
-#endif
- Pool::instance()->remove(this);
-}
-
-
-PISystemMonitor::ProcessStats PISystemMonitor::statistic() const {
- PIMutexLocker _ml(stat_mutex);
- return stat;
-}
-
-
-#ifdef MAC_OS
-PISystemTime uint64toST(uint64_t v) {
- return PISystemTime(((uint*)&(v))[1], ((uint*)&(v))[0]);
-}
-#endif
-
-void PISystemMonitor::run() {
- cur_tm.clear();
- tbid.clear();
- __PIThreadCollection * pitc = __PIThreadCollection::instance();
- pitc->lock();
- PIVector tv = pitc->threads();
- piForeach (PIThread * t, tv)
- if (t->isPIObject())
- tbid[t->tid()] = t->name();
- pitc->unlock();
- //piCout << tbid.keys().toType();
- ProcessStats tstat;
- tstat.ID = pID_;
-#ifdef FREERTOS
- piForeach (PIThread * t, tv)
- if (t->isPIObject())
- gatherThread(t->tid());
-#else
-#ifndef WINDOWS
- tbid[pID_] = "main";
-# ifdef MAC_OS
- rusage_info_current ru;
- proc_pid_rusage(pID_, RUSAGE_INFO_CURRENT, (rusage_info_t*)&ru);
- //piCout << PISystemTime(((uint*)&(ru.ri_user_time))[1], ((uint*)&(ru.ri_user_time))[0]);
- if (cycle < 0) {
- PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur = uint64toST(ru.ri_user_time);
- PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur = uint64toST(ru.ri_system_time);
- }
- PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur;
- PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur;
- PRIVATE->cpu_u_cur = uint64toST(ru.ri_user_time);
- PRIVATE->cpu_s_cur = uint64toST(ru.ri_system_time);
- tstat.cpu_load_system = 100.f * (PRIVATE->cpu_s_cur - PRIVATE->cpu_s_prev).toMilliseconds() / delay_;
- tstat.cpu_load_user = 100.f * (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_;
- cycle = 0;
- //piCout << (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_;
-# else
- PRIVATE->file.seekToBegin();
- PIString str(PRIVATE->file.readAll(true));
- int si = str.find('(') + 1, fi = 0, cc = 1;
- for (int i = si; i < str.size_s(); ++i) {
- if (str[i] == '(') cc++;
- if (str[i] == ')') cc--;
- if (cc <= 0) {
- fi = i;
- break;
- }
- }
- tstat.exec_name = str.mid(si, fi - si);
- str.cutMid(si - 1, fi - si + 3);
- PIStringList sl = str.split(" ");
- if (sl.size_s() < 19) return;
- tstat.ID = sl[0].toInt();
- tstat.state = sl[1];
- tstat.parent_ID = sl[2].toInt();
- tstat.group_ID = sl[3].toInt();
- tstat.session_ID = sl[4].toInt();
- if (cycle < 0) {
- PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur = sl[12].toLLong();
- PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur = sl[13].toLLong();
- }
- PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur;
- PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur;
- PRIVATE->cpu_u_cur = sl[12].toLLong();
- PRIVATE->cpu_s_cur = sl[13].toLLong();
- tstat.cpu_load_system = (PRIVATE->cpu_s_cur - PRIVATE->cpu_s_prev) / (delay_ / 1000.);
- tstat.cpu_load_user = (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev) / (delay_ / 1000.);
- tstat.cpu_load_system /= cpu_count;
- tstat.cpu_load_user /= cpu_count;
- cycle = 0;
- tstat.priority = sl[16].toInt();
- tstat.threads = sl[18].toInt();
- //piCout << "\n";
- //piCout << sl[0] << sl[12] << sl[13];
-
- PRIVATE->filem.seekToBegin();
- str = PRIVATE->filem.readAll(true);
- sl = str.split(" ");
- if (sl.size_s() < 6) return;
- tstat.virtual_memsize = sl[0].toLong() * page_size;
- tstat.resident_memsize = sl[1].toLong() * page_size;
- tstat.share_memsize = sl[2].toLong() * page_size;
- tstat.data_memsize = sl[5].toLong() * page_size;
- tstat.physical_memsize = tstat.resident_memsize - tstat.share_memsize;
-
- PIVector tld = PIDir(PRIVATE->proc_dir + "task").entries();
- piForeachC (PIFile::FileInfo & i, tld) {
- if (i.flags[PIFile::FileInfo::Dot] || i.flags[PIFile::FileInfo::DotDot])
- continue;
- gatherThread(i.name().toInt());
- }
-# endif
-#else
- if (GetProcessMemoryInfo(PRIVATE->hProc, &PRIVATE->mem_cnt, sizeof(PRIVATE->mem_cnt)) != 0) {
- tstat.physical_memsize = PRIVATE->mem_cnt.WorkingSetSize;
- }
- tstat.priority = GetPriorityClass(PRIVATE->hProc);
- HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, pID_);
- int thcnt = 0;
- if (snap != 0) {
- THREADENTRY32 thread;
- thread.dwSize = sizeof(THREADENTRY32);
- if (Thread32First(snap, &thread) == TRUE) {
- if (thread.th32OwnerProcessID == DWORD(pID_)) {
- ++thcnt;
- gatherThread(thread.th32ThreadID);
- }
- while (Thread32Next(snap, &thread) == TRUE) {
- if (thread.th32OwnerProcessID == DWORD(pID_)) {
- ++thcnt;
- gatherThread(thread.th32ThreadID);
- }
- //piCout << thread.th32ThreadID;
- }
- }
- tstat.threads = thcnt;
- CloseHandle(snap);
- }
- FILETIME ft0, ft1, ft_kernel, ft_user;
- double el_s = PRIVATE->tm.elapsed_s() * cpu_count / 100.;
- if (GetProcessTimes(PRIVATE->hProc, &ft0, &ft1, &ft_kernel, &ft_user) != 0) {
- PISystemTime tm_kernel_c = FILETIME2PISystemTime(ft_kernel);
- PISystemTime tm_user_c = FILETIME2PISystemTime(ft_user);
- if (cycle < 0) {
- PRIVATE->tm_kernel = tm_kernel_c;
- PRIVATE->tm_user = tm_user_c;
- }
- cycle = 0;
- if (el_s <= 0.) {
- tstat.cpu_load_system = 0.f;
- tstat.cpu_load_user = 0.f;
- } else {
- tstat.cpu_load_system = (tm_kernel_c - PRIVATE->tm_kernel).toSeconds() / el_s;
- tstat.cpu_load_user = (tm_user_c - PRIVATE->tm_user).toSeconds() / el_s;
- }
- PRIVATE->tm_kernel = tm_kernel_c;
- PRIVATE->tm_user = tm_user_c;
- } else {
- tstat.cpu_load_system = 0.f;
- tstat.cpu_load_user = 0.f;
- }
- PRIVATE->tm.reset();
-#endif
-#endif
-
- tstat.cpu_load_system = piClampf(tstat.cpu_load_system, 0.f, 100.f);
- tstat.cpu_load_user = piClampf(tstat.cpu_load_user , 0.f, 100.f);
-
- auto i = cur_tm.makeIterator();
- while (i.next()) {
- if (!last_tm.contains(i.key())) continue;
- ThreadStats & ts_new(i.valueRef());
- ThreadStats & ts_old(last_tm[i.key()]);
- ts_new.cpu_load_kernel = calcThreadUsage(ts_new.kernel_time, ts_old.kernel_time);
- ts_new.cpu_load_user = calcThreadUsage(ts_new.user_time, ts_old.user_time);
- //piCout << ts_new.cpu_load_user;
- }
- last_tm = cur_tm;
- lock();
- cur_ts = cur_tm.values();
- unlock();
- tstat.ram_total = totalRAM();
- tstat.ram_used = usedRAM();
- tstat.ram_free = freeRAM();
- stat_mutex.lock();
- stat = tstat;
- stat.makeStrings();
- stat_mutex.unlock();
-}
-
-
-void PISystemMonitor::gatherThread(llong id) {
- PISystemMonitor::ThreadStats ts;
- ts.id = id;
-#ifdef FREERTOS
- ts.name = tbid.value(id, "");
-#else
- ts.name = tbid.value(id, "");
-# ifndef WINDOWS
- PIFile f(PRIVATE->proc_dir + "task/" + PIString::fromNumber(id) + "/stat");
- //piCout << f.path();
- if (!f.open(PIIODevice::ReadOnly))
- return;
- PIString str = f.readAll(true);
- int si = str.find('(') + 1, fi = 0, cc = 1;
- for (int i = si; i < str.size_s(); ++i) {
- if (str[i] == '(') cc++;
- if (str[i] == ')') cc--;
- if (cc <= 0) {
- fi = i;
- break;
- }
- }
- str.cutMid(si - 1, fi - si + 3);
- PIStringList sl = str.split(" ");
- if (sl.size_s() < 14) return;
- //piCout << sl[0] << sl[12] << sl[13];
- ts.user_time = PISystemTime::fromMilliseconds(sl[12].toInt() * 10.);
- ts.kernel_time = PISystemTime::fromMilliseconds(sl[13].toInt() * 10.);
-# else
- PISystemTime ct = PISystemTime::current();
- FILETIME times[4];
- HANDLE thdl = OpenThread(THREAD_QUERY_INFORMATION, FALSE, DWORD(id));
- if (thdl == NULL) {
- piCout << "[PISystemMonitor] gatherThread(" << id << "):: OpenThread() error:" << errorString();
- return;
- }
- if (GetThreadTimes(thdl, &(times[0]), &(times[1]), &(times[2]), &(times[3])) == 0) {
- piCout << "[PISystemMonitor] gatherThread(" << id << "):: GetThreadTimes() error:" << errorString();
- return;
- }
- CloseHandle(thdl);
- ts.created = FILETIME2PIDateTime(times[0]);
- ts.work_time = ct - ts.created.toSystemTime();
- ts.kernel_time = FILETIME2PISystemTime(times[2]);
- ts.user_time = FILETIME2PISystemTime(times[3]);
-# endif
-#endif
- cur_tm[id] = ts;
-}
-
-
-float PISystemMonitor::calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old) {
- if (delay_ <= 0) return -1.;
- return piClampf(100. * ((t_new - t_old).toMilliseconds() / delay_), 0.f, 100.f);
-}
-
-
-ullong PISystemMonitor::totalRAM() {
-#ifdef ESP_PLATFORM
- multi_heap_info_t heap_info;
- memset(&heap_info, 0, sizeof(multi_heap_info_t));
- heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
- return heap_info.total_allocated_bytes + heap_info.total_free_bytes;
-#endif
- return 0;
-}
-
-
-ullong PISystemMonitor::freeRAM() {
-#ifdef ESP_PLATFORM
- multi_heap_info_t heap_info;
- memset(&heap_info, 0, sizeof(multi_heap_info_t));
- heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
- return heap_info.total_free_bytes;
-#endif
- return 0;
-}
-
-
-ullong PISystemMonitor::usedRAM() {
-#ifdef ESP_PLATFORM
- multi_heap_info_t heap_info;
- memset(&heap_info, 0, sizeof(multi_heap_info_t));
- heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
- return heap_info.total_allocated_bytes;
-#endif
- return 0;
-}
-
-
-
-
-PISystemMonitor::Pool * PISystemMonitor::Pool::instance() {
- static Pool ret;
- return &ret;
-}
-
-
-PISystemMonitor * PISystemMonitor::Pool::getByPID(int pID) {
- PIMutexLocker _ml(mutex);
- return sysmons.value(pID, 0);
-}
-
-
-void PISystemMonitor::Pool::add(PISystemMonitor * sm) {
- PIMutexLocker _ml(mutex);
- sysmons[sm->pID()] = sm;
-}
-
-
-void PISystemMonitor::Pool::remove(PISystemMonitor * sm) {
- PIMutexLocker _ml(mutex);
- sysmons.remove(sm->pID());
-}
-
-
-
-
-PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ProcessStats & v) {
- s << PIByteArray::RawData(&v, sizeof(PISystemMonitor::ProcessStatsFixed))
- << v.exec_name << v.state;
- return s;
-}
-
-
-PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ProcessStats & v) {
- s >> PIByteArray::RawData(&v, sizeof(PISystemMonitor::ProcessStatsFixed))
- >> v.exec_name >> v.state;
- v.makeStrings();
- return s;
-}
-
-
-PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ThreadStats & v) {
- s << PIByteArray::RawData(&v, sizeof(PISystemMonitor::ThreadStatsFixed))
- << v.name << v.created;
- return s;
-}
-
-
-PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ThreadStats & v) {
- s >> PIByteArray::RawData(&v, sizeof(PISystemMonitor::ThreadStatsFixed))
- >> v.name >> v.created;
- return s;
-}
+/*
+ PIP - Platform Independent Primitives
+ Process resource monitor
+ Ivan Pelipenko peri4ko@yandex.ru
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#include "piincludes_p.h"
+#include "pisystemmonitor.h"
+#include "pisysteminfo.h"
+#include "piprocess.h"
+#include "pidir.h"
+#include "pitime_win.h"
+#ifdef WINDOWS
+# include
+# include
+#endif
+#ifdef MAC_OS
+ struct kqueue_id_t;
+# include
+# include
+#endif
+#ifdef ESP_PLATFORM
+# include "esp_heap_caps.h"
+#endif
+
+
+PISystemMonitor::ProcessStatsFixed::ProcessStatsFixed() {
+ ID = parent_ID = group_ID = session_ID = priority = threads = 0;
+ physical_memsize = resident_memsize = share_memsize = virtual_memsize = data_memsize = 0;
+ cpu_load_user = cpu_load_system = 0.f;
+}
+
+
+void PISystemMonitor::ProcessStats::makeStrings() {
+ physical_memsize_readable.setReadableSize(physical_memsize);
+ resident_memsize_readable.setReadableSize(resident_memsize);
+ share_memsize_readable.setReadableSize(share_memsize);
+ virtual_memsize_readable.setReadableSize(virtual_memsize);
+ data_memsize_readable.setReadableSize(data_memsize);
+}
+
+
+PISystemMonitor::ThreadStatsFixed::ThreadStatsFixed() {
+ id = 0;
+ cpu_load_kernel = cpu_load_user = -1.f;
+}
+
+
+#ifndef FREERTOS
+PRIVATE_DEFINITION_START(PISystemMonitor)
+#ifndef WINDOWS
+# ifdef MAC_OS
+ PISystemTime
+# else
+ llong
+# endif
+ cpu_u_cur, cpu_u_prev, cpu_s_cur, cpu_s_prev;
+ PIString proc_dir;
+ PIFile file, filem;
+#else
+ HANDLE hProc;
+ PROCESS_MEMORY_COUNTERS mem_cnt;
+ PISystemTime tm_kernel, tm_user;
+ PITimeMeasurer tm;
+#endif
+PRIVATE_DEFINITION_END(PISystemMonitor)
+#endif
+
+
+PISystemMonitor::PISystemMonitor(): PIThread() {
+ pID_ = cycle = 0;
+ cpu_count = PISystemInfo::instance()->processorsCount;
+#ifndef FREERTOS
+#ifndef WINDOWS
+# ifdef QNX
+ page_size = 4096;
+# else
+ page_size = getpagesize();
+# endif
+#else
+ PRIVATE->hProc = 0;
+ PRIVATE->mem_cnt.cb = sizeof(PRIVATE->mem_cnt);
+#endif
+#endif
+ setName("system_monitor");
+}
+
+
+PISystemMonitor::~PISystemMonitor() {
+ stop();
+}
+
+
+#ifndef FREERTOS
+bool PISystemMonitor::startOnProcess(int pID, int interval_ms) {
+ stop();
+ pID_ = pID;
+ Pool::instance()->add(this);
+ cycle = -1;
+#ifndef WINDOWS
+# ifndef MAC_OS
+ PRIVATE->proc_dir = PIStringAscii("/proc/") + PIString::fromNumber(pID_) + PIStringAscii("/");
+ PRIVATE->file. open(PRIVATE->proc_dir + "stat", PIIODevice::ReadOnly);
+ PRIVATE->filem.open(PRIVATE->proc_dir + "statm", PIIODevice::ReadOnly);
+ if (!PRIVATE->file.isOpened()) {
+ piCoutObj << "Can`t find process with ID = " << pID_ << "!";
+ return false;
+ }
+# endif
+#else
+ PRIVATE->hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pID_);
+ if (PRIVATE->hProc == 0) {
+ piCoutObj << "Can`t open process with ID = " << pID_ << "," << errorString();
+ return false;
+ }
+ PRIVATE->tm.reset();
+#endif
+ return start(interval_ms);
+}
+#endif
+
+
+bool PISystemMonitor::startOnSelf(int interval_ms) {
+#ifndef FREERTOS
+ bool ret = startOnProcess(PIProcess::currentPID(), interval_ms);
+ cycle = -1;
+#else
+ bool ret = start(interval_ms);
+#endif
+ return ret;
+}
+
+
+PIVector PISystemMonitor::threadsStatistic() const {
+ mutex_.lock();
+ PIVector ret = cur_ts;
+ mutex_.unlock();
+ return ret;
+}
+
+
+void PISystemMonitor::setStatistic(const PISystemMonitor::ProcessStats & s) {
+ PIMutexLocker _ml(stat_mutex);
+ stat = s;
+ stat.makeStrings();
+}
+
+
+void PISystemMonitor::stop() {
+ PIThread::stop();
+#ifdef WINDOWS
+ if (PRIVATE->hProc != 0) {
+ CloseHandle(PRIVATE->hProc);
+ PRIVATE->hProc = 0;
+ }
+#endif
+ Pool::instance()->remove(this);
+}
+
+
+PISystemMonitor::ProcessStats PISystemMonitor::statistic() const {
+ PIMutexLocker _ml(stat_mutex);
+ return stat;
+}
+
+
+#ifdef MAC_OS
+PISystemTime uint64toST(uint64_t v) {
+ return PISystemTime(((uint*)&(v))[1], ((uint*)&(v))[0]);
+}
+#endif
+
+void PISystemMonitor::run() {
+ cur_tm.clear();
+ tbid.clear();
+ __PIThreadCollection * pitc = __PIThreadCollection::instance();
+ pitc->lock();
+ PIVector tv = pitc->threads();
+ piForeach (PIThread * t, tv)
+ if (t->isPIObject())
+ tbid[t->tid()] = t->name();
+ pitc->unlock();
+ //piCout << tbid.keys().toType();
+ ProcessStats tstat;
+ tstat.ID = pID_;
+#ifdef FREERTOS
+ piForeach (PIThread * t, tv)
+ if (t->isPIObject())
+ gatherThread(t->tid());
+#else
+#ifndef WINDOWS
+ tbid[pID_] = "main";
+# ifdef MAC_OS
+ rusage_info_current ru;
+ proc_pid_rusage(pID_, RUSAGE_INFO_CURRENT, (rusage_info_t*)&ru);
+ //piCout << PISystemTime(((uint*)&(ru.ri_user_time))[1], ((uint*)&(ru.ri_user_time))[0]);
+ if (cycle < 0) {
+ PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur = uint64toST(ru.ri_user_time);
+ PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur = uint64toST(ru.ri_system_time);
+ }
+ PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur;
+ PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur;
+ PRIVATE->cpu_u_cur = uint64toST(ru.ri_user_time);
+ PRIVATE->cpu_s_cur = uint64toST(ru.ri_system_time);
+ tstat.cpu_load_system = 100.f * (PRIVATE->cpu_s_cur - PRIVATE->cpu_s_prev).toMilliseconds() / delay_;
+ tstat.cpu_load_user = 100.f * (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_;
+ cycle = 0;
+ //piCout << (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_;
+# else
+ PRIVATE->file.seekToBegin();
+ PIString str(PRIVATE->file.readAll(true));
+ int si = str.find('(') + 1, fi = 0, cc = 1;
+ for (int i = si; i < str.size_s(); ++i) {
+ if (str[i] == '(') cc++;
+ if (str[i] == ')') cc--;
+ if (cc <= 0) {
+ fi = i;
+ break;
+ }
+ }
+ tstat.exec_name = str.mid(si, fi - si);
+ str.cutMid(si - 1, fi - si + 3);
+ PIStringList sl = str.split(" ");
+ if (sl.size_s() < 19) return;
+ tstat.ID = sl[0].toInt();
+ tstat.state = sl[1];
+ tstat.parent_ID = sl[2].toInt();
+ tstat.group_ID = sl[3].toInt();
+ tstat.session_ID = sl[4].toInt();
+ if (cycle < 0) {
+ PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur = sl[12].toLLong();
+ PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur = sl[13].toLLong();
+ }
+ PRIVATE->cpu_u_prev = PRIVATE->cpu_u_cur;
+ PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur;
+ PRIVATE->cpu_u_cur = sl[12].toLLong();
+ PRIVATE->cpu_s_cur = sl[13].toLLong();
+ tstat.cpu_load_system = (PRIVATE->cpu_s_cur - PRIVATE->cpu_s_prev) / (delay_ / 1000.);
+ tstat.cpu_load_user = (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev) / (delay_ / 1000.);
+ tstat.cpu_load_system /= cpu_count;
+ tstat.cpu_load_user /= cpu_count;
+ cycle = 0;
+ tstat.priority = sl[16].toInt();
+ tstat.threads = sl[18].toInt();
+ //piCout << "\n";
+ //piCout << sl[0] << sl[12] << sl[13];
+
+ PRIVATE->filem.seekToBegin();
+ str = PRIVATE->filem.readAll(true);
+ sl = str.split(" ");
+ if (sl.size_s() < 6) return;
+ tstat.virtual_memsize = sl[0].toLong() * page_size;
+ tstat.resident_memsize = sl[1].toLong() * page_size;
+ tstat.share_memsize = sl[2].toLong() * page_size;
+ tstat.data_memsize = sl[5].toLong() * page_size;
+ tstat.physical_memsize = tstat.resident_memsize - tstat.share_memsize;
+
+ PIVector tld = PIDir(PRIVATE->proc_dir + "task").entries();
+ piForeachC (PIFile::FileInfo & i, tld) {
+ if (i.flags[PIFile::FileInfo::Dot] || i.flags[PIFile::FileInfo::DotDot])
+ continue;
+ gatherThread(i.name().toInt());
+ }
+# endif
+#else
+ if (GetProcessMemoryInfo(PRIVATE->hProc, &PRIVATE->mem_cnt, sizeof(PRIVATE->mem_cnt)) != 0) {
+ tstat.physical_memsize = PRIVATE->mem_cnt.WorkingSetSize;
+ }
+ tstat.priority = GetPriorityClass(PRIVATE->hProc);
+ HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, pID_);
+ int thcnt = 0;
+ if (snap != 0) {
+ THREADENTRY32 thread;
+ thread.dwSize = sizeof(THREADENTRY32);
+ if (Thread32First(snap, &thread) == TRUE) {
+ if (thread.th32OwnerProcessID == DWORD(pID_)) {
+ ++thcnt;
+ gatherThread(thread.th32ThreadID);
+ }
+ while (Thread32Next(snap, &thread) == TRUE) {
+ if (thread.th32OwnerProcessID == DWORD(pID_)) {
+ ++thcnt;
+ gatherThread(thread.th32ThreadID);
+ }
+ //piCout << thread.th32ThreadID;
+ }
+ }
+ tstat.threads = thcnt;
+ CloseHandle(snap);
+ }
+ FILETIME ft0, ft1, ft_kernel, ft_user;
+ double el_s = PRIVATE->tm.elapsed_s() * cpu_count / 100.;
+ if (GetProcessTimes(PRIVATE->hProc, &ft0, &ft1, &ft_kernel, &ft_user) != 0) {
+ PISystemTime tm_kernel_c = FILETIME2PISystemTime(ft_kernel);
+ PISystemTime tm_user_c = FILETIME2PISystemTime(ft_user);
+ if (cycle < 0) {
+ PRIVATE->tm_kernel = tm_kernel_c;
+ PRIVATE->tm_user = tm_user_c;
+ }
+ cycle = 0;
+ if (el_s <= 0.) {
+ tstat.cpu_load_system = 0.f;
+ tstat.cpu_load_user = 0.f;
+ } else {
+ tstat.cpu_load_system = (tm_kernel_c - PRIVATE->tm_kernel).toSeconds() / el_s;
+ tstat.cpu_load_user = (tm_user_c - PRIVATE->tm_user).toSeconds() / el_s;
+ }
+ PRIVATE->tm_kernel = tm_kernel_c;
+ PRIVATE->tm_user = tm_user_c;
+ } else {
+ tstat.cpu_load_system = 0.f;
+ tstat.cpu_load_user = 0.f;
+ }
+ PRIVATE->tm.reset();
+#endif
+#endif
+
+ tstat.cpu_load_system = piClampf(tstat.cpu_load_system, 0.f, 100.f);
+ tstat.cpu_load_user = piClampf(tstat.cpu_load_user , 0.f, 100.f);
+
+ auto i = cur_tm.makeIterator();
+ while (i.next()) {
+ if (!last_tm.contains(i.key())) continue;
+ ThreadStats & ts_new(i.valueRef());
+ ThreadStats & ts_old(last_tm[i.key()]);
+ ts_new.cpu_load_kernel = calcThreadUsage(ts_new.kernel_time, ts_old.kernel_time);
+ ts_new.cpu_load_user = calcThreadUsage(ts_new.user_time, ts_old.user_time);
+ //piCout << ts_new.cpu_load_user;
+ }
+ last_tm = cur_tm;
+ mutex_.lock();
+ cur_ts = cur_tm.values();
+ mutex_.unlock();
+ tstat.ram_total = totalRAM();
+ tstat.ram_used = usedRAM();
+ tstat.ram_free = freeRAM();
+ stat_mutex.lock();
+ stat = tstat;
+ stat.makeStrings();
+ stat_mutex.unlock();
+}
+
+
+void PISystemMonitor::gatherThread(llong id) {
+ PISystemMonitor::ThreadStats ts;
+ ts.id = id;
+#ifdef FREERTOS
+ ts.name = tbid.value(id, "");
+#else
+ ts.name = tbid.value(id, "");
+# ifndef WINDOWS
+ PIFile f(PRIVATE->proc_dir + "task/" + PIString::fromNumber(id) + "/stat");
+ //piCout << f.path();
+ if (!f.open(PIIODevice::ReadOnly))
+ return;
+ PIString str = f.readAll(true);
+ int si = str.find('(') + 1, fi = 0, cc = 1;
+ for (int i = si; i < str.size_s(); ++i) {
+ if (str[i] == '(') cc++;
+ if (str[i] == ')') cc--;
+ if (cc <= 0) {
+ fi = i;
+ break;
+ }
+ }
+ str.cutMid(si - 1, fi - si + 3);
+ PIStringList sl = str.split(" ");
+ if (sl.size_s() < 14) return;
+ //piCout << sl[0] << sl[12] << sl[13];
+ ts.user_time = PISystemTime::fromMilliseconds(sl[12].toInt() * 10.);
+ ts.kernel_time = PISystemTime::fromMilliseconds(sl[13].toInt() * 10.);
+# else
+ PISystemTime ct = PISystemTime::current();
+ FILETIME times[4];
+ HANDLE thdl = OpenThread(THREAD_QUERY_INFORMATION, FALSE, DWORD(id));
+ if (thdl == NULL) {
+ piCout << "[PISystemMonitor] gatherThread(" << id << "):: OpenThread() error:" << errorString();
+ return;
+ }
+ if (GetThreadTimes(thdl, &(times[0]), &(times[1]), &(times[2]), &(times[3])) == 0) {
+ piCout << "[PISystemMonitor] gatherThread(" << id << "):: GetThreadTimes() error:" << errorString();
+ return;
+ }
+ CloseHandle(thdl);
+ ts.created = FILETIME2PIDateTime(times[0]);
+ ts.work_time = ct - ts.created.toSystemTime();
+ ts.kernel_time = FILETIME2PISystemTime(times[2]);
+ ts.user_time = FILETIME2PISystemTime(times[3]);
+# endif
+#endif
+ cur_tm[id] = ts;
+}
+
+
+float PISystemMonitor::calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old) {
+ if (delay_ <= 0) return -1.;
+ return piClampf(100. * ((t_new - t_old).toMilliseconds() / delay_), 0.f, 100.f);
+}
+
+
+ullong PISystemMonitor::totalRAM() {
+#ifdef ESP_PLATFORM
+ multi_heap_info_t heap_info;
+ memset(&heap_info, 0, sizeof(multi_heap_info_t));
+ heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
+ return heap_info.total_allocated_bytes + heap_info.total_free_bytes;
+#endif
+ return 0;
+}
+
+
+ullong PISystemMonitor::freeRAM() {
+#ifdef ESP_PLATFORM
+ multi_heap_info_t heap_info;
+ memset(&heap_info, 0, sizeof(multi_heap_info_t));
+ heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
+ return heap_info.total_free_bytes;
+#endif
+ return 0;
+}
+
+
+ullong PISystemMonitor::usedRAM() {
+#ifdef ESP_PLATFORM
+ multi_heap_info_t heap_info;
+ memset(&heap_info, 0, sizeof(multi_heap_info_t));
+ heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
+ return heap_info.total_allocated_bytes;
+#endif
+ return 0;
+}
+
+
+
+
+PISystemMonitor::Pool * PISystemMonitor::Pool::instance() {
+ static Pool ret;
+ return &ret;
+}
+
+
+PISystemMonitor * PISystemMonitor::Pool::getByPID(int pID) {
+ PIMutexLocker _ml(mutex);
+ return sysmons.value(pID, 0);
+}
+
+
+void PISystemMonitor::Pool::add(PISystemMonitor * sm) {
+ PIMutexLocker _ml(mutex);
+ sysmons[sm->pID()] = sm;
+}
+
+
+void PISystemMonitor::Pool::remove(PISystemMonitor * sm) {
+ PIMutexLocker _ml(mutex);
+ sysmons.remove(sm->pID());
+}
+
+
+
+
+PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ProcessStats & v) {
+ s << PIByteArray::RawData(&v, sizeof(PISystemMonitor::ProcessStatsFixed))
+ << v.exec_name << v.state;
+ return s;
+}
+
+
+PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ProcessStats & v) {
+ s >> PIByteArray::RawData(&v, sizeof(PISystemMonitor::ProcessStatsFixed))
+ >> v.exec_name >> v.state;
+ v.makeStrings();
+ return s;
+}
+
+
+PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ThreadStats & v) {
+ s << PIByteArray::RawData(&v, sizeof(PISystemMonitor::ThreadStatsFixed))
+ << v.name;
+ return s;
+}
+
+
+PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ThreadStats & v) {
+ s >> PIByteArray::RawData(&v, sizeof(PISystemMonitor::ThreadStatsFixed))
+ >> v.name;
+ return s;
+}
diff --git a/libs/main/system/pisystemmonitor.h b/libs/main/system/pisystemmonitor.h
index f3407f81..dbae9e97 100644
--- a/libs/main/system/pisystemmonitor.h
+++ b/libs/main/system/pisystemmonitor.h
@@ -1,144 +1,144 @@
-/*
- PIP - Platform Independent Primitives
- Process resource monitor
- Ivan Pelipenko peri4ko@yandex.ru
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see .
-*/
-
-#ifndef PISYSTEMMONITOR_H
-#define PISYSTEMMONITOR_H
-
-#include "pithread.h"
-#include "pifile.h"
-
-class PIP_EXPORT PISystemMonitor: public PIThread
-{
- PIOBJECT_SUBCLASS(PISystemMonitor, PIThread)
- friend class PIIntrospectionServer;
-public:
- PISystemMonitor();
- ~PISystemMonitor();
-
-#pragma pack(push, 1)
- struct PIP_EXPORT ProcessStatsFixed {
- ProcessStatsFixed();
- int ID;
- int parent_ID;
- int group_ID;
- int session_ID;
- int priority;
- int threads;
- ullong physical_memsize;
- ullong resident_memsize;
- ullong share_memsize;
- ullong virtual_memsize;
- ullong data_memsize;
- ullong ram_total;
- ullong ram_free;
- ullong ram_used;
- float cpu_load_system;
- float cpu_load_user;
- };
-
- struct PIP_EXPORT ThreadStatsFixed {
- ThreadStatsFixed();
- llong id;
- PISystemTime work_time;
- PISystemTime kernel_time;
- PISystemTime user_time;
- float cpu_load_kernel;
- float cpu_load_user;
- };
-#pragma pack(pop)
-
- struct PIP_EXPORT ProcessStats: ProcessStatsFixed {
- void makeStrings();
- PIString exec_name;
- PIString state;
- PIString physical_memsize_readable;
- PIString resident_memsize_readable;
- PIString share_memsize_readable;
- PIString virtual_memsize_readable;
- PIString data_memsize_readable;
- };
-
- struct PIP_EXPORT ThreadStats: ThreadStatsFixed {
- PIString name;
- PIDateTime created;
- };
-
-#ifndef FREERTOS
- bool startOnProcess(int pID, int interval_ms = 1000);
-#endif
- bool startOnSelf(int interval_ms = 1000);
- void stop();
-
- int pID() const {return pID_;}
- ProcessStats statistic() const;
- PIVector threadsStatistic() const;
- void setStatistic(const ProcessStats & s);
-
- static ullong totalRAM();
- static ullong freeRAM();
- static ullong usedRAM();
-
-
-private:
- void run();
- void gatherThread(llong id);
- float calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old);
-
- ProcessStats stat;
- PIVector cur_ts;
- PIMap last_tm, cur_tm;
- PIMap tbid;
- mutable PIMutex stat_mutex;
- int pID_, page_size, cpu_count, cycle;
-#ifndef FREERTOS
- PRIVATE_DECLARATION(PIP_EXPORT)
-#endif
-
- class PIP_EXPORT Pool {
- friend class PISystemMonitor;
- public:
- static Pool * instance();
- PISystemMonitor * getByPID(int pID);
- private:
- void add(PISystemMonitor * sm);
- void remove(PISystemMonitor * sm);
- PIMap sysmons;
- PIMutex mutex;
- };
-
-
-};
-
-inline PICout operator <<(PICout s, const PISystemMonitor::ThreadStats & v) {
- s.setControl(0, true);
- s << "ThreadInfo(\"" << v.name << "\", created " << v.created
- << ", work " << v.work_time.toMilliseconds() << " ms"
- << ", kernel " << v.kernel_time.toMilliseconds() << " ms"
- << ", user " << v.user_time.toMilliseconds() << " ms"
- << ")\n";
- s.restoreControl();
- return s;
-}
-
-PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ProcessStats & v);
-PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ProcessStats & v);
-PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ThreadStats & v);
-PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ThreadStats & v);
-
-#endif // PISYSTEMMONITOR_H
+/*
+ PIP - Platform Independent Primitives
+ Process resource monitor
+ Ivan Pelipenko peri4ko@yandex.ru
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef PISYSTEMMONITOR_H
+#define PISYSTEMMONITOR_H
+
+#include "pithread.h"
+#include "pifile.h"
+
+class PIP_EXPORT PISystemMonitor: public PIThread
+{
+ PIOBJECT_SUBCLASS(PISystemMonitor, PIThread)
+ friend class PIIntrospectionServer;
+public:
+ PISystemMonitor();
+ ~PISystemMonitor();
+
+#pragma pack(push, 1)
+ struct PIP_EXPORT ProcessStatsFixed {
+ ProcessStatsFixed();
+ int ID;
+ int parent_ID;
+ int group_ID;
+ int session_ID;
+ int priority;
+ int threads;
+ ullong physical_memsize;
+ ullong resident_memsize;
+ ullong share_memsize;
+ ullong virtual_memsize;
+ ullong data_memsize;
+ ullong ram_total;
+ ullong ram_free;
+ ullong ram_used;
+ float cpu_load_system;
+ float cpu_load_user;
+ };
+
+ struct PIP_EXPORT ThreadStatsFixed {
+ ThreadStatsFixed();
+ llong id;
+ PISystemTime work_time;
+ PISystemTime kernel_time;
+ PISystemTime user_time;
+ float cpu_load_kernel;
+ float cpu_load_user;
+ PIDateTime created;
+ };
+#pragma pack(pop)
+
+ struct PIP_EXPORT ProcessStats: ProcessStatsFixed {
+ void makeStrings();
+ PIString exec_name;
+ PIString state;
+ PIString physical_memsize_readable;
+ PIString resident_memsize_readable;
+ PIString share_memsize_readable;
+ PIString virtual_memsize_readable;
+ PIString data_memsize_readable;
+ };
+
+ struct PIP_EXPORT ThreadStats: ThreadStatsFixed {
+ PIString name;
+ };
+
+#ifndef FREERTOS
+ bool startOnProcess(int pID, int interval_ms = 1000);
+#endif
+ bool startOnSelf(int interval_ms = 1000);
+ void stop();
+
+ int pID() const {return pID_;}
+ ProcessStats statistic() const;
+ PIVector threadsStatistic() const;
+ void setStatistic(const ProcessStats & s);
+
+ static ullong totalRAM();
+ static ullong freeRAM();
+ static ullong usedRAM();
+
+
+private:
+ void run();
+ void gatherThread(llong id);
+ float calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old);
+
+ ProcessStats stat;
+ PIVector cur_ts;
+ PIMap last_tm, cur_tm;
+ PIMap tbid;
+ mutable PIMutex stat_mutex;
+ int pID_, page_size, cpu_count, cycle;
+#ifndef FREERTOS
+ PRIVATE_DECLARATION(PIP_EXPORT)
+#endif
+
+ class PIP_EXPORT Pool {
+ friend class PISystemMonitor;
+ public:
+ static Pool * instance();
+ PISystemMonitor * getByPID(int pID);
+ private:
+ void add(PISystemMonitor * sm);
+ void remove(PISystemMonitor * sm);
+ PIMap sysmons;
+ PIMutex mutex;
+ };
+
+
+};
+
+inline PICout operator <<(PICout s, const PISystemMonitor::ThreadStats & v) {
+ s.setControl(0, true);
+ s << "ThreadInfo(\"" << v.name << "\", created " << v.created
+ << ", work " << v.work_time.toMilliseconds() << " ms"
+ << ", kernel " << v.kernel_time.toMilliseconds() << " ms"
+ << ", user " << v.user_time.toMilliseconds() << " ms"
+ << ")\n";
+ s.restoreControl();
+ return s;
+}
+
+PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ProcessStats & v);
+PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ProcessStats & v);
+PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ThreadStats & v);
+PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ThreadStats & v);
+
+#endif // PISYSTEMMONITOR_H
diff --git a/utils/system_daemon/main.cpp b/utils/system_daemon/main.cpp
index 85900bd1..664d7590 100755
--- a/utils/system_daemon/main.cpp
+++ b/utils/system_daemon/main.cpp
@@ -332,7 +332,7 @@ void usage() {
int main(int argc, char * argv[]) {
sys_mon.startOnSelf();
- PIINTROSPECTION_START
+ PIINTROSPECTION_START(pisd)
//piDebug = false;
PICLI cli(argc, argv);
cli.addArgument("help");