common: waitForFile using Inotify 30/50530/1
authorJan Olszak <j.olszak@samsung.com>
Thu, 29 Oct 2015 11:48:30 +0000 (12:48 +0100)
committerJan Olszak <j.olszak@samsung.com>
Thu, 29 Oct 2015 11:50:17 +0000 (12:50 +0100)
[Feature]       Changed the implementation of waitForFile to use
                the Inotify class
[Cause]         Inotify verification
[Solution]      N/A
[Verification]  Build, install, run tests

Change-Id: I5fe10f38e9ebdf1f0dde02eb6a63bdbb4c1548fd

common/utils/file-wait.cpp

index b1d9a4f..4386473 100644 (file)
  */
 
 #include "config.hpp"
-#include "utils/exception.hpp"
+
 #include "utils/file-wait.hpp"
+#include "utils/exception.hpp"
+#include "utils/inotify.hpp"
+#include "utils/paths.hpp"
+#include "utils/fs.hpp"
+
+#include "ipc/epoll/event-poll.hpp"
 
 #include <sys/stat.h>
 #include <unistd.h>
 #include <stdexcept>
+#include <chrono>
+#include <thread>
+#include "logger/logger.hpp"
 
 namespace utils {
 
+void waitForFile(const std::string& file, const unsigned int timeoutMs)
+{
+    std::string dir = dirName(file);
+    assertIsDir(dir);
 
-const unsigned int GRANULARITY = 100;
+    ipc::epoll::EventPoll poll;
+    Inotify inotify(poll);
 
-void waitForFile(const std::string& filename, const unsigned int timeoutMs)
-{
-    //TODO this is a temporary solution, use inotify instead of sleep
-    struct stat s;
-    unsigned int loops = 0;
-    while (stat(filename.c_str(), &s) == -1) {
-        if (errno != ENOENT) {
-            throw UtilsException("file access error: " + filename);
-        }
-        ++ loops;
-        if (loops * GRANULARITY > timeoutMs) {
-            throw UtilsException("timeout on waiting for: " + filename);
+    std::string filename = file.substr(dir.size() + 1);
+    bool isWaiting = true;
+    inotify.setHandler(dir, IN_CREATE | IN_ISDIR, [&isWaiting, &filename](const std::string& name, uint32_t) {
+        if (name == filename) {
+            isWaiting = false;
+
+            // There's a race between inotify event and filesystem update.
+            ::sync();
         }
-        usleep(GRANULARITY * 1000);
+    });
+
+    auto deadline = std::chrono::steady_clock::now() +
+                    std::chrono::milliseconds(timeoutMs);
+
+    while (isWaiting && std::chrono::steady_clock::now() < deadline ) {
+        auto duration = deadline - std::chrono::steady_clock::now();
+        poll.dispatchIteration(std::chrono::duration_cast<std::chrono::milliseconds>(duration).count());
     }
-}
 
+    if(isWaiting) {
+        throw UtilsException("No such file: " + file);
+    }
+}
 
 } // namespace utils