From 06fa3c93dd15e17b9f6569a4d0378b6d2316e7d8 Mon Sep 17 00:00:00 2001
From: Mirko Waechter <mirko.waechter@kit.edu>
Date: Wed, 13 Jul 2016 09:30:42 +0200
Subject: [PATCH] plugincache: using file hash additionally to check if file
 changed

---
 .../libraries/ArmarXGuiBase/PluginCache.cpp   | 43 ++++++++++++++-----
 .../libraries/ArmarXGuiBase/PluginCache.h     |  3 ++
 2 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/source/ArmarXGui/libraries/ArmarXGuiBase/PluginCache.cpp b/source/ArmarXGui/libraries/ArmarXGuiBase/PluginCache.cpp
index 4de678b3..fadc937d 100644
--- a/source/ArmarXGui/libraries/ArmarXGuiBase/PluginCache.cpp
+++ b/source/ArmarXGui/libraries/ArmarXGuiBase/PluginCache.cpp
@@ -9,6 +9,7 @@
 #include <QDirIterator>
 #include <QFile>
 #include <QResource>
+#include <QCryptographicHash>
 
 namespace armarx
 {
@@ -28,12 +29,13 @@ namespace armarx
         for (QString key : map.keys())
         {
             QStringList w = map[key].toString().split(":");
-            if (w.size() == 2)
+            if (w.size() == 3)
             {
                 pluginData[key].pluginPath = key;
                 pluginData[key].lastModified = QDateTime::fromMSecsSinceEpoch(w[0].toLongLong());
-                ARMARX_INFO_S << "Widget: " << w[1];
-                pluginData[key].widgets[w[1]] = ArmarXWidgetInfoPtr();
+                pluginData[key].hash = w[1].toAscii();
+                ARMARX_INFO_S << "Widget: " << w[2];
+                pluginData[key].widgets[w[2]] = ArmarXWidgetInfoPtr();
             }
         }
     }
@@ -55,6 +57,10 @@ namespace armarx
                 {
                     found = true;
                 }
+                else if (getHash(pluginPath) == elem.hash)
+                {
+                    found = true;
+                }
                 else
                 {
                     ARMARX_VERBOSE_S << "Plugin filestamp is different - loading plugin again.";
@@ -164,8 +170,25 @@ namespace armarx
         s.clear();
     }
 
+    QByteArray PluginCache::getHash(const QString& pluginPath)
+    {
+        QFile file(pluginPath);
+        QByteArray hashData;
+        if (file.open(QIODevice::ReadOnly))
+        {
+            QByteArray fileData = file.readAll();
+            hashData = QCryptographicHash::hash(fileData, QCryptographicHash::Md5);
+
+            ARMARX_INFO_S << hashData.toHex().toDouble();
+        }
+        return hashData.toHex();
+    }
+
     void PluginCache::writeToCache(const QString& pluginPath)
     {
+        auto start = IceUtil::Time::now();
+        QByteArray hashData = getHash(pluginPath);
+        ARMARX_INFO_S << "Hashing took " << (IceUtil::Time::now() - start).toMicroSecondsDouble();
         QSharedPointer<QPluginLoader> loader(new QPluginLoader(pluginPath));
         auto widgets = loadPlugin(loader);
         QSettings s(settingsOrganization, settingsApplicationName);
@@ -174,16 +197,14 @@ namespace armarx
         QDateTime time = QFileInfo(pluginPath).lastModified();
         for (auto & elem : widgets)
         {
-            widgetMap[pluginPath] = QString::number(time.toMSecsSinceEpoch()) + ":" + elem.first;
+            widgetMap[pluginPath] = QString::number(time.toMSecsSinceEpoch()) + ":" + hashData + ":" + elem.first;
         }
 
         s.setValue("widgets", widgetMap);
 
-        pluginData[pluginPath] = {loader, pluginPath, time, widgets};
+        pluginData[pluginPath] = {loader, pluginPath, hashData, time, widgets};
 
         copyResourcesToCache();
-
-
     }
 
     PluginData PluginCache::loadFromCache(const QString& widgetName)
@@ -194,17 +215,19 @@ namespace armarx
         QSharedPointer<QPluginLoader> loader;
         WidgetCreatorMap widgets;
         QDateTime time;
+        QByteArray hash;
         auto map = s.value("widgets").toMap();
         for (auto key : map.keys())
         {
             QStringList w = map[key].toString().split(":");
-            if (w.size() == 2)
+            if (w.size() == 3)
             {
-                if (w[1] == widgetName)
+                if (w[2] == widgetName)
                 {
                     pluginPath = key;
                     if (QFile::exists(pluginPath))
                     {
+                        hash = w[1].toAscii();
                         loader = QSharedPointer<QPluginLoader>(new QPluginLoader(pluginPath));
                         widgets = loadPlugin(loader);
                         time = QDateTime::fromMSecsSinceEpoch(w[0].toLongLong());
@@ -227,7 +250,7 @@ namespace armarx
         {
             manager->registerKnownObjectFactoriesWithIce();
         }
-        return PluginData {loader, pluginPath, time, widgets};
+        return PluginData {loader, pluginPath, hash, time, widgets};
     }
 
     WidgetCreatorMap PluginCache::loadPlugin(QSharedPointer<QPluginLoader> loader)
diff --git a/source/ArmarXGui/libraries/ArmarXGuiBase/PluginCache.h b/source/ArmarXGui/libraries/ArmarXGuiBase/PluginCache.h
index edabf700..e60430d7 100644
--- a/source/ArmarXGui/libraries/ArmarXGuiBase/PluginCache.h
+++ b/source/ArmarXGui/libraries/ArmarXGuiBase/PluginCache.h
@@ -21,6 +21,7 @@ namespace armarx
     {
         QSharedPointer<QPluginLoader> pluginLoader;
         QString pluginPath;
+        QByteArray hash;
         QDateTime lastModified;
         WidgetCreatorMap widgets;
     };
@@ -41,6 +42,8 @@ namespace armarx
         static QString GetIconPath(const QString& widgetName);
         static QString GetCategoryIconPath(const QString& widgetName);
         void clearCacheFile();
+        QByteArray getHash(const QString& pluginPath);
+
     protected:
         void writeToCache(const QString& pluginPath);
         PluginData loadFromCache(const QString& pluginPath);
-- 
GitLab