Poseidon : Concurrency issues in chunked_vec.hpp::store() . [ and probably chunked_vec.hpp::erase() too ]

1) Issue: "Chunked_vec.hpp::store()" or "Chunked_vec.hpp::store_at()" and similar methods are not thread safe.

2) Line num : https://dbgit.prakinf.tu-ilmenau.de/code/poseidon_core/-/blob/null_values/src/storage/chunked_vec.hpp#L369

3) Scenario : Try to create node in two different threads/transactions.

4) How to reproduce the issue ?

Steps : Added the following Test case at beginning of "../../test/transaction_test.cpp" ( commented-out all remaining test cases)


TEST_CASE("Test two concurrent Txns by trying to create node" "[transaction]") {

#ifdef USE_PMDK

auto pop = prepare_pool();

auto gdb = create_graph_db(pop);

#else

auto gdb = create_graph_db();

#endif

node::id_t nid1 = 0,nid2 = 0;

// Thread 1: Add node

auto t1 = std::thread( [&] () {

    auto tx = gdb->begin_transaction();

    nid1 = gdb->add_node("New Actor",
                        {{"name", boost::any(std::string("Mark Wahlberg"))},
                         {"age", boost::any(48)}});

    gdb->commit_transaction();

});

// Thread 2: concurrently add node

            auto t2 = std::thread([&] () {

	    auto tx = gdb->begin_transaction();

	    nid2 = gdb->add_node("Actor",
	                        {{"name", boost::any(std::string("Peter"))},
	                         {"age", boost::any(22)}});

	    gdb->commit_transaction();

});

t1.join();

t2.join();

gdb->dump();

#ifdef USE_PMDK

drop_graph_db(pop, gdb);

#endif

} // Test case ends


5) Output : Below is a debug output


arth0746@dbpmem:~/06june_poseidon_test_concurr_issue/poseidon_core/build/test$ ./transaction_test

Txid: 1591470227122702065, Pos:0, Num chunks: 1,cap :18724 //<== Transaction-1 is assigned offset 0 in Pmem

Txid: 1591470227122702446, Pos:0, Num chunks: 2,cap :18724 //<== Transaction-2 is also assigned offset 0 in Pmem

transaction_test: /usr/local/include/libpmemobj++/container/vector.hpp:2150: void

pmem::obj::vector::construct_at_end(pmem::obj::vector::size_type, Args&& ...) [with Args = {const

pmem::obj::persistent_ptr<chunk<property_set, 16384> >&}; T = pmem::obj::persistent_ptr<chunk<property_set, 16384> >;

pmem::obj::vector::size_type = long unsigned int]: Assertion `_capacity >= count + _size' failed.

Aborted (core dumped)


6) Issue Description : From the above output we can see, At line https://dbgit.prakinf.tu-ilmenau.de/code/poseidon_core/-/blob/null_values/src/storage/chunked_vec.hpp#L385

1.Both Txn-1 and Txn-2, calls "offset_t pos = ch->first_available();" and gets same "offset_t pos: 0" for both nodes "New Actor" and "Actor".

2.Also both transactions creates a new chunk and thus 2 chunks are created (instead of one). A simple call to num_chunks() would give this information.

Finally, the program crashes with a "segmentation fault" arising from line : https://dbgit.prakinf.tu-ilmenau.de/code/poseidon_core/-/blob/null_values/src/storage/chunked_vec.hpp#L120

Is this Test case Wrong ? Please ignore the issue if wrong. Can't two or n-concurrent threads/transactions create nodes ?

7) Why running transaction_tests now ?

I found this issue while working on the currently assigned task "Design Strict 2-phase locking" and "A driver to evaluate con-Current Transactions" and this issue is blocking it.

Edited by Arun Kumar Tharanatha