add hashes for nodes for persistent identification

This commit is contained in:
Jussi Kuokkanen 2020-05-06 20:40:48 +03:00
parent 40d740fd6b
commit d445e3d7d8
8 changed files with 105 additions and 20 deletions

10
src/include/Crypto.hpp Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include <string>
namespace TuxClocker::Crypto {
std::string sha256(std::string s);
std::string md5(std::string s);
};

View File

@ -77,8 +77,8 @@ using DeviceInterface = std::variant<Assignable, DynamicReadable>;
struct DeviceNode { struct DeviceNode {
std::string name; std::string name;
std::optional<DeviceInterface> interface; std::optional<DeviceInterface> interface;
std::string hash;
}; };
}; };
}; };

32
src/lib/Crypto.cpp Normal file
View File

@ -0,0 +1,32 @@
#include <Crypto.hpp>
#include <openssl/md5.h>
#include <openssl/sha.h>
namespace TuxClocker::Crypto {
std::string sha256(std::string s) {
auto d = SHA256(reinterpret_cast<const unsigned char*>(s.c_str()), s.size(), 0);
char out[(SHA256_DIGEST_LENGTH * 2) + 1];
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
sprintf(out + (i * 2), "%02x", d[i]);
out[SHA256_DIGEST_LENGTH * 2] = '\0';
return std::string(out);
}
std::string md5(std::string s) {
unsigned char data[MD5_DIGEST_LENGTH];
MD5(reinterpret_cast<const unsigned char*>(s.c_str()), s.size(), data);
char out[(MD5_DIGEST_LENGTH * 2) + 1];
for (int i = 0; i < MD5_DIGEST_LENGTH; i++)
sprintf(out + (i * 2), "%02x", data[i]);
out[MD5_DIGEST_LENGTH * 2] = '\0';
return std::string(out);
}
};

View File

@ -1,3 +1,4 @@
#include <Crypto.hpp>
#include <Device.hpp> #include <Device.hpp>
#include <Plugin.hpp> #include <Plugin.hpp>
@ -10,6 +11,7 @@
#include <nvml.h> #include <nvml.h>
using namespace TuxClocker; using namespace TuxClocker;
using namespace TuxClocker::Crypto;
using namespace TuxClocker::Device; using namespace TuxClocker::Device;
using namespace TuxClocker::Plugin; using namespace TuxClocker::Plugin;
using namespace mpark::patterns; using namespace mpark::patterns;
@ -34,6 +36,18 @@ struct UnspecializedReadable {
std::function<std::variant<ReadError, ReadableValue>(T)> func; std::function<std::variant<ReadError, ReadableValue>(T)> func;
std::optional<std::string> unit; std::optional<std::string> unit;
std::string nodeName; std::string nodeName;
// One time function for getting a hash
std::function<std::string(T)> hash;
static std::vector<DeviceNode> toDeviceNodes(
std::vector<UnspecializedReadable<T>> rawNodes, T data, std::string uuid) {
std::vector<DeviceNode> retval;
for (const auto &rawNode : rawNodes) {
}
return retval;
}
}; };
template <typename T> template <typename T>
@ -43,10 +57,11 @@ struct UnspecializedAssignable {
std::function<std::optional<AssignmentError>(T, AssignableInfo, AssignmentArgument)> func; std::function<std::optional<AssignmentError>(T, AssignableInfo, AssignmentArgument)> func;
std::optional<std::string> unit; std::optional<std::string> unit;
std::string nodeName; std::string nodeName;
std::function<std::string(std::string, T)> hash;
static std::vector<DeviceNode> toDeviceNodes( static std::vector<DeviceNode> toDeviceNodes(
std::vector<UnspecializedAssignable<T>> rawNodes, std::vector<UnspecializedAssignable<T>> rawNodes,
T devData) { T devData, std::string uuid) {
std::vector<DeviceNode> retval; std::vector<DeviceNode> retval;
for (auto &rawNode : rawNodes) { for (auto &rawNode : rawNodes) {
if_let(pattern(some(arg)) = rawNode.assignableInfo(devData)) = [&](auto info) { if_let(pattern(some(arg)) = rawNode.assignableInfo(devData)) = [&](auto info) {
@ -55,7 +70,8 @@ struct UnspecializedAssignable {
}, info); }, info);
auto node = DeviceNode { auto node = DeviceNode {
.name = rawNode.nodeName, .name = rawNode.nodeName,
.interface = assignable .interface = assignable,
.hash = rawNode.hash(uuid, devData)
}; };
retval.push_back(node); retval.push_back(node);
}; };
@ -259,7 +275,10 @@ NvidiaPlugin::NvidiaPlugin() : m_dpy() {
return retval; return retval;
}, },
"W", "W",
"Power Limit" "Power Limit",
[](std::string uuid, nvmlDevice_t) {
return md5(uuid + "Power Limit");
}
} }
}; };
@ -297,7 +316,10 @@ NvidiaPlugin::NvidiaPlugin() : m_dpy() {
return retval; return retval;
}, },
"MHz", "MHz",
"Memory Clock Offset" "Memory Clock Offset",
[](std::string uuid, NVClockInfo) {
return md5(uuid + "Memory Clock Offset");
}
} }
}; };
@ -335,7 +357,10 @@ NvidiaPlugin::NvidiaPlugin() : m_dpy() {
return ret; return ret;
}, },
std::nullopt, std::nullopt,
"Fan Mode" "Fan Mode",
[](std::string uuid, uint) {
return md5(uuid + "Fan Mode");
}
} }
}; };
@ -448,7 +473,7 @@ NvidiaPlugin::NvidiaPlugin() : m_dpy() {
gpuRoot.appendChild(specNode); gpuRoot.appendChild(specNode);
for (auto &node : UnspecializedAssignable<nvmlDevice_t>::toDeviceNodes( for (auto &node : UnspecializedAssignable<nvmlDevice_t>::toDeviceNodes(
rawNVMLAssignables, dev)) rawNVMLAssignables, dev, nvOpt.uuid))
gpuRoot.appendChild(node); gpuRoot.appendChild(node);
}; };
@ -472,11 +497,11 @@ NvidiaPlugin::NvidiaPlugin() : m_dpy() {
auto clockInfo = NVClockInfo{nvctrlPerfModes(index), index}; auto clockInfo = NVClockInfo{nvctrlPerfModes(index), index};
for (auto &node : UnspecializedAssignable<NVClockInfo>::toDeviceNodes( for (auto &node : UnspecializedAssignable<NVClockInfo>::toDeviceNodes(
rawNVCTRLClockAssignables, clockInfo)) rawNVCTRLClockAssignables, clockInfo, nvOpt.uuid))
gpuRoot.appendChild(node); gpuRoot.appendChild(node);
for (auto &node : UnspecializedAssignable<uint>::toDeviceNodes( for (auto &node : UnspecializedAssignable<uint>::toDeviceNodes(
rawNVCTRLAssignables, index)) rawNVCTRLAssignables, index, nvOpt.uuid))
gpuRoot.appendChild(node); gpuRoot.appendChild(node);
}; };

