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