serialization: reworked init for serialized backend 27/200327/5
authorAdrian Szyndela <adrian.s@samsung.com>
Thu, 21 Feb 2019 15:03:35 +0000 (16:03 +0100)
committerHyotaek Shim <hyotaek.shim@samsung.com>
Thu, 7 Mar 2019 07:36:58 +0000 (07:36 +0000)
Change-Id: Ie72cf3444dfc7bf446bb6035df6a57d04ae0c180

src/internal/storage_backend_serialized.cpp
src/internal/storage_backend_serialized.hpp
src/internal/transaction_guard.hpp [new file with mode: 0644]

index 96b4532..fb5ccda 100644 (file)
@@ -2,6 +2,7 @@
 #include "print_content.hpp"
 #include "serialized_convert.hpp"
 #include "tslog.hpp"
+#include "transaction_guard.hpp"
 
 #include "include/fb_generated.h"
 
@@ -25,11 +26,16 @@ struct type_helper;
 
 class StorageBackendSerialized::StorageBackendSerializedImpl {
        int fd{-1};
-       uint8_t *mem{nullptr};
+       uint8_t *mem{static_cast<decltype(mem)>(MAP_FAILED)};
        size_t length{0};
-       const FB::File *file;
+       const FB::File *file{nullptr};
+
+       void releaseMMap();
+       void releaseFD();
+
 public:
-       void init(const char *filename);
+       bool init(const char *filename, bool verify);
+       bool init(const FB::File *f);
        void release();
 
        void printContent() const;
@@ -38,57 +44,82 @@ public:
        const M *getPolicySet();
 };
 
-void StorageBackendSerialized::StorageBackendSerializedImpl::release() {
-       if (nullptr != mem) {
-               if (munmap(mem, length) != 0)
-                       tslog::log("munmap(): ", strerror(errno), "\n");
-               mem = nullptr;
-               length = 0;
-       }
+void StorageBackendSerialized::StorageBackendSerializedImpl::releaseMMap() {
+       assert(MAP_FAILED != mem);
+       assert(0 != length);
+
+       if (munmap(mem, length) != 0)
+               tslog::log("munmap(): ", strerror(errno), "\n");
+
+       mem = static_cast<decltype(mem)>(MAP_FAILED);
+       length = 0;
+}
 
-       if (-1 != fd) {
-               if (close(fd) != 0)
-                       tslog::log("close(): ", strerror(errno), "\n");
-               fd = -1;
+void StorageBackendSerialized::StorageBackendSerializedImpl::releaseFD() {
+       assert(-1 != fd);
+
+       if (close(fd) != 0)
+               tslog::log("close(): ", strerror(errno), "\n");
+
+       fd = -1;
+}
+
+void StorageBackendSerialized::StorageBackendSerializedImpl::release() {
+       if (-1 != fd) {         // we need to check it, because we may have initialized the storage directly from File *
+               releaseMMap();
+               releaseFD();
        }
 
        file = nullptr;
 }
 
-void StorageBackendSerialized::StorageBackendSerializedImpl::init(const char *filename) {
+bool StorageBackendSerialized::StorageBackendSerializedImpl::init(const char *filename, bool verify) {
+       assert(nullptr == file);
+
        auto err = [filename] (const char *what) {
                tslog::log("Can't ", what, " ", filename, ": ", strerror(errno), "\n");
+               return false;
        };
 
        fd = open(filename, O_RDONLY);
-       if (-1 == fd) {
-               err("open");
-               return;
-       }
+       if (-1 == fd)
+               return err("open");
+
+       auto openGuard = transaction_guard::makeGuard([&] () { releaseFD(); });
 
        struct stat buf;
 
-       if (fstat(fd, &buf) == -1) {
-               err("stat");
-               close(fd);
-               return;
-       }
+       if (fstat(fd, &buf) == -1)
+               return err("stat");
 
        length = buf.st_size;
 
        mem = reinterpret_cast<uint8_t*>(mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0));
-       if (MAP_FAILED == mem) {
-               err("mmap");
-               close(fd);
-               return;
+       if (MAP_FAILED == mem)
+               return err("mmap");
+
+       auto mmapGuard = transaction_guard::makeGuard([&] () { releaseMMap(); });
+
+       if (verify) {
+               auto verifier = flatbuffers::Verifier(mem, length);
+               if (!FB::VerifyFileBuffer(verifier)) {
+                       tslog::log("verification of serialized data: failed\n");
+                       return false;
+               }
        }
-// TODO: decide - do we need verification?
-// for verification:
-//
-//     if (!VerifyFileBuffer(Verifier(mem, length)))
-//             bailout();
-//
+
+       openGuard.dismiss();
+       mmapGuard.dismiss();
+
        file = GetFile(mem);
+       return true;
+}
+
+bool StorageBackendSerialized::StorageBackendSerializedImpl::init(const FB::File *f) {
+       assert(nullptr == file);
+
+       file = f;
+       return true;
 }
 
 void StorageBackendSerialized::StorageBackendSerializedImpl::printContent() const {
@@ -115,8 +146,12 @@ TYPE_HELPER(Send, send)
 TYPE_HELPER(Receive, receive)
 TYPE_HELPER(Access, access)
 
-void StorageBackendSerialized::init(const char *filename) {
-       pimpl->init(filename);
+bool StorageBackendSerialized::init(const char *filename, bool verify) {
+       return pimpl->init(filename, verify);
+}
+
+bool StorageBackendSerialized::init(const FB::File *f) {
+       return pimpl->init(f);
 }
 
 void StorageBackendSerialized::release() {
index 159994a..bf48dd7 100644 (file)
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "policy.hpp"
+#include "fb_generated.h"
 
 #include <memory>
 
@@ -13,7 +14,8 @@ public:
        StorageBackendSerialized();
        ~StorageBackendSerialized();
 
-       void init(const char *filename);
+       bool init(const char *filename, bool verify = false);
+       bool init(const FB::File *file);
        void release();
 
        void printContent() const;
diff --git a/src/internal/transaction_guard.hpp b/src/internal/transaction_guard.hpp
new file mode 100644 (file)
index 0000000..5fc20da
--- /dev/null
@@ -0,0 +1,37 @@
+#pragma once
+
+namespace transaction_guard {
+
+/* Helping class for automatically releasing acquired resources when transaction
+ * during initialization failed at some point.
+ */
+template <typename FunRelease>
+class Guard {
+       FunRelease fun;
+       bool active;
+public:
+       Guard(FunRelease f) : fun(f), active(true) {}
+       Guard() = delete;
+       Guard(const Guard &) = delete;
+       Guard &operator=(const Guard &) = delete;
+
+       ~Guard() {
+               if (active)
+                       fun();
+       }
+
+       void dismiss() {
+               active = false;
+       }
+
+       Guard(Guard &&g) : fun(std::move(g.fun)), active(g.active) {
+               dismiss();
+       }
+};
+
+template <typename FunRelease>
+Guard<FunRelease> makeGuard(FunRelease f) {
+       return Guard<FunRelease>(std::move(f));
+}
+
+} // namespace transaction_guard