View File

@ -34,5 +34,6 @@ if all_nvidia_linux_libs
include_directories : [incdir, patterns_inc, fplus_inc], include_directories : [incdir, patterns_inc, fplus_inc],
dependencies : [nvidia_linux_libs, boost_dep], dependencies : [nvidia_linux_libs, boost_dep],
install_dir : get_option('libdir') / 'tuxclocker' / 'plugins', install_dir : get_option('libdir') / 'tuxclocker' / 'plugins',
install : true) install : true,
link_with : libtuxclocker)
endif endif

View File

@ -16,14 +16,14 @@ public:
/* Returns a raw pointer since smart pointers caused some scope issues. /* Returns a raw pointer since smart pointers caused some scope issues.
* TODO: try to use smart pointers instead? */ * TODO: try to use smart pointers instead? */
static std::optional<QDBusAbstractAdaptor*> adaptor(QObject *obj, static std::optional<QDBusAbstractAdaptor*> adaptor(QObject *obj,
DeviceInterface iface) { DeviceInterface iface, DeviceNode devNode) {
std::optional<QDBusAbstractAdaptor*> retval = std::nullopt; std::optional<QDBusAbstractAdaptor*> retval = std::nullopt;
match(iface) match(iface)
(pattern(as<DynamicReadable>(arg)) = [&](auto dr) { (pattern(as<DynamicReadable>(arg)) = [&](auto dr) {
retval = new DynamicReadableAdaptor(obj, dr); retval = new DynamicReadableAdaptor(obj, dr);
}, },
pattern(as<Assignable>(arg)) = [&](auto a) { pattern(as<Assignable>(arg)) = [&](auto a) {
retval = new AssignableAdaptor(obj, a); retval = new AssignableAdaptor(obj, a, devNode);
}, },
pattern(_) = []{}); pattern(_) = []{});
return retval; return retval;

View File

@ -63,8 +63,8 @@ Q_DECLARE_METATYPE(TCDBus::Result<int>)
class AssignableAdaptor : public QDBusAbstractAdaptor { class AssignableAdaptor : public QDBusAbstractAdaptor {
public: public:
explicit AssignableAdaptor(QObject *obj, Assignable a) : QDBusAbstractAdaptor(obj), explicit AssignableAdaptor(QObject *obj, Assignable a, DeviceNode devNode) :
m_assignable(a) { QDBusAbstractAdaptor(obj), m_assignable(a), m_devNode(devNode) {
qDBusRegisterMetaType<TCDBus::Range>(); qDBusRegisterMetaType<TCDBus::Range>();
qDBusRegisterMetaType<TCDBus::Enumeration>(); qDBusRegisterMetaType<TCDBus::Enumeration>();
qDBusRegisterMetaType<QVector<TCDBus::Enumeration>>(); qDBusRegisterMetaType<QVector<TCDBus::Enumeration>>();
@ -99,6 +99,7 @@ public:
m_dbusAssignableInfo = QDBusVariant(a_info); m_dbusAssignableInfo = QDBusVariant(a_info);
} }
QDBusVariant assignableInfo_() {return m_dbusAssignableInfo;} QDBusVariant assignableInfo_() {return m_dbusAssignableInfo;}
QString hash_() {return QString::fromStdString(m_devNode.hash);}
public Q_SLOTS: public Q_SLOTS:
TCDBus::Result<int> assign(QDBusVariant arg_) { TCDBus::Result<int> assign(QDBusVariant arg_) {
auto v = arg_.variant(); auto v = arg_.variant();
@ -132,8 +133,10 @@ private:
Q_OBJECT Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.tuxclocker.Assignable") Q_CLASSINFO("D-Bus Interface", "org.tuxclocker.Assignable")
Q_PROPERTY(QDBusVariant assignableInfo READ assignableInfo_) Q_PROPERTY(QDBusVariant assignableInfo READ assignableInfo_)
Q_PROPERTY(QString hash READ hash_)
Assignable m_assignable; Assignable m_assignable;
DeviceNode m_devNode;
QDBusVariant m_dbusAssignableInfo; QDBusVariant m_dbusAssignableInfo;
}; };
@ -155,7 +158,6 @@ public:
childIndices.append(i); childIndices.append(i);
TCDBus::FlatTreeNode<TCDBus::DeviceNode> fn{f_node.value, childIndices}; TCDBus::FlatTreeNode<TCDBus::DeviceNode> fn{f_node.value, childIndices};
qDebug("Hello");
m_flatTree.append(fn); m_flatTree.append(fn);
} }
} }

View File

@ -28,21 +28,36 @@ int main(int argc, char **argv) {
TreeNode<TCDBus::DeviceNode> dbusRootNode; TreeNode<TCDBus::DeviceNode> dbusRootNode;
std::function<void(TreeNode<DeviceNode>, QString, TreeNode<TCDBus::DeviceNode>*)> traverse; std::function<void(TreeNode<DeviceNode>, QString, TreeNode<TCDBus::DeviceNode>*)> traverse;
traverse = [&traverse, &connection, &adaptors, &root, &dbusRootNode]( traverse = [&traverse, &connection, &adaptors, &root](
TreeNode<DeviceNode> node, TreeNode<DeviceNode> node,
QString parentPath, TreeNode<TCDBus::DeviceNode> *dbusNode) { QString parentPath, TreeNode<TCDBus::DeviceNode> *dbusNode) {
auto obj = new QObject(&root); // Is destroyed when root goes out of scope auto obj = new QObject(&root); // Is destroyed when root goes out of scope
// Remove whitespaces to make valid object paths // Remove whitespaces to make valid object paths
auto objName = QString::fromStdString(node.value().name).replace(" ", ""); auto objName = QString::fromStdString(node.value().name).replace(" ", "");
auto thisPath = parentPath + objName; auto thisPath = parentPath + objName;
QString ifaceName;
if_let(pattern(some(arg)) = node.value().interface) = [&](auto iface) { if_let(pattern(some(arg)) = node.value().interface) = [&](auto iface) {
if_let(pattern(some(arg)) = AdaptorFactory::adaptor(obj, iface)) = [&](auto adaptor) { if_let(pattern(some(arg)) =
AdaptorFactory::adaptor(obj, iface, node.value())) = [&](auto adaptor) {
adaptors.append(adaptor); adaptors.append(adaptor);
connection.registerObject(thisPath, obj); connection.registerObject(thisPath, obj);
// TODO: don't hardcode interface name
// Maybe create an intermediate class that contains the interface name to avoid this
// For some reason this throws a bad_cast when using 'as' with pointer type
match(*adaptor)
(pattern(as<AssignableAdaptor>(_)) = [&] {
ifaceName = "org.tuxclocker.Assignable";
},
pattern(as<DynamicReadableAdaptor>(_)) = [&] {
ifaceName = "org.tuxclocker.DynamicReadable";
},
pattern(_) = [] {});
}; };
}; };
auto thisDBusNode = new TreeNode<TCDBus::DeviceNode>{{thisPath, "org.tuxclocker"}};
dbusNode->appendChild(*thisDBusNode); auto thisDBusNode = TreeNode<TCDBus::DeviceNode>{{thisPath, ifaceName}};
dbusNode->appendChild(thisDBusNode);
qDebug() << thisPath; qDebug() << thisPath;
for (const auto &child : node.children()) for (const auto &child : node.children())
traverse(child, thisPath + "/", &dbusNode->childrenPtr()->back()); traverse(child, thisPath + "/", &dbusNode->childrenPtr()->back());