felixguendling/cista

mmap with mmap::protection::MODIFY throws exception

BinaryCat17 opened this issue · 4 comments

I try to run this simple code and I get exception
'std::runtime_error': what(): open file mode not supported
from file "cista/targets/file.h" line 31
verify(read || write, "open file mode not supported");

I use Windows with msys2(mingw64).

    namespace data = cista::offset;
    constexpr auto const MODE = cista::mode::WITH_VERSION | cista::mode::WITH_INTEGRITY;

    struct pos {
        int x, y;
    };

    using vec = data::vector<pos>;

    {
        vec positions{{1, 2}, {3, 4}, {5, 6}, {7, 8}};
        cista::buf mmap{cista::mmap{"data"}};
        cista::serialize<MODE>(mmap, positions);
    }

    auto b = cista::mmap("data", cista::mmap::protection::MODIFY);
    auto positions = cista::deserialize<vec, MODE>(b);
    positions->push_back({5, 5});

    for(auto pos : *positions) {
        std::cout << pos.x << " " << pos.y << std::endl;
    }

And question. I need load data from disk and modify it, but I don't need to sync data always with disk.
Should I serialize data from disk, copy it to memory and, after changing it, serialize it back?
Or should I just use mmap::modify? I do not fully understand how much mmap costs and what is more efficient"

Note that using MODIFY mode on an mmap is a really bad idea if you want to read and modify serialized data. Using push_back in your example will allocate memory from the heap and replace the pointer in the pointer of the vector serialized in the memory mapped file with the heap pointer. However, the data the pointer points to (the contents of the vector) won't be written to the file. This way, you get a dangling pointer in your serialized data. This can't be fixed.

The only modifications that are possible are changing scalar values in-place. Allocations will allocate from the heap and will lead to dangling pointers in the data serialized in the file.

Should I serialize data from disk, copy it to memory and, after changing it, serialize it back?

Yes: read data from disk, modify it in-memory and write it back to another file. Then replace the original file (swap new vs old).

I added support for MODIFY on windows. However, this should not be used for changing serialized data beyond simple scalar modifications.

Thanks a lot, I think it's better to cover this issue in the documentation.