From 9d8d7fa5f8bc94cdea2c898eb9c8e8ceb2cbd137 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Sat, 22 Mar 2025 21:09:37 +0300 Subject: [PATCH 01/51] Add minimum classes for sc-transactions implementation (element version, transaction, epoch management) --- .../sc-store/sc-transaction/epoch_manager.c | 1 + .../sc-store/sc-transaction/epoch_manager.h | 13 +++++++++++++ .../sc-transaction/sc_element_version.h | 19 +++++++++++++++++++ .../sc-store/sc-transaction/sc_transaction.h | 12 ++++++++++++ .../sc-transaction/sc_transaction_manager.c | 2 ++ .../sc-transaction/sc_transaction_manager.h | 19 +++++++++++++++++++ .../units/common/test_sc_transaction_core.cpp | 0 7 files changed, 66 insertions(+) create mode 100644 sc-memory/sc-core/src/sc-store/sc-transaction/epoch_manager.c create mode 100644 sc-memory/sc-core/src/sc-store/sc-transaction/epoch_manager.h create mode 100644 sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h create mode 100644 sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h create mode 100644 sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c create mode 100644 sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h create mode 100644 sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/epoch_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/epoch_manager.c new file mode 100644 index 0000000000..4e1b12d872 --- /dev/null +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/epoch_manager.c @@ -0,0 +1 @@ +#include "epoch_manager.h" diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/epoch_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/epoch_manager.h new file mode 100644 index 0000000000..3232dd5125 --- /dev/null +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/epoch_manager.h @@ -0,0 +1,13 @@ +#ifndef SC_EPOCH_MANAGER_H +#define SC_EPOCH_MANAGER_H + +#include + +typedef struct epoch_manager { + uint64_t current_epoch; +} epoch_manager; + +void initialize_epoch_manager(epoch_manager* manager); +uint64_t start_epoch(epoch_manager* manager); + +#endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h new file mode 100644 index 0000000000..f4b7b80903 --- /dev/null +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h @@ -0,0 +1,19 @@ +#ifndef SC_ELEMENT_VERSION_H +#define SC_ELEMENT_VERSION_H + +#include + +typedef struct element_version { + void* data; + uint64_t version_id; + element_version * prev_version; + uint64_t epoch; + uint64_t transaction_id; + int is_committed; +} element_version; + +element_version* create_new_version(void* data, uint64_t version_id, uint64_t transaction_id, uint64_t epoch); +void commit_version(element_version* version); +void rollback_version(element_version* version); + +#endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h new file mode 100644 index 0000000000..83f585dc20 --- /dev/null +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -0,0 +1,12 @@ +#ifndef SC_TRANSACTION_H +#define SC_TRANSACTION_H + +#include + +typedef struct transaction { + uint64_t transaction_id; + uint64_t timestamp; + bool is_committed; +} transaction; + +#endif \ No newline at end of file diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c new file mode 100644 index 0000000000..4e81a08e4b --- /dev/null +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c @@ -0,0 +1,2 @@ +#include "sc_transaction_manager.h" + diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h new file mode 100644 index 0000000000..7fe71737cf --- /dev/null +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h @@ -0,0 +1,19 @@ +#ifndef SC_TRANSACTION_MANAGER_H +#define SC_TRANSACTION_MANAGER_H + +#include +#include + +#include "epoch_manager.h" + +typedef struct transaction_manager { + uint64_t current_transaction_id; + epoch_manager* epoch_mgr; +} transaction_manager; + +void initialize_transaction_manager(transaction_manager* manager); +uint64_t start_transaction(transaction_manager* manager); +void commit_transaction(transaction_manager* manager, uint64_t transaction_id); +void rollback_transaction(transaction_manager* manager, uint64_t transaction_id); + +#endif diff --git a/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp b/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp new file mode 100644 index 0000000000..e69de29bb2 From bbd5206fe61e6b711cbce1366339272f97bcc163 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Sun, 23 Mar 2025 19:26:15 +0300 Subject: [PATCH 02/51] Basic structures, transaction_manager init, remove epoch, supplement sc_element --- .../sc-store/sc-transaction/epoch_manager.c | 1 - .../sc-store/sc-transaction/epoch_manager.h | 13 --- .../sc-transaction/sc_element_version.c | 1 + .../sc-transaction/sc_element_version.h | 16 ++-- .../sc-store/sc-transaction/sc_transaction.h | 8 +- .../sc-transaction/sc_transaction_manager.c | 16 ++++ .../sc-transaction/sc_transaction_manager.h | 21 ++-- sc-memory/sc-core/src/sc-store/sc_element.h | 3 + .../units/common/test_sc_transaction_core.cpp | 95 +++++++++++++++++++ 9 files changed, 137 insertions(+), 37 deletions(-) delete mode 100644 sc-memory/sc-core/src/sc-store/sc-transaction/epoch_manager.c delete mode 100644 sc-memory/sc-core/src/sc-store/sc-transaction/epoch_manager.h create mode 100644 sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/epoch_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/epoch_manager.c deleted file mode 100644 index 4e1b12d872..0000000000 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/epoch_manager.c +++ /dev/null @@ -1 +0,0 @@ -#include "epoch_manager.h" diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/epoch_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/epoch_manager.h deleted file mode 100644 index 3232dd5125..0000000000 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/epoch_manager.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SC_EPOCH_MANAGER_H -#define SC_EPOCH_MANAGER_H - -#include - -typedef struct epoch_manager { - uint64_t current_epoch; -} epoch_manager; - -void initialize_epoch_manager(epoch_manager* manager); -uint64_t start_epoch(epoch_manager* manager); - -#endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c new file mode 100644 index 0000000000..36d0ce55f5 --- /dev/null +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c @@ -0,0 +1 @@ +#include "sc_element_version.h" diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h index f4b7b80903..f35b2cc82d 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h @@ -1,19 +1,15 @@ #ifndef SC_ELEMENT_VERSION_H #define SC_ELEMENT_VERSION_H +#include #include -typedef struct element_version { +typedef struct sc_element_version { void* data; uint64_t version_id; - element_version * prev_version; - uint64_t epoch; - uint64_t transaction_id; - int is_committed; -} element_version; - -element_version* create_new_version(void* data, uint64_t version_id, uint64_t transaction_id, uint64_t epoch); -void commit_version(element_version* version); -void rollback_version(element_version* version); + struct sc_element_version* prev_version; + struct sc_element_version* next_version; + bool is_committed; +} sc_element_version; #endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index 83f585dc20..68e9ff6687 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -2,11 +2,15 @@ #define SC_TRANSACTION_H #include +#include +#include -typedef struct transaction { +typedef struct sc_transaction { uint64_t transaction_id; uint64_t timestamp; bool is_committed; -} transaction; + sc_list elements; + sc_uint32 element_count; +} sc_transaction; #endif \ No newline at end of file diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c index 4e81a08e4b..49405eb4de 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c @@ -1,2 +1,18 @@ #include "sc_transaction_manager.h" +#include +#include +sc_transaction_manager* sc_transaction_manager_initialize(void) { + sc_transaction_manager* manager = malloc(sizeof(sc_transaction_manager)); + if (!manager) + { + perror("Failed to allocate memory for transaction manager"); + return NULL; + } + + manager->current_sc_transaction = NULL; + sc_monitor_init(&manager->sc_monitor); + sc_queue_init(&manager->sc_transaction_queue); + + return manager; +} diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h index 7fe71737cf..56fe7147c5 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h @@ -1,19 +1,18 @@ #ifndef SC_TRANSACTION_MANAGER_H #define SC_TRANSACTION_MANAGER_H -#include -#include +#include "sc_transaction.h" +#include "sc-store/sc-base/sc_monitor_private.h" -#include "epoch_manager.h" +#include -typedef struct transaction_manager { - uint64_t current_transaction_id; - epoch_manager* epoch_mgr; -} transaction_manager; +typedef struct sc_transaction_manager +{ + sc_transaction * current_sc_transaction; + sc_monitor sc_monitor; + sc_queue sc_transaction_queue; +} sc_transaction_manager; -void initialize_transaction_manager(transaction_manager* manager); -uint64_t start_transaction(transaction_manager* manager); -void commit_transaction(transaction_manager* manager, uint64_t transaction_id); -void rollback_transaction(transaction_manager* manager, uint64_t transaction_id); +sc_transaction_manager* sc_transaction_manager_initialize(void); #endif diff --git a/sc-memory/sc-core/src/sc-store/sc_element.h b/sc-memory/sc-core/src/sc-store/sc_element.h index de0c9f6406..7cce950142 100644 --- a/sc-memory/sc-core/src/sc-store/sc_element.h +++ b/sc-memory/sc-core/src/sc-store/sc_element.h @@ -8,6 +8,7 @@ #define _sc_element_h_ #include "sc-core/sc_types.h" +#include "sc-transaction/sc_element_version.h" struct _sc_arc_info { @@ -65,6 +66,8 @@ struct _sc_element sc_uint32 incoming_arcs_count; sc_uint32 outgoing_arcs_count; + + sc_element_version* current_version; }; #endif diff --git a/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp b/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp index e69de29bb2..0b27d2cfac 100644 --- a/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp +++ b/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp @@ -0,0 +1,95 @@ +#include +#include +#include + +extern "C" { +#include +} + +struct TransactionThreadData { + transaction_manager* manager; + int thread_id; +}; + +void* transaction_thread(void* arg) { + auto* data = static_cast(arg); + transaction_manager* manager = data->manager; + + sc_element_version version = {}; + log_version_change(manager, &version); + + if (data->thread_id % 2 == 0) { + commit_transaction(manager); + } else { + rollback_transaction(manager); + } + + return nullptr; +} + +TEST_F(ScMemoryTest, MultiThreadedTransactionTest) { + transaction_manager manager; + initialize_transaction_manager(&manager); + + const int NUM_THREADS = 10; + pthread_t threads[NUM_THREADS]; + TransactionThreadData thread_data[NUM_THREADS]; + + for (int i = 0; i < NUM_THREADS; ++i) { + thread_data[i].manager = &manager; + thread_data[i].thread_id = i; + pthread_create(&threads[i], nullptr, transaction_thread, &thread_data[i]); + } + + for (int i = 0; i < NUM_THREADS; ++i) { + pthread_join(threads[i], nullptr); + } + + EXPECT_EQ(manager.current_transaction, nullptr); + + EXPECT_NE(manager.log_head, nullptr); +} + +TEST_F(ScMemoryTest, MultiThreadedTransactionLogTest) { + transaction_manager manager; + initialize_transaction_manager(&manager); + + const int NUM_THREADS = 5; + pthread_t threads[NUM_THREADS]; + TransactionThreadData thread_data[NUM_THREADS]; + + for (int i = 0; i < NUM_THREADS; ++i) { + thread_data[i].manager = &manager; + thread_data[i].thread_id = i; + pthread_create(&threads[i], nullptr, transaction_thread, &thread_data[i]); + } + + for (int i = 0; i < NUM_THREADS; ++i) { + pthread_join(threads[i], nullptr); + } + + EXPECT_NE(manager.log_head, nullptr); +} + +TEST_F(ScMemoryTest, TransactionManagerTests) { + transaction_manager manager; + initialize_transaction_manager(&manager); + + const int NUM_THREADS = 20; + pthread_t threads[NUM_THREADS]; + TransactionThreadData thread_data[NUM_THREADS]; + + for (int i = 0; i < NUM_THREADS; ++i) { + thread_data[i].manager = &manager; + thread_data[i].thread_id = i; + pthread_create(&threads[i], nullptr, transaction_thread, &thread_data[i]); + } + + for (int i = 0; i < NUM_THREADS; ++i) { + pthread_join(threads[i], nullptr); + } + + EXPECT_EQ(manager.current_transaction, nullptr); + + EXPECT_NE(manager.log_head, nullptr); +} From 1d0fc234f2d22c183e586ccb728ae8fe0666242b Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Mon, 24 Mar 2025 23:38:54 +0300 Subject: [PATCH 03/51] Add transaction-related methods (.h), use sc_* types --- .../sc-transaction/sc_element_version.h | 7 ++--- .../sc-store/sc-transaction/sc_transaction.c | 0 .../sc-store/sc-transaction/sc_transaction.h | 29 +++++++++++++++---- .../sc-transaction/sc_transaction_manager.c | 17 ----------- .../sc-transaction/sc_transaction_manager.h | 26 ++++++++++++----- 5 files changed, 45 insertions(+), 34 deletions(-) create mode 100644 sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h index f35b2cc82d..216c7bdcee 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h @@ -1,15 +1,14 @@ #ifndef SC_ELEMENT_VERSION_H #define SC_ELEMENT_VERSION_H -#include -#include +#include "sc-core/sc_types.h" typedef struct sc_element_version { void* data; - uint64_t version_id; + sc_uint64 version_id; struct sc_element_version* prev_version; struct sc_element_version* next_version; - bool is_committed; + sc_bool is_committed; } sc_element_version; #endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index 68e9ff6687..94a93b6f6c 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -1,16 +1,33 @@ #ifndef SC_TRANSACTION_H #define SC_TRANSACTION_H -#include -#include #include typedef struct sc_transaction { - uint64_t transaction_id; - uint64_t timestamp; - bool is_committed; + sc_uint64 transaction_id; + sc_uint64 timestamp; + sc_bool is_committed; sc_list elements; sc_uint32 element_count; } sc_transaction; -#endif \ No newline at end of file +sc_transaction* sc_transaction_create(); +// create a new transaction +void sc_transaction_destroy(sc_transaction* txn); +// destroy the given transaction + +void sc_transaction_add_element(sc_transaction* txn, sc_element* element); +// add element to track in transaction (based on "touched" elements, manager will try to commit or rollback transaction) +void sc_transaction_commit(sc_transaction* txn); +// apply all operations of the transaction on sc-memory +void sc_transaction_rollback(sc_transaction* txn); +// rollback the transaction operations + +sc_bool sc_transaction_validate(sc_transaction* txn); +// check if the transaction can be applied based on element versions and free segments +void sc_transaction_merge(sc_transaction* txn); +// check versions of all elements in the transaction and try to merge them +void sc_transaction_apply(sc_transaction* txn); +// apply all operations (merged versions, allocated spaces) to sc-memory + +#endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c index 49405eb4de..d0e2290b04 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c @@ -1,18 +1 @@ #include "sc_transaction_manager.h" -#include -#include - -sc_transaction_manager* sc_transaction_manager_initialize(void) { - sc_transaction_manager* manager = malloc(sizeof(sc_transaction_manager)); - if (!manager) - { - perror("Failed to allocate memory for transaction manager"); - return NULL; - } - - manager->current_sc_transaction = NULL; - sc_monitor_init(&manager->sc_monitor); - sc_queue_init(&manager->sc_transaction_queue); - - return manager; -} diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h index 56fe7147c5..4fba6dfcfc 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h @@ -4,15 +4,27 @@ #include "sc_transaction.h" #include "sc-store/sc-base/sc_monitor_private.h" -#include - -typedef struct sc_transaction_manager -{ - sc_transaction * current_sc_transaction; - sc_monitor sc_monitor; +typedef struct sc_transaction_manager { + sc_transaction *current_sc_transaction; sc_queue sc_transaction_queue; + sc_monitor sc_monitor; } sc_transaction_manager; -sc_transaction_manager* sc_transaction_manager_initialize(void); +sc_transaction_manager* sc_transaction_manager_initialize(); +// create and initialize the transaction manager +sc_bool sc_transaction_manager_is_initialized(); +// check if the transaction manager is initialized +void sc_transaction_shutdown(); +// shutdown the transaction manager + +sc_transaction* sc_transaction_manager_transaction_new(); +// create a new empty sc-transaction +void sc_transaction_manager_transaction_add(sc_transaction* txn); +// add transaction to the queue and start operations when the thread is ready +void sc_transaction_manager_transaction_execute(); +// try to execute the transaction and wait till it's finished + +void sc_transaction_manager_destroy(); +// destroy the transaction manager #endif From 29cd49841a001e2f2d85d2ea2d0210c7749354cf Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Mon, 24 Mar 2025 23:41:17 +0300 Subject: [PATCH 04/51] Add sc_transaction_clear --- sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c | 1 + sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index e69de29bb2..1e87324622 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -0,0 +1 @@ +#include "sc_transaction.h" \ No newline at end of file diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index 94a93b6f6c..d59bd4c595 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -29,5 +29,7 @@ void sc_transaction_merge(sc_transaction* txn); // check versions of all elements in the transaction and try to merge them void sc_transaction_apply(sc_transaction* txn); // apply all operations (merged versions, allocated spaces) to sc-memory +void sc_transaction_clear(sc_transaction* txn); +// deletes all transaction items and clears them without performing a commit #endif From 84f8bac8c872bf1c67c19df3b29a7ce0790af3f4 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Tue, 25 Mar 2025 01:03:53 +0300 Subject: [PATCH 05/51] Implemented initialization method for the manager and transaction creation method --- .../sc-store/sc-transaction/sc_transaction.c | 25 +++++++- .../sc-store/sc-transaction/sc_transaction.h | 5 +- .../sc-transaction/sc_transaction_manager.c | 57 +++++++++++++++++++ .../sc-transaction/sc_transaction_manager.h | 7 ++- 4 files changed, 87 insertions(+), 7 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index 1e87324622..5cc04c60b8 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -1 +1,24 @@ -#include "sc_transaction.h" \ No newline at end of file +#include "sc_transaction.h" + +#include + +sc_transaction* sc_transaction_create(const sc_uint64* txn_id) { + sc_transaction *txn = sc_mem_new(sc_transaction, 1); + if (txn == NULL) { + return NULL; + } + + txn->transaction_id = *txn_id; + txn->is_committed = SC_FALSE; + txn->element_count = 0; + sc_list_init(&txn->elements); + return txn; +} + +void sc_transaction_destroy(sc_transaction* txn) { + if (txn != NULL) { + sc_list_clear(txn->elements); + + sc_mem_free(txn); + } +} \ No newline at end of file diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index d59bd4c595..44cd5607a0 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -5,13 +5,12 @@ typedef struct sc_transaction { sc_uint64 transaction_id; - sc_uint64 timestamp; sc_bool is_committed; - sc_list elements; + sc_list* elements; sc_uint32 element_count; } sc_transaction; -sc_transaction* sc_transaction_create(); +sc_transaction* sc_transaction_create(const sc_uint64* txn_id); // create a new transaction void sc_transaction_destroy(sc_transaction* txn); // destroy the given transaction diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c index d0e2290b04..221bbbcf5f 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c @@ -1 +1,58 @@ #include "sc_transaction_manager.h" + +#include + +sc_transaction_manager * transaction_manager = null_ptr; + +sc_transaction_manager* sc_transaction_manager_initialize() { + if (sc_transaction_manager_is_initialized()) { + return transaction_manager; + } + + transaction_manager = sc_mem_new(sc_transaction_manager, 1); + if (!sc_transaction_manager_is_initialized()) { + return null_ptr; + } + + transaction_manager->current_sc_transaction = null_ptr; + sc_queue_init(transaction_manager->sc_transaction_queue); + sc_monitor_init(transaction_manager->sc_monitor); + transaction_manager->transaction_counter = 0; + + return transaction_manager; +} + +sc_bool sc_transaction_manager_is_initialized() { + return transaction_manager != null_ptr; +} + +void sc_transaction_shutdown() { + if (transaction_manager != null_ptr) { + sc_transaction_manager_destroy(); + } +} + +void sc_transaction_manager_destroy() { + if (transaction_manager != null_ptr) { + sc_monitor_acquire_write(transaction_manager->sc_monitor); + sc_queue_destroy(transaction_manager->sc_transaction_queue); + sc_monitor_release_write(transaction_manager->sc_monitor); + + sc_monitor_destroy(transaction_manager->sc_monitor); + + sc_mem_free(transaction_manager); + transaction_manager = null_ptr; + } +} + +sc_transaction* sc_transaction_manager_transaction_new() { + if (!sc_transaction_manager_is_initialized()) { + return null_ptr; + } + + sc_monitor_acquire_write(transaction_manager->sc_monitor); + const sc_uint64 txn_id = transaction_manager->transaction_counter++; + sc_monitor_release_write(transaction_manager->sc_monitor); + + return sc_transaction_create(&txn_id); +} \ No newline at end of file diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h index 4fba6dfcfc..4499d11fd3 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h @@ -5,9 +5,10 @@ #include "sc-store/sc-base/sc_monitor_private.h" typedef struct sc_transaction_manager { - sc_transaction *current_sc_transaction; - sc_queue sc_transaction_queue; - sc_monitor sc_monitor; + sc_transaction*current_sc_transaction; + sc_queue* sc_transaction_queue; + sc_monitor* sc_monitor; + sc_uint64 transaction_counter; } sc_transaction_manager; sc_transaction_manager* sc_transaction_manager_initialize(); From ba1ff66ca08fdaf715f47ad0915a858f3c7e9ca3 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 26 Mar 2025 00:59:40 +0300 Subject: [PATCH 06/51] Fix link error, correct sc_transaction_manager vars name --- .../sc-store/sc-transaction/sc_transaction.c | 24 +++++++++++++- .../sc-transaction/sc_transaction_manager.c | 33 ++++++++++++++----- .../sc-transaction/sc_transaction_manager.h | 4 +-- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index 5cc04c60b8..94051a88ea 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -21,4 +21,26 @@ void sc_transaction_destroy(sc_transaction* txn) { sc_mem_free(txn); } -} \ No newline at end of file +} + +void sc_transaction_add_element(sc_transaction* txn, sc_element* element) { +} + +void sc_transaction_commit(sc_transaction* txn) { +} + +void sc_transaction_rollback(sc_transaction* txn) { +} + +sc_bool sc_transaction_validate(sc_transaction* txn) { + return SC_FALSE; +} + +void sc_transaction_merge(sc_transaction* txn) { +} + +void sc_transaction_apply(sc_transaction* txn) { +} + +void sc_transaction_clear(sc_transaction* txn) { +} diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c index 221bbbcf5f..fc622c1e00 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c @@ -15,8 +15,17 @@ sc_transaction_manager* sc_transaction_manager_initialize() { } transaction_manager->current_sc_transaction = null_ptr; - sc_queue_init(transaction_manager->sc_transaction_queue); - sc_monitor_init(transaction_manager->sc_monitor); + + transaction_manager->transaction_queue = sc_mem_new(sc_queue, 1); + transaction_manager->monitor = sc_mem_new(sc_monitor, 1); + + if (transaction_manager->transaction_queue == NULL || transaction_manager->monitor == NULL) { + sc_mem_free(transaction_manager); + return NULL; + } + + sc_queue_init(transaction_manager->transaction_queue); + sc_monitor_init(transaction_manager->monitor); transaction_manager->transaction_counter = 0; return transaction_manager; @@ -34,11 +43,11 @@ void sc_transaction_shutdown() { void sc_transaction_manager_destroy() { if (transaction_manager != null_ptr) { - sc_monitor_acquire_write(transaction_manager->sc_monitor); - sc_queue_destroy(transaction_manager->sc_transaction_queue); - sc_monitor_release_write(transaction_manager->sc_monitor); + sc_monitor_acquire_write(transaction_manager->monitor); + sc_queue_destroy(transaction_manager->transaction_queue); + sc_monitor_release_write(transaction_manager->monitor); - sc_monitor_destroy(transaction_manager->sc_monitor); + sc_monitor_destroy(transaction_manager->monitor); sc_mem_free(transaction_manager); transaction_manager = null_ptr; @@ -50,9 +59,15 @@ sc_transaction* sc_transaction_manager_transaction_new() { return null_ptr; } - sc_monitor_acquire_write(transaction_manager->sc_monitor); + sc_monitor_acquire_write(transaction_manager->monitor); const sc_uint64 txn_id = transaction_manager->transaction_counter++; - sc_monitor_release_write(transaction_manager->sc_monitor); + sc_monitor_release_write(transaction_manager->monitor); return sc_transaction_create(&txn_id); -} \ No newline at end of file +} + +void sc_transaction_manager_transaction_add(sc_transaction* txn) { +} + +void sc_transaction_manager_transaction_execute() { +} diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h index 4499d11fd3..6e96c1c61e 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h @@ -6,8 +6,8 @@ typedef struct sc_transaction_manager { sc_transaction*current_sc_transaction; - sc_queue* sc_transaction_queue; - sc_monitor* sc_monitor; + sc_queue* transaction_queue; + sc_monitor* monitor; sc_uint64 transaction_counter; } sc_transaction_manager; From 6e28a24cb13b36da2bfab4c3e3f5f2c40ba29119 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 26 Mar 2025 01:38:23 +0300 Subject: [PATCH 07/51] Change element version handling --- .../src/sc-store/sc-transaction/sc_element_version.h | 5 +++++ .../sc-store/sc-transaction/sc_transaction_buffer.c | 1 + .../sc-store/sc-transaction/sc_transaction_buffer.h | 12 ++++++++++++ .../sc-store/sc-transaction/sc_transaction_manager.h | 2 +- sc-memory/sc-core/src/sc-store/sc_element.h | 2 +- 5 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c create mode 100644 sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h index 216c7bdcee..b84508c898 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h @@ -11,4 +11,9 @@ typedef struct sc_element_version { sc_bool is_committed; } sc_element_version; +typedef struct sc_version_chain { + sc_element_version* head; + sc_element_version* tail; +} sc_version_chain; + #endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c new file mode 100644 index 0000000000..ba66191eec --- /dev/null +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c @@ -0,0 +1 @@ +#include "sc_transaction_buffer.h" diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h new file mode 100644 index 0000000000..c6f824c476 --- /dev/null +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h @@ -0,0 +1,12 @@ +#ifndef SC_TRANSACTION_BUFFER_H +#define SC_TRANSACTION_BUFFER_H + +#include + +typedef struct sc_transaction_buffer{ + sc_list* new_elements; + sc_list* modified_elements; + sc_list* deleted_elements; +} sc_transaction_buffer; + +#endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h index 6e96c1c61e..512419ba98 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h @@ -5,7 +5,7 @@ #include "sc-store/sc-base/sc_monitor_private.h" typedef struct sc_transaction_manager { - sc_transaction*current_sc_transaction; + sc_transaction* current_sc_transaction; sc_queue* transaction_queue; sc_monitor* monitor; sc_uint64 transaction_counter; diff --git a/sc-memory/sc-core/src/sc-store/sc_element.h b/sc-memory/sc-core/src/sc-store/sc_element.h index 7cce950142..d051187286 100644 --- a/sc-memory/sc-core/src/sc-store/sc_element.h +++ b/sc-memory/sc-core/src/sc-store/sc_element.h @@ -67,7 +67,7 @@ struct _sc_element sc_uint32 incoming_arcs_count; sc_uint32 outgoing_arcs_count; - sc_element_version* current_version; + sc_version_chain versions; }; #endif From 1a5d43d2a2138198b72518564dc31ca0e7708ac1 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 26 Mar 2025 02:12:36 +0300 Subject: [PATCH 08/51] Upgrade .gitignore --- .gitignore | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.gitignore b/.gitignore index 4a9fcd2a76..42d497398c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ generated cmake-build-debug cmake-build-release cmake-build-debug-coverage +cmake-build-* /CMakeUserPresets.json /ConanPresets.json @@ -43,3 +44,14 @@ __pycache__ *.log *.pdf *.run.xml + +CMakeCache.txt +CMakeFiles/ +CPackConfig.cmake +CPackSourceConfig.cmake +CTestTestfile.cmake +DartConfiguration.tcl +Makefile +cmake_install.cmake +*.cmake +*.tcl \ No newline at end of file From 2967adc3c659823f2bca695ca4d8d4640da0ad47 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 26 Mar 2025 02:13:42 +0300 Subject: [PATCH 09/51] Connect txn and buffer, init for buffer --- .../sc-store/sc-transaction/sc_transaction.c | 28 ++- .../sc-store/sc-transaction/sc_transaction.h | 5 +- .../sc-transaction/sc_transaction_buffer.c | 33 ++++ .../sc-transaction/sc_transaction_buffer.h | 20 ++- .../sc-transaction/sc_transaction_manager.c | 2 +- .../units/common/test_sc_transaction_core.cpp | 160 ++++++++++-------- 6 files changed, 158 insertions(+), 90 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index 94051a88ea..bfa68f5e0c 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -2,16 +2,36 @@ #include -sc_transaction* sc_transaction_create(const sc_uint64* txn_id) { +sc_transaction* sc_transaction_new(const sc_uint64* txn_id) +{ + if (txn_id == NULL) + return NULL; + sc_transaction *txn = sc_mem_new(sc_transaction, 1); - if (txn == NULL) { + if (txn == NULL) return NULL; - } txn->transaction_id = *txn_id; txn->is_committed = SC_FALSE; - txn->element_count = 0; + + txn->elements = sc_mem_new(sc_list, 1); + if (txn->elements == NULL) + { + sc_mem_free(txn); + return NULL; + } + + txn->transaction_buffer = sc_mem_new(sc_transaction_buffer, 1); + if (txn->transaction_buffer == NULL) + { + sc_mem_free(txn->elements); + sc_mem_free(txn); + return NULL; + } + + sc_transaction_buffer_initialize(txn->transaction_buffer); sc_list_init(&txn->elements); + return txn; } diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index 44cd5607a0..f526d53f62 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -2,15 +2,16 @@ #define SC_TRANSACTION_H #include +#include typedef struct sc_transaction { sc_uint64 transaction_id; sc_bool is_committed; sc_list* elements; - sc_uint32 element_count; + sc_transaction_buffer* transaction_buffer; } sc_transaction; -sc_transaction* sc_transaction_create(const sc_uint64* txn_id); +sc_transaction* sc_transaction_new(const sc_uint64* txn_id); // create a new transaction void sc_transaction_destroy(sc_transaction* txn); // destroy the given transaction diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c index ba66191eec..64b98b4033 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c @@ -1 +1,34 @@ #include "sc_transaction_buffer.h" + +#include +#include + +sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer* buffer) +{ + if (buffer == null_ptr) + return SC_FALSE; + + buffer->new_elements = sc_mem_new(sc_list, 1); + if (buffer->new_elements == null_ptr) + return SC_FALSE; + sc_list_init(&buffer->new_elements); + + buffer->modified_elements = sc_mem_new(sc_list, 1); + if (buffer->modified_elements == null_ptr) + { + sc_mem_free(buffer->new_elements); + return SC_FALSE; + } + sc_list_init(&buffer->modified_elements); + + buffer->deleted_elements = sc_mem_new(sc_list, 1); + if (buffer->deleted_elements == null_ptr) + { + sc_mem_free(buffer->new_elements); + sc_mem_free(buffer->modified_elements); + return SC_FALSE; + } + sc_list_init(&buffer->deleted_elements); + + return SC_TRUE; +} \ No newline at end of file diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h index c6f824c476..720d2829db 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h @@ -1,12 +1,14 @@ -#ifndef SC_TRANSACTION_BUFFER_H -#define SC_TRANSACTION_BUFFER_H + #ifndef SC_TRANSACTION_BUFFER_H + #define SC_TRANSACTION_BUFFER_H -#include + #include -typedef struct sc_transaction_buffer{ - sc_list* new_elements; - sc_list* modified_elements; - sc_list* deleted_elements; -} sc_transaction_buffer; + typedef struct sc_transaction_buffer{ + sc_list* new_elements; + sc_list* modified_elements; + sc_list* deleted_elements; + } sc_transaction_buffer; -#endif + sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer* transaction_buffer); + + #endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c index fc622c1e00..ed94ab2459 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c @@ -63,7 +63,7 @@ sc_transaction* sc_transaction_manager_transaction_new() { const sc_uint64 txn_id = transaction_manager->transaction_counter++; sc_monitor_release_write(transaction_manager->monitor); - return sc_transaction_create(&txn_id); + return sc_transaction_new(&txn_id); } void sc_transaction_manager_transaction_add(sc_transaction* txn) { diff --git a/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp b/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp index 0b27d2cfac..62717e695e 100644 --- a/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp +++ b/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp @@ -1,95 +1,107 @@ +#include "sc-memory/test/sc_test.hpp" +#include "sc-store/sc_element.h" + #include -#include -#include extern "C" { #include +#include } -struct TransactionThreadData { - transaction_manager* manager; - int thread_id; -}; - -void* transaction_thread(void* arg) { - auto* data = static_cast(arg); - transaction_manager* manager = data->manager; +#ifndef null_ptr +#define null_ptr NULL +#endif - sc_element_version version = {}; - log_version_change(manager, &version); +class ScTransactionManagerTest : public ScMemoryTest { +protected: + void SetUp() override { + sc_transaction_manager_initialize(); + } - if (data->thread_id % 2 == 0) { - commit_transaction(manager); - } else { - rollback_transaction(manager); - } + void TearDown() override { + sc_transaction_shutdown(); + } +}; - return nullptr; +TEST_F(ScTransactionManagerTest, InitializationTest) { + EXPECT_TRUE(sc_transaction_manager_is_initialized()); } -TEST_F(ScMemoryTest, MultiThreadedTransactionTest) { - transaction_manager manager; - initialize_transaction_manager(&manager); - - const int NUM_THREADS = 10; - pthread_t threads[NUM_THREADS]; - TransactionThreadData thread_data[NUM_THREADS]; - - for (int i = 0; i < NUM_THREADS; ++i) { - thread_data[i].manager = &manager; - thread_data[i].thread_id = i; - pthread_create(&threads[i], nullptr, transaction_thread, &thread_data[i]); - } - - for (int i = 0; i < NUM_THREADS; ++i) { - pthread_join(threads[i], nullptr); - } - - EXPECT_EQ(manager.current_transaction, nullptr); - - EXPECT_NE(manager.log_head, nullptr); +TEST_F(ScTransactionManagerTest, TransactionCreationTest) { + sc_transaction* txn = sc_transaction_manager_transaction_new(); + ASSERT_NE(txn, null_ptr); + EXPECT_EQ(txn->transaction_id, 0u); + sc_transaction_destroy(txn); } -TEST_F(ScMemoryTest, MultiThreadedTransactionLogTest) { - transaction_manager manager; - initialize_transaction_manager(&manager); - - const int NUM_THREADS = 5; - pthread_t threads[NUM_THREADS]; - TransactionThreadData thread_data[NUM_THREADS]; - - for (int i = 0; i < NUM_THREADS; ++i) { - thread_data[i].manager = &manager; - thread_data[i].thread_id = i; - pthread_create(&threads[i], nullptr, transaction_thread, &thread_data[i]); - } - - for (int i = 0; i < NUM_THREADS; ++i) { - pthread_join(threads[i], nullptr); - } - - EXPECT_NE(manager.log_head, nullptr); +TEST_F(ScTransactionManagerTest, TransactionCounterIncrementsTest) { + sc_transaction* txn1 = sc_transaction_manager_transaction_new(); + sc_transaction* txn2 = sc_transaction_manager_transaction_new(); + ASSERT_NE(txn1, null_ptr); + ASSERT_NE(txn2, null_ptr); + EXPECT_EQ(txn1->transaction_id, 0u); + EXPECT_EQ(txn2->transaction_id, 1u); + sc_transaction_destroy(txn1); + sc_transaction_destroy(txn2); } -TEST_F(ScMemoryTest, TransactionManagerTests) { - transaction_manager manager; - initialize_transaction_manager(&manager); +TEST_F(ScTransactionManagerTest, ShutdownTest) { + sc_transaction_shutdown(); + EXPECT_FALSE(sc_transaction_manager_is_initialized()); +} - const int NUM_THREADS = 20; - pthread_t threads[NUM_THREADS]; - TransactionThreadData thread_data[NUM_THREADS]; +TEST_F(ScTransactionManagerTest, TransactionBufferInitializationTest) { + sc_transaction* txn = sc_transaction_manager_transaction_new(); + ASSERT_NE(txn, null_ptr); + ASSERT_NE(txn->transaction_buffer, null_ptr); + EXPECT_NE(txn->transaction_buffer->new_elements, null_ptr); + EXPECT_NE(txn->transaction_buffer->modified_elements, null_ptr); + EXPECT_NE(txn->transaction_buffer->deleted_elements, null_ptr); + EXPECT_TRUE(txn->transaction_buffer->new_elements->size == 0u); + EXPECT_TRUE(txn->transaction_buffer->modified_elements->size == 0u); + EXPECT_TRUE(txn->transaction_buffer->deleted_elements->size == 0u); + sc_transaction_destroy(txn); +} - for (int i = 0; i < NUM_THREADS; ++i) { - thread_data[i].manager = &manager; - thread_data[i].thread_id = i; - pthread_create(&threads[i], nullptr, transaction_thread, &thread_data[i]); - } +TEST_F(ScTransactionManagerTest, TransactionMemoryCleanupTest) { + sc_transaction* txn = sc_transaction_manager_transaction_new(); + ASSERT_NE(txn, null_ptr); + sc_element elem = {0}; + sc_list_push_back(txn->transaction_buffer->new_elements, &elem); + sc_list_push_back(txn->transaction_buffer->modified_elements, &elem); + sc_list_push_back(txn->transaction_buffer->deleted_elements, &elem); + sc_transaction_destroy(txn); +} - for (int i = 0; i < NUM_THREADS; ++i) { - pthread_join(threads[i], nullptr); - } +TEST_F(ScTransactionManagerTest, InvalidTransactionCreationTest) { + sc_transaction_shutdown(); + sc_transaction* txn = sc_transaction_manager_transaction_new(); + EXPECT_EQ(txn, null_ptr); + sc_transaction_manager_initialize(); +} - EXPECT_EQ(manager.current_transaction, nullptr); +TEST_F(ScTransactionManagerTest, BufferOperationsTest) { + sc_transaction* txn = sc_transaction_manager_transaction_new(); + ASSERT_NE(txn, null_ptr); + sc_element elem1 = {.flags = {.type = sc_type_node}}; + sc_element elem2 = {.flags = {.type = sc_type_arc}}; + sc_list_push_back(txn->transaction_buffer->new_elements, &elem1); + EXPECT_EQ(txn->transaction_buffer->new_elements->size, 1u); + sc_list_push_back(txn->transaction_buffer->modified_elements, &elem2); + EXPECT_EQ(txn->transaction_buffer->modified_elements->size, 1u); + sc_list_push_back(txn->transaction_buffer->deleted_elements, &elem1); + EXPECT_EQ(txn->transaction_buffer->deleted_elements->size, 1u); + sc_transaction_destroy(txn); +} - EXPECT_NE(manager.log_head, nullptr); +TEST_F(ScTransactionManagerTest, TransactionIdSequenceTest) { + constexpr sc_uint32 iterations = 100; + sc_transaction* txns[iterations]; + for (sc_uint32 i = 0; i < iterations; ++i) { + txns[i] = sc_transaction_manager_transaction_new(); + ASSERT_NE(txns[i], null_ptr); + EXPECT_EQ(txns[i]->transaction_id, i); + } + for (sc_uint32 i = 0; i < iterations; ++i) + sc_transaction_destroy(txns[i]); } From a4df08decb6467c4a3e5b0c5966d6af3606558ce Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 26 Mar 2025 16:59:04 +0300 Subject: [PATCH 10/51] Highlighted 4 types of operation, flags to track sc-element field changes, implementation of adding the created element to the buffer --- .../sc-transaction/sc_element_version.h | 27 +++++--- .../sc-store/sc-transaction/sc_transaction.c | 43 +++++++----- .../sc-store/sc-transaction/sc_transaction.h | 39 +++++++---- .../sc-transaction/sc_transaction_buffer.c | 65 ++++++++++++++++++- .../sc-transaction/sc_transaction_buffer.h | 35 +++++++--- .../sc-transaction/sc_transaction_manager.c | 41 +++++++----- .../sc-transaction/sc_transaction_manager.h | 19 +++--- sc-memory/sc-core/src/sc-store/sc_element.h | 3 +- 8 files changed, 195 insertions(+), 77 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h index b84508c898..91c2fde4b2 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h @@ -1,19 +1,30 @@ #ifndef SC_ELEMENT_VERSION_H #define SC_ELEMENT_VERSION_H -#include "sc-core/sc_types.h" +#include -typedef struct sc_element_version { - void* data; +typedef struct sc_element_version +{ + sc_element * data; sc_uint64 version_id; - struct sc_element_version* prev_version; - struct sc_element_version* next_version; + struct sc_element_version * prev_version; + struct sc_element_version * next_version; sc_bool is_committed; + sc_type modified_fields; } sc_element_version; -typedef struct sc_version_chain { - sc_element_version* head; - sc_element_version* tail; +typedef struct sc_version_chain +{ + sc_element_version * head; + sc_element_version * tail; } sc_version_chain; +typedef enum +{ + SC_ELEMENT_FLAGS_MODIFIED = 1 << 0, + SC_ELEMENT_ARCS_MODIFIED = 1 << 1, + SC_ELEMENT_CONTENT_MODIFIED = 1 << 2, + SC_ELEMENT_LINKS_MODIFIED = 1 << 3 +} SC_ELEMENT_MODIFIED_FLAGS; + #endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index bfa68f5e0c..c040600579 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -2,12 +2,12 @@ #include -sc_transaction* sc_transaction_new(const sc_uint64* txn_id) +sc_transaction * sc_transaction_new(sc_uint64 const * txn_id) { if (txn_id == NULL) return NULL; - sc_transaction *txn = sc_mem_new(sc_transaction, 1); + sc_transaction * txn = sc_mem_new(sc_transaction, 1); if (txn == NULL) return NULL; @@ -35,32 +35,43 @@ sc_transaction* sc_transaction_new(const sc_uint64* txn_id) return txn; } -void sc_transaction_destroy(sc_transaction* txn) { - if (txn != NULL) { +void sc_transaction_destroy(sc_transaction * txn) +{ + if (txn != NULL) + { sc_list_clear(txn->elements); sc_mem_free(txn); } } -void sc_transaction_add_element(sc_transaction* txn, sc_element* element) { -} +void sc_transaction_add_element(sc_transaction * txn, sc_element * element) {} -void sc_transaction_commit(sc_transaction* txn) { -} +void sc_transaction_commit(sc_transaction * txn) {} -void sc_transaction_rollback(sc_transaction* txn) { -} +void sc_transaction_rollback(sc_transaction * txn) {} -sc_bool sc_transaction_validate(sc_transaction* txn) { +sc_bool sc_transaction_validate(sc_transaction * txn) +{ return SC_FALSE; } -void sc_transaction_merge(sc_transaction* txn) { -} +void sc_transaction_merge(sc_transaction * txn) {} -void sc_transaction_apply(sc_transaction* txn) { -} +void sc_transaction_apply(sc_transaction * txn) {} + +void sc_transaction_clear(sc_transaction * txn) {} + +sc_bool sc_transaction_element_new(sc_transaction * txn, sc_element * element) {} -void sc_transaction_clear(sc_transaction* txn) { +sc_bool sc_transaction_element_change( + sc_element * element, + sc_transaction * txn, + SC_ELEMENT_MODIFIED_FLAGS modified_flags, + sc_element const * new_data) +{ } + +sc_bool sc_transaction_element_remove(sc_transaction * txn, sc_addr addr) {} + +sc_bool sc_transaction_element_content_set(sc_transaction * txn, sc_addr addr, sc_stream * content) {} \ No newline at end of file diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index f526d53f62..2143568963 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -1,35 +1,46 @@ #ifndef SC_TRANSACTION_H #define SC_TRANSACTION_H -#include +#include #include -typedef struct sc_transaction { +#include +#include + +typedef struct sc_transaction +{ sc_uint64 transaction_id; sc_bool is_committed; - sc_list* elements; - sc_transaction_buffer* transaction_buffer; + sc_list * elements; + sc_transaction_buffer * transaction_buffer; } sc_transaction; -sc_transaction* sc_transaction_new(const sc_uint64* txn_id); +sc_transaction * sc_transaction_new(sc_uint64 const * txn_id); // create a new transaction -void sc_transaction_destroy(sc_transaction* txn); +void sc_transaction_destroy(sc_transaction * txn); // destroy the given transaction -void sc_transaction_add_element(sc_transaction* txn, sc_element* element); -// add element to track in transaction (based on "touched" elements, manager will try to commit or rollback transaction) -void sc_transaction_commit(sc_transaction* txn); +sc_bool sc_transaction_element_new(sc_transaction * txn, sc_element * element); +sc_bool sc_transaction_element_change( + sc_element * element, + sc_transaction * txn, + SC_ELEMENT_MODIFIED_FLAGS modified_flags, + sc_element const * new_data); +sc_bool sc_transaction_element_remove(sc_transaction * txn, sc_addr addr); +sc_bool sc_transaction_element_content_set(sc_transaction * txn, sc_addr addr, sc_stream * content); + +void sc_transaction_commit(sc_transaction * txn); // apply all operations of the transaction on sc-memory -void sc_transaction_rollback(sc_transaction* txn); +void sc_transaction_rollback(sc_transaction * txn); // rollback the transaction operations -sc_bool sc_transaction_validate(sc_transaction* txn); +sc_bool sc_transaction_validate(sc_transaction * txn); // check if the transaction can be applied based on element versions and free segments -void sc_transaction_merge(sc_transaction* txn); +void sc_transaction_merge(sc_transaction * txn); // check versions of all elements in the transaction and try to merge them -void sc_transaction_apply(sc_transaction* txn); +void sc_transaction_apply(sc_transaction * txn); // apply all operations (merged versions, allocated spaces) to sc-memory -void sc_transaction_clear(sc_transaction* txn); +void sc_transaction_clear(sc_transaction * txn); // deletes all transaction items and clears them without performing a commit #endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c index 64b98b4033..3926078d3c 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c @@ -1,9 +1,12 @@ #include "sc_transaction_buffer.h" +#include + #include #include +#include -sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer* buffer) +sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * buffer) { if (buffer == null_ptr) return SC_FALSE; @@ -31,4 +34,62 @@ sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer* buffer) sc_list_init(&buffer->deleted_elements); return SC_TRUE; -} \ No newline at end of file +} + +sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer * buffer, sc_addr addr) +{ + if (buffer == null_ptr || buffer->new_elements == null_ptr) + { + return SC_FALSE; + } + + if (SC_ADDR_IS_EMPTY(addr)) + { + return SC_FALSE; + } + + if (transaction_buffer_contains_created(buffer, addr)) + { + return SC_TRUE; + } + + sc_addr * addr_copy = sc_mem_new(sc_addr, 1); + if (addr_copy == null_ptr) + { + return SC_FALSE; + } + + *addr_copy = addr; + + if (sc_list_push_back(buffer->new_elements, addr_copy) == null_ptr) + { + sc_mem_free(addr_copy); + return SC_FALSE; + } + + return SC_TRUE; +} + +sc_bool sc_transaction_buffer_modified_add( + sc_transaction_buffer * buf, + sc_addr addr, + sc_element_version * version, + SC_ELEMENT_MODIFIED_FLAGS flags) +{ +} + +sc_bool transaction_buffer_contains_created(sc_transaction_buffer const * buffer, sc_addr addr) +{ + sc_iterator * it = sc_list_iterator(buffer->new_elements); + while (sc_iterator_next(it)) + { + sc_addr * stored_addr = (sc_addr *)sc_iterator_get(it); + if (SC_ADDR_IS_EQUAL(*stored_addr, addr)) + return SC_TRUE; + } + return SC_FALSE; +} + +sc_bool sc_transaction_buffer_removed_add(sc_transaction_buffer * buffer, sc_addr addr) {} + +sc_bool sc_transaction_buffer_content_change_add(sc_transaction_buffer * buffer, sc_addr addr, sc_stream * content) {} diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h index 720d2829db..c79bffb8d2 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h @@ -1,14 +1,29 @@ - #ifndef SC_TRANSACTION_BUFFER_H - #define SC_TRANSACTION_BUFFER_H +#ifndef SC_TRANSACTION_BUFFER_H +#define SC_TRANSACTION_BUFFER_H - #include +#include - typedef struct sc_transaction_buffer{ - sc_list* new_elements; - sc_list* modified_elements; - sc_list* deleted_elements; - } sc_transaction_buffer; +#include +#include - sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer* transaction_buffer); +typedef struct sc_transaction_buffer +{ + sc_list * new_elements; + sc_list * modified_elements; + sc_list * deleted_elements; +} sc_transaction_buffer; - #endif +sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer); + +sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer * buffer, sc_addr addr); +sc_bool sc_transaction_buffer_modified_add( + sc_transaction_buffer * buf, + sc_addr addr, + sc_element_version * version, + SC_ELEMENT_MODIFIED_FLAGS flags); +sc_bool sc_transaction_buffer_removed_add(sc_transaction_buffer * buffer, sc_addr addr); +sc_bool sc_transaction_buffer_content_change_add(sc_transaction_buffer * buffer, sc_addr addr, sc_stream * content); + +sc_bool transaction_buffer_contains_created(sc_transaction_buffer const * buffer, sc_addr addr); + +#endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c index ed94ab2459..eaa2562efc 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c @@ -4,13 +4,16 @@ sc_transaction_manager * transaction_manager = null_ptr; -sc_transaction_manager* sc_transaction_manager_initialize() { - if (sc_transaction_manager_is_initialized()) { +sc_transaction_manager * sc_transaction_manager_initialize() +{ + if (sc_transaction_manager_is_initialized()) + { return transaction_manager; } transaction_manager = sc_mem_new(sc_transaction_manager, 1); - if (!sc_transaction_manager_is_initialized()) { + if (!sc_transaction_manager_is_initialized()) + { return null_ptr; } @@ -19,7 +22,8 @@ sc_transaction_manager* sc_transaction_manager_initialize() { transaction_manager->transaction_queue = sc_mem_new(sc_queue, 1); transaction_manager->monitor = sc_mem_new(sc_monitor, 1); - if (transaction_manager->transaction_queue == NULL || transaction_manager->monitor == NULL) { + if (transaction_manager->transaction_queue == NULL || transaction_manager->monitor == NULL) + { sc_mem_free(transaction_manager); return NULL; } @@ -31,18 +35,23 @@ sc_transaction_manager* sc_transaction_manager_initialize() { return transaction_manager; } -sc_bool sc_transaction_manager_is_initialized() { +sc_bool sc_transaction_manager_is_initialized() +{ return transaction_manager != null_ptr; } -void sc_transaction_shutdown() { - if (transaction_manager != null_ptr) { +void sc_transaction_shutdown() +{ + if (transaction_manager != null_ptr) + { sc_transaction_manager_destroy(); } } -void sc_transaction_manager_destroy() { - if (transaction_manager != null_ptr) { +void sc_transaction_manager_destroy() +{ + if (transaction_manager != null_ptr) + { sc_monitor_acquire_write(transaction_manager->monitor); sc_queue_destroy(transaction_manager->transaction_queue); sc_monitor_release_write(transaction_manager->monitor); @@ -54,20 +63,20 @@ void sc_transaction_manager_destroy() { } } -sc_transaction* sc_transaction_manager_transaction_new() { - if (!sc_transaction_manager_is_initialized()) { +sc_transaction * sc_transaction_manager_transaction_new() +{ + if (!sc_transaction_manager_is_initialized()) + { return null_ptr; } sc_monitor_acquire_write(transaction_manager->monitor); - const sc_uint64 txn_id = transaction_manager->transaction_counter++; + sc_uint64 const txn_id = transaction_manager->transaction_counter++; sc_monitor_release_write(transaction_manager->monitor); return sc_transaction_new(&txn_id); } -void sc_transaction_manager_transaction_add(sc_transaction* txn) { -} +void sc_transaction_manager_transaction_add(sc_transaction * txn) {} -void sc_transaction_manager_transaction_execute() { -} +void sc_transaction_manager_transaction_execute() {} diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h index 512419ba98..c4c1752c78 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h @@ -1,26 +1,27 @@ #ifndef SC_TRANSACTION_MANAGER_H #define SC_TRANSACTION_MANAGER_H -#include "sc_transaction.h" -#include "sc-store/sc-base/sc_monitor_private.h" +#include +#include -typedef struct sc_transaction_manager { - sc_transaction* current_sc_transaction; - sc_queue* transaction_queue; - sc_monitor* monitor; +typedef struct sc_transaction_manager +{ + sc_transaction * current_sc_transaction; + sc_queue * transaction_queue; + sc_monitor * monitor; sc_uint64 transaction_counter; } sc_transaction_manager; -sc_transaction_manager* sc_transaction_manager_initialize(); +sc_transaction_manager * sc_transaction_manager_initialize(); // create and initialize the transaction manager sc_bool sc_transaction_manager_is_initialized(); // check if the transaction manager is initialized void sc_transaction_shutdown(); // shutdown the transaction manager -sc_transaction* sc_transaction_manager_transaction_new(); +sc_transaction * sc_transaction_manager_transaction_new(); // create a new empty sc-transaction -void sc_transaction_manager_transaction_add(sc_transaction* txn); +void sc_transaction_manager_transaction_add(sc_transaction * txn); // add transaction to the queue and start operations when the thread is ready void sc_transaction_manager_transaction_execute(); // try to execute the transaction and wait till it's finished diff --git a/sc-memory/sc-core/src/sc-store/sc_element.h b/sc-memory/sc-core/src/sc-store/sc_element.h index d051187286..fd9c6ad7c5 100644 --- a/sc-memory/sc-core/src/sc-store/sc_element.h +++ b/sc-memory/sc-core/src/sc-store/sc_element.h @@ -7,8 +7,7 @@ #ifndef _sc_element_h_ #define _sc_element_h_ -#include "sc-core/sc_types.h" -#include "sc-transaction/sc_element_version.h" +#include struct _sc_arc_info { From c433d47506a004fd6ae0430ea049ff07804f4916 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 26 Mar 2025 16:59:50 +0300 Subject: [PATCH 11/51] Tests for buffer (add created element) --- .../units/common/test_sc_transaction_core.cpp | 156 +++++++++++++----- 1 file changed, 111 insertions(+), 45 deletions(-) diff --git a/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp b/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp index 62717e695e..f5593d8ad1 100644 --- a/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp +++ b/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp @@ -1,42 +1,61 @@ -#include "sc-memory/test/sc_test.hpp" -#include "sc-store/sc_element.h" - #include +#include -extern "C" { +extern "C" +{ #include #include +#include +#include +#include +#include +#include +#include } #ifndef null_ptr -#define null_ptr NULL +# define null_ptr NULL #endif -class ScTransactionManagerTest : public ScMemoryTest { +class ScTransactionManagerTest : public ScMemoryTest +{ protected: - void SetUp() override { + void SetUp() override + { + ScMemoryTest::Initialize(); + m_ctx = std::make_unique(); + sc_transaction_manager_initialize(); } - void TearDown() override { + void TearDown() override + { sc_transaction_shutdown(); + + if (m_ctx) + m_ctx->Destroy(); + + ScMemoryTest::Shutdown(); } }; -TEST_F(ScTransactionManagerTest, InitializationTest) { +TEST_F(ScTransactionManagerTest, InitializationTest) +{ EXPECT_TRUE(sc_transaction_manager_is_initialized()); } -TEST_F(ScTransactionManagerTest, TransactionCreationTest) { - sc_transaction* txn = sc_transaction_manager_transaction_new(); - ASSERT_NE(txn, null_ptr); +TEST_F(ScTransactionManagerTest, TransactionCreationTest) +{ + sc_transaction * txn = sc_transaction_manager_transaction_new(); + ASSERT_NE(txn, null_ptr) << "Transaction creation failed"; EXPECT_EQ(txn->transaction_id, 0u); sc_transaction_destroy(txn); } -TEST_F(ScTransactionManagerTest, TransactionCounterIncrementsTest) { - sc_transaction* txn1 = sc_transaction_manager_transaction_new(); - sc_transaction* txn2 = sc_transaction_manager_transaction_new(); +TEST_F(ScTransactionManagerTest, TransactionCounterIncrementsTest) +{ + sc_transaction * txn1 = sc_transaction_manager_transaction_new(); + sc_transaction * txn2 = sc_transaction_manager_transaction_new(); ASSERT_NE(txn1, null_ptr); ASSERT_NE(txn2, null_ptr); EXPECT_EQ(txn1->transaction_id, 0u); @@ -45,59 +64,56 @@ TEST_F(ScTransactionManagerTest, TransactionCounterIncrementsTest) { sc_transaction_destroy(txn2); } -TEST_F(ScTransactionManagerTest, ShutdownTest) { +TEST_F(ScTransactionManagerTest, ShutdownTest) +{ sc_transaction_shutdown(); EXPECT_FALSE(sc_transaction_manager_is_initialized()); } -TEST_F(ScTransactionManagerTest, TransactionBufferInitializationTest) { - sc_transaction* txn = sc_transaction_manager_transaction_new(); +TEST_F(ScTransactionManagerTest, TransactionBufferInitializationTest) +{ + sc_transaction * txn = sc_transaction_manager_transaction_new(); ASSERT_NE(txn, null_ptr); + ASSERT_NE(txn->transaction_buffer, null_ptr); - EXPECT_NE(txn->transaction_buffer->new_elements, null_ptr); - EXPECT_NE(txn->transaction_buffer->modified_elements, null_ptr); - EXPECT_NE(txn->transaction_buffer->deleted_elements, null_ptr); - EXPECT_TRUE(txn->transaction_buffer->new_elements->size == 0u); - EXPECT_TRUE(txn->transaction_buffer->modified_elements->size == 0u); - EXPECT_TRUE(txn->transaction_buffer->deleted_elements->size == 0u); + ASSERT_NE(txn->transaction_buffer->new_elements, null_ptr); + ASSERT_NE(txn->transaction_buffer->modified_elements, null_ptr); + ASSERT_NE(txn->transaction_buffer->deleted_elements, null_ptr); + + EXPECT_EQ(txn->transaction_buffer->new_elements->size, 0u); + EXPECT_EQ(txn->transaction_buffer->modified_elements->size, 0u); + EXPECT_EQ(txn->transaction_buffer->deleted_elements->size, 0u); + sc_transaction_destroy(txn); } -TEST_F(ScTransactionManagerTest, TransactionMemoryCleanupTest) { - sc_transaction* txn = sc_transaction_manager_transaction_new(); +TEST_F(ScTransactionManagerTest, TransactionMemoryCleanupTest) +{ + sc_transaction * txn = sc_transaction_manager_transaction_new(); ASSERT_NE(txn, null_ptr); + sc_element elem = {0}; sc_list_push_back(txn->transaction_buffer->new_elements, &elem); sc_list_push_back(txn->transaction_buffer->modified_elements, &elem); sc_list_push_back(txn->transaction_buffer->deleted_elements, &elem); + sc_transaction_destroy(txn); } -TEST_F(ScTransactionManagerTest, InvalidTransactionCreationTest) { +TEST_F(ScTransactionManagerTest, InvalidTransactionCreationTest) +{ sc_transaction_shutdown(); - sc_transaction* txn = sc_transaction_manager_transaction_new(); + sc_transaction * txn = sc_transaction_manager_transaction_new(); EXPECT_EQ(txn, null_ptr); sc_transaction_manager_initialize(); } -TEST_F(ScTransactionManagerTest, BufferOperationsTest) { - sc_transaction* txn = sc_transaction_manager_transaction_new(); - ASSERT_NE(txn, null_ptr); - sc_element elem1 = {.flags = {.type = sc_type_node}}; - sc_element elem2 = {.flags = {.type = sc_type_arc}}; - sc_list_push_back(txn->transaction_buffer->new_elements, &elem1); - EXPECT_EQ(txn->transaction_buffer->new_elements->size, 1u); - sc_list_push_back(txn->transaction_buffer->modified_elements, &elem2); - EXPECT_EQ(txn->transaction_buffer->modified_elements->size, 1u); - sc_list_push_back(txn->transaction_buffer->deleted_elements, &elem1); - EXPECT_EQ(txn->transaction_buffer->deleted_elements->size, 1u); - sc_transaction_destroy(txn); -} - -TEST_F(ScTransactionManagerTest, TransactionIdSequenceTest) { +TEST_F(ScTransactionManagerTest, TransactionIdSequenceTest) +{ constexpr sc_uint32 iterations = 100; - sc_transaction* txns[iterations]; - for (sc_uint32 i = 0; i < iterations; ++i) { + sc_transaction * txns[iterations]; + for (sc_uint32 i = 0; i < iterations; ++i) + { txns[i] = sc_transaction_manager_transaction_new(); ASSERT_NE(txns[i], null_ptr); EXPECT_EQ(txns[i]->transaction_id, i); @@ -105,3 +121,53 @@ TEST_F(ScTransactionManagerTest, TransactionIdSequenceTest) { for (sc_uint32 i = 0; i < iterations; ++i) sc_transaction_destroy(txns[i]); } + +TEST_F(ScTransactionManagerTest, AddCreatedElementSuccess) +{ + sc_transaction * txn = sc_transaction_manager_transaction_new(); + ASSERT_NE(txn, null_ptr); + + sc_addr const & addr = sc_storage_node_new(m_ctx.get()->GetRealContext(), sc_type_const_node); + + EXPECT_TRUE(sc_transaction_buffer_created_add(txn->transaction_buffer, addr)); + EXPECT_EQ(txn->transaction_buffer->new_elements->size, 1u); + + sc_struct_node * node = sc_list_front(txn->transaction_buffer->new_elements); + ASSERT_NE(node, null_ptr); + + sc_addr const * stored_addr = static_cast(node->data); + ASSERT_NE(stored_addr, null_ptr); + + EXPECT_EQ(stored_addr->seg, addr.seg); + EXPECT_EQ(stored_addr->offset, addr.offset); + + sc_transaction_destroy(txn); +} + +TEST_F(ScTransactionManagerTest, AddCreatedDuplicateElement) +{ + sc_transaction * txn = sc_transaction_manager_transaction_new(); + ASSERT_NE(txn, null_ptr); + + sc_addr const & addr = sc_storage_node_new(m_ctx.get()->GetRealContext(), sc_type_const_node); + + EXPECT_TRUE(sc_transaction_buffer_created_add(txn->transaction_buffer, addr)); + EXPECT_TRUE(sc_transaction_buffer_created_add(txn->transaction_buffer, addr)); + EXPECT_EQ(txn->transaction_buffer->new_elements->size, 1u); + + sc_transaction_destroy(txn); +} + +TEST_F(ScTransactionManagerTest, AddCreatedInvalidAddress) +{ + sc_transaction * txn = sc_transaction_manager_transaction_new(); + ASSERT_NE(txn, null_ptr); + + EXPECT_FALSE(sc_transaction_buffer_created_add(txn->transaction_buffer, SC_ADDR_EMPTY)); + EXPECT_FALSE(sc_transaction_buffer_created_add(static_cast null_ptr, SC_ADDR_EMPTY)); + + if (txn->transaction_buffer->new_elements) + EXPECT_EQ(txn->transaction_buffer->new_elements->size, 0u); + + sc_transaction_destroy(txn); +} From 06a7dcbb72be55f949477658e5ec989908df2bad Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Sat, 29 Mar 2025 01:43:08 +0300 Subject: [PATCH 12/51] Implementation of transaction_buffer --- .../sc-transaction/sc_element_version.c | 29 +++++ .../sc-transaction/sc_element_version.h | 4 +- .../sc-transaction/sc_transaction_buffer.c | 110 +++++++++++++++--- .../sc-transaction/sc_transaction_buffer.h | 7 +- 4 files changed, 130 insertions(+), 20 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c index 36d0ce55f5..c2fbd02eae 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c @@ -1 +1,30 @@ #include "sc_element_version.h" + +#include +#include + +sc_element_version * sc_element_create_new_version(sc_element * element, sc_uint64 version_id, sc_type modified_fields) +{ + if (element == NULL) + return NULL; + + sc_element_version * new_version = sc_mem_new(sc_element_version, 1); + if (new_version == NULL) + return NULL; + + new_version->data = element; + new_version->version_id = version_id; + new_version->prev_version = element->versions.tail; + new_version->next_version = NULL; + new_version->is_committed = SC_FALSE; + new_version->modified_fields = modified_fields; + + if (element->versions.tail) + element->versions.tail->next_version = new_version; + else + element->versions.head = new_version; + + element->versions.tail = new_version; + + return new_version; +} diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h index 91c2fde4b2..e7125e8968 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h @@ -5,7 +5,7 @@ typedef struct sc_element_version { - sc_element * data; + sc_element* data; sc_uint64 version_id; struct sc_element_version * prev_version; struct sc_element_version * next_version; @@ -27,4 +27,6 @@ typedef enum SC_ELEMENT_LINKS_MODIFIED = 1 << 3 } SC_ELEMENT_MODIFIED_FLAGS; +sc_element_version * sc_element_create_new_version(sc_element * element, sc_uint64 version_id, sc_type modified_fields); + #endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c index 3926078d3c..4b6147269a 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c @@ -1,11 +1,17 @@ #include "sc_transaction_buffer.h" #include - #include #include #include +typedef struct sc_modified_element { + sc_addr addr; + sc_element_version * version; + sc_stream * content; + SC_ELEMENT_MODIFIED_FLAGS flags; +} sc_modified_element; + sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * buffer) { if (buffer == null_ptr) @@ -39,25 +45,17 @@ sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * buffer) sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer * buffer, sc_addr addr) { if (buffer == null_ptr || buffer->new_elements == null_ptr) - { return SC_FALSE; - } if (SC_ADDR_IS_EMPTY(addr)) - { return SC_FALSE; - } if (transaction_buffer_contains_created(buffer, addr)) - { return SC_TRUE; - } sc_addr * addr_copy = sc_mem_new(sc_addr, 1); if (addr_copy == null_ptr) - { return SC_FALSE; - } *addr_copy = addr; @@ -71,25 +69,107 @@ sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer * buffer, sc_add } sc_bool sc_transaction_buffer_modified_add( - sc_transaction_buffer * buf, + sc_transaction_buffer * buffer, sc_addr addr, - sc_element_version * version, + sc_element * element, + sc_stream * content, SC_ELEMENT_MODIFIED_FLAGS flags) { + if (buffer == null_ptr || buffer->modified_elements == null_ptr) + return SC_FALSE; + + if (SC_ADDR_IS_EMPTY(addr)) + return SC_FALSE; + + sc_element_version * new_version = sc_element_create_new_version(element, /* version_id */ 0, flags); // Add generation for id + if (new_version == NULL) + return SC_FALSE; + + sc_iterator * it = sc_list_iterator(buffer->modified_elements); + while (sc_iterator_next(it)) + { + sc_modified_element * mod = (sc_modified_element *) sc_iterator_get(it); + if (SC_ADDR_IS_EQUAL(mod->addr, addr)) + { + mod->version = new_version; + mod->content = content; + mod->flags = flags; + sc_iterator_destroy(it); + return SC_TRUE; + } + } + sc_iterator_destroy(it); + + sc_modified_element * new_mod = sc_mem_new(sc_modified_element, 1); + if (new_mod == null_ptr) + return SC_FALSE; + + new_mod->addr = addr; + new_mod->version = new_version; + new_mod->content = content; + new_mod->flags = flags; + + if (sc_list_push_back(buffer->modified_elements, new_mod) == null_ptr) + { + sc_mem_free(new_version); + sc_mem_free(new_mod); + return SC_FALSE; + } + + return SC_TRUE; +} + +sc_bool sc_transaction_buffer_removed_add(sc_transaction_buffer * buffer, sc_addr addr) +{ + if (buffer == null_ptr || buffer->deleted_elements == null_ptr) + return SC_FALSE; + + if (SC_ADDR_IS_EMPTY(addr)) + return SC_FALSE; + + sc_iterator * it = sc_list_iterator(buffer->deleted_elements); + while (sc_iterator_next(it)) + { + sc_addr * stored_addr = (sc_addr *) sc_iterator_get(it); + if (SC_ADDR_IS_EQUAL(*stored_addr, addr)) + { + sc_iterator_destroy(it); + return SC_TRUE; + } + } + sc_iterator_destroy(it); + + sc_addr * addr_copy = sc_mem_new(sc_addr, 1); + if (addr_copy == null_ptr) + return SC_FALSE; + + *addr_copy = addr; + if (sc_list_push_back(buffer->deleted_elements, addr_copy) == null_ptr) + { + sc_mem_free(addr_copy); + return SC_FALSE; + } + + return SC_TRUE; } sc_bool transaction_buffer_contains_created(sc_transaction_buffer const * buffer, sc_addr addr) { + if (buffer == null_ptr || buffer->new_elements == null_ptr) + return SC_FALSE; + sc_iterator * it = sc_list_iterator(buffer->new_elements); while (sc_iterator_next(it)) { - sc_addr * stored_addr = (sc_addr *)sc_iterator_get(it); + sc_addr * stored_addr = (sc_addr *) sc_iterator_get(it); if (SC_ADDR_IS_EQUAL(*stored_addr, addr)) + { + sc_iterator_destroy(it); return SC_TRUE; + } } + sc_iterator_destroy(it); + return SC_FALSE; } -sc_bool sc_transaction_buffer_removed_add(sc_transaction_buffer * buffer, sc_addr addr) {} - -sc_bool sc_transaction_buffer_content_change_add(sc_transaction_buffer * buffer, sc_addr addr, sc_stream * content) {} diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h index c79bffb8d2..e49c14362c 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h @@ -2,7 +2,6 @@ #define SC_TRANSACTION_BUFFER_H #include - #include #include @@ -17,12 +16,12 @@ sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buf sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer * buffer, sc_addr addr); sc_bool sc_transaction_buffer_modified_add( - sc_transaction_buffer * buf, + sc_transaction_buffer * buffer, sc_addr addr, - sc_element_version * version, + sc_element * element, + sc_stream * content, SC_ELEMENT_MODIFIED_FLAGS flags); sc_bool sc_transaction_buffer_removed_add(sc_transaction_buffer * buffer, sc_addr addr); -sc_bool sc_transaction_buffer_content_change_add(sc_transaction_buffer * buffer, sc_addr addr, sc_stream * content); sc_bool transaction_buffer_contains_created(sc_transaction_buffer const * buffer, sc_addr addr); From a418e36d5fd8038e619d6cd1b783091848ac9887 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Sun, 30 Mar 2025 21:29:41 +0300 Subject: [PATCH 13/51] Replace sc_addr pointers with their hash values in lists --- .../sc-transaction/sc_transaction_buffer.c | 100 +++++++++--------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c index 4b6147269a..74388a8ef7 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c @@ -1,5 +1,7 @@ #include "sc_transaction_buffer.h" +#include "sc-store/sc-base/sc_monitor_private.h" + #include #include #include @@ -12,37 +14,32 @@ typedef struct sc_modified_element { SC_ELEMENT_MODIFIED_FLAGS flags; } sc_modified_element; -sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * buffer) +sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer) { - if (buffer == null_ptr) + if (transaction_buffer == null_ptr) return SC_FALSE; - buffer->new_elements = sc_mem_new(sc_list, 1); - if (buffer->new_elements == null_ptr) + if (!sc_list_init(&transaction_buffer->new_elements)) return SC_FALSE; - sc_list_init(&buffer->new_elements); - buffer->modified_elements = sc_mem_new(sc_list, 1); - if (buffer->modified_elements == null_ptr) + if (!sc_list_init(&transaction_buffer->modified_elements)) { - sc_mem_free(buffer->new_elements); + sc_list_destroy(transaction_buffer->new_elements); return SC_FALSE; } - sc_list_init(&buffer->modified_elements); - buffer->deleted_elements = sc_mem_new(sc_list, 1); - if (buffer->deleted_elements == null_ptr) + if (!sc_list_init(&transaction_buffer->deleted_elements)) { - sc_mem_free(buffer->new_elements); - sc_mem_free(buffer->modified_elements); + sc_list_destroy(transaction_buffer->new_elements); + sc_list_destroy(transaction_buffer->modified_elements); return SC_FALSE; } - sc_list_init(&buffer->deleted_elements); return SC_TRUE; } -sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer * buffer, sc_addr addr) + +sc_bool sc_transaction_buffer_created_add(const sc_transaction_buffer * buffer, const sc_addr addr) { if (buffer == null_ptr || buffer->new_elements == null_ptr) return SC_FALSE; @@ -50,30 +47,22 @@ sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer * buffer, sc_add if (SC_ADDR_IS_EMPTY(addr)) return SC_FALSE; + const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); if (transaction_buffer_contains_created(buffer, addr)) return SC_TRUE; - sc_addr * addr_copy = sc_mem_new(sc_addr, 1); - if (addr_copy == null_ptr) + if (sc_list_push_back(buffer->new_elements, (void*)(uintptr_t)addr_hash) == null_ptr) return SC_FALSE; - *addr_copy = addr; - - if (sc_list_push_back(buffer->new_elements, addr_copy) == null_ptr) - { - sc_mem_free(addr_copy); - return SC_FALSE; - } - return SC_TRUE; } sc_bool sc_transaction_buffer_modified_add( - sc_transaction_buffer * buffer, - sc_addr addr, + const sc_transaction_buffer * buffer, + const sc_addr addr, sc_element * element, sc_stream * content, - SC_ELEMENT_MODIFIED_FLAGS flags) + const SC_ELEMENT_MODIFIED_FLAGS flags) { if (buffer == null_ptr || buffer->modified_elements == null_ptr) return SC_FALSE; @@ -81,19 +70,27 @@ sc_bool sc_transaction_buffer_modified_add( if (SC_ADDR_IS_EMPTY(addr)) return SC_FALSE; - sc_element_version * new_version = sc_element_create_new_version(element, /* version_id */ 0, flags); // Add generation for id - if (new_version == NULL) - return SC_FALSE; + const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); sc_iterator * it = sc_list_iterator(buffer->modified_elements); while (sc_iterator_next(it)) { - sc_modified_element * mod = (sc_modified_element *) sc_iterator_get(it); - if (SC_ADDR_IS_EQUAL(mod->addr, addr)) + sc_modified_element * mod = sc_iterator_get(it); + if (SC_ADDR_LOCAL_TO_INT(mod->addr) == addr_hash) { + sc_element_version * new_version = sc_element_create_new_version(element, mod->version->version_id + 1, flags); + if (new_version == NULL) + { + sc_iterator_destroy(it); + return SC_FALSE; + } + + new_version->prev_version = mod->version; + mod->version->next_version = new_version; + mod->version = new_version; mod->content = content; - mod->flags = flags; + mod->flags |= flags; // merge field edit flags sc_iterator_destroy(it); return SC_TRUE; } @@ -105,13 +102,19 @@ sc_bool sc_transaction_buffer_modified_add( return SC_FALSE; new_mod->addr = addr; - new_mod->version = new_version; + new_mod->version = sc_element_create_new_version(element, 0, flags); + if (new_mod->version == NULL) + { + sc_mem_free(new_mod); + return SC_FALSE; + } + new_mod->content = content; new_mod->flags = flags; if (sc_list_push_back(buffer->modified_elements, new_mod) == null_ptr) { - sc_mem_free(new_version); + sc_mem_free(new_mod->version); sc_mem_free(new_mod); return SC_FALSE; } @@ -119,7 +122,7 @@ sc_bool sc_transaction_buffer_modified_add( return SC_TRUE; } -sc_bool sc_transaction_buffer_removed_add(sc_transaction_buffer * buffer, sc_addr addr) +sc_bool sc_transaction_buffer_removed_add(const sc_transaction_buffer * buffer, const sc_addr addr) { if (buffer == null_ptr || buffer->deleted_elements == null_ptr) return SC_FALSE; @@ -127,11 +130,13 @@ sc_bool sc_transaction_buffer_removed_add(sc_transaction_buffer * buffer, sc_add if (SC_ADDR_IS_EMPTY(addr)) return SC_FALSE; + const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); + sc_iterator * it = sc_list_iterator(buffer->deleted_elements); while (sc_iterator_next(it)) { - sc_addr * stored_addr = (sc_addr *) sc_iterator_get(it); - if (SC_ADDR_IS_EQUAL(*stored_addr, addr)) + const sc_uint32 stored_hash = (uintptr_t)sc_iterator_get(it); + if (stored_hash == addr_hash) { sc_iterator_destroy(it); return SC_TRUE; @@ -139,30 +144,24 @@ sc_bool sc_transaction_buffer_removed_add(sc_transaction_buffer * buffer, sc_add } sc_iterator_destroy(it); - sc_addr * addr_copy = sc_mem_new(sc_addr, 1); - if (addr_copy == null_ptr) + if (sc_list_push_back(buffer->deleted_elements, (void*)(uintptr_t)addr_hash) == null_ptr) return SC_FALSE; - *addr_copy = addr; - if (sc_list_push_back(buffer->deleted_elements, addr_copy) == null_ptr) - { - sc_mem_free(addr_copy); - return SC_FALSE; - } - return SC_TRUE; } + sc_bool transaction_buffer_contains_created(sc_transaction_buffer const * buffer, sc_addr addr) { if (buffer == null_ptr || buffer->new_elements == null_ptr) return SC_FALSE; + const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); sc_iterator * it = sc_list_iterator(buffer->new_elements); while (sc_iterator_next(it)) { - sc_addr * stored_addr = (sc_addr *) sc_iterator_get(it); - if (SC_ADDR_IS_EQUAL(*stored_addr, addr)) + const sc_uint32 stored_hash = (uintptr_t)sc_iterator_get(it); + if (stored_hash == addr_hash) { sc_iterator_destroy(it); return SC_TRUE; @@ -173,3 +172,4 @@ sc_bool transaction_buffer_contains_created(sc_transaction_buffer const * buffer return SC_FALSE; } + From 5ca1034ca2d35226fe98dc9f2d27e5616edaf53e Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Sun, 30 Mar 2025 23:39:19 +0300 Subject: [PATCH 14/51] Generation of id's for elements versions using monitor_table --- .../sc-store/sc-transaction/sc_transaction.c | 32 +++++++------------ .../sc-store/sc-transaction/sc_transaction.h | 2 +- .../sc-transaction/sc_transaction_buffer.c | 29 +++++++++++++++-- .../sc-transaction/sc_transaction_buffer.h | 2 ++ 4 files changed, 41 insertions(+), 24 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index c040600579..ce79a28c32 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -2,44 +2,36 @@ #include -sc_transaction * sc_transaction_new(sc_uint64 const * txn_id) +sc_transaction * sc_transaction_new(const sc_uint64 txn_id) { - if (txn_id == NULL) - return NULL; - sc_transaction * txn = sc_mem_new(sc_transaction, 1); - if (txn == NULL) - return NULL; + if (txn == null_ptr) + return null_ptr; - txn->transaction_id = *txn_id; + txn->transaction_id = txn_id; txn->is_committed = SC_FALSE; - txn->elements = sc_mem_new(sc_list, 1); - if (txn->elements == NULL) + txn->transaction_buffer = sc_mem_new(sc_transaction_buffer, 1); + if (txn->transaction_buffer == null_ptr) { sc_mem_free(txn); - return NULL; + return null_ptr; } + sc_transaction_buffer_initialize(txn->transaction_buffer); - txn->transaction_buffer = sc_mem_new(sc_transaction_buffer, 1); - if (txn->transaction_buffer == NULL) + if(!sc_list_init(&txn->elements)) { - sc_mem_free(txn->elements); - sc_mem_free(txn); - return NULL; + return null_ptr; } - sc_transaction_buffer_initialize(txn->transaction_buffer); - sc_list_init(&txn->elements); - return txn; } void sc_transaction_destroy(sc_transaction * txn) { - if (txn != NULL) + if (txn != null_ptr) { - sc_list_clear(txn->elements); + sc_list_destroy(txn->elements); sc_mem_free(txn); } diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index 2143568963..ce9f1aab12 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -15,7 +15,7 @@ typedef struct sc_transaction sc_transaction_buffer * transaction_buffer; } sc_transaction; -sc_transaction * sc_transaction_new(sc_uint64 const * txn_id); +sc_transaction * sc_transaction_new(sc_uint64 txn_id); // create a new transaction void sc_transaction_destroy(sc_transaction * txn); // destroy the given transaction diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c index 74388a8ef7..3e1cdfcdeb 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c @@ -1,6 +1,8 @@ #include "sc_transaction_buffer.h" #include "sc-store/sc-base/sc_monitor_private.h" +#include "sc-store/sc-base/sc_monitor_table.h" +#include "sc-store/sc-base/sc_monitor_table_private.h" #include #include @@ -35,10 +37,20 @@ sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buf return SC_FALSE; } + transaction_buffer->monitor_table = sc_mem_new(sc_monitor_table, 1); + if (transaction_buffer->monitor_table == null_ptr) + { + sc_list_destroy(transaction_buffer->new_elements); + sc_list_destroy(transaction_buffer->modified_elements); + sc_list_destroy(transaction_buffer->deleted_elements); + return SC_FALSE; + } + + _sc_monitor_table_init(transaction_buffer->monitor_table); + return SC_TRUE; } - sc_bool sc_transaction_buffer_created_add(const sc_transaction_buffer * buffer, const sc_addr addr) { if (buffer == null_ptr || buffer->new_elements == null_ptr) @@ -72,13 +84,17 @@ sc_bool sc_transaction_buffer_modified_add( const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); + sc_monitor* monitor = sc_monitor_table_get_monitor_for_addr(buffer->monitor_table, addr); + if (monitor == NULL) + return SC_FALSE; + sc_iterator * it = sc_list_iterator(buffer->modified_elements); while (sc_iterator_next(it)) { sc_modified_element * mod = sc_iterator_get(it); if (SC_ADDR_LOCAL_TO_INT(mod->addr) == addr_hash) { - sc_element_version * new_version = sc_element_create_new_version(element, mod->version->version_id + 1, flags); + sc_element_version * new_version = sc_element_create_new_version(element, monitor->id, flags); if (new_version == NULL) { sc_iterator_destroy(it); @@ -92,6 +108,9 @@ sc_bool sc_transaction_buffer_modified_add( mod->content = content; mod->flags |= flags; // merge field edit flags sc_iterator_destroy(it); + + monitor->id++; + return SC_TRUE; } } @@ -102,7 +121,8 @@ sc_bool sc_transaction_buffer_modified_add( return SC_FALSE; new_mod->addr = addr; - new_mod->version = sc_element_create_new_version(element, 0, flags); + + new_mod->version = sc_element_create_new_version(element, monitor->id, flags); if (new_mod->version == NULL) { sc_mem_free(new_mod); @@ -119,9 +139,12 @@ sc_bool sc_transaction_buffer_modified_add( return SC_FALSE; } + monitor->id++; + return SC_TRUE; } + sc_bool sc_transaction_buffer_removed_add(const sc_transaction_buffer * buffer, const sc_addr addr) { if (buffer == null_ptr || buffer->deleted_elements == null_ptr) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h index e49c14362c..22075db834 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h @@ -4,12 +4,14 @@ #include #include #include +#include typedef struct sc_transaction_buffer { sc_list * new_elements; sc_list * modified_elements; sc_list * deleted_elements; + sc_monitor_table * monitor_table; } sc_transaction_buffer; sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer); From c3e7cb1d64746d4bad99d31d793b9d0e32ff9ada Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Sun, 30 Mar 2025 23:40:54 +0300 Subject: [PATCH 15/51] Refactor --- .../sc-transaction/sc_element_version.c | 2 +- .../sc-transaction/sc_transaction_manager.c | 23 ++++++++++++------- .../units/common/test_sc_transaction_core.cpp | 4 ---- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c index c2fbd02eae..d3a5ff7869 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c @@ -12,7 +12,7 @@ sc_element_version * sc_element_create_new_version(sc_element * element, sc_uint if (new_version == NULL) return NULL; - new_version->data = element; + new_version->data = element; new_version->version_id = version_id; new_version->prev_version = element->versions.tail; new_version->next_version = NULL; diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c index eaa2562efc..df50c4a2c2 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c @@ -12,7 +12,7 @@ sc_transaction_manager * sc_transaction_manager_initialize() } transaction_manager = sc_mem_new(sc_transaction_manager, 1); - if (!sc_transaction_manager_is_initialized()) + if (transaction_manager == null_ptr) { return null_ptr; } @@ -20,21 +20,28 @@ sc_transaction_manager * sc_transaction_manager_initialize() transaction_manager->current_sc_transaction = null_ptr; transaction_manager->transaction_queue = sc_mem_new(sc_queue, 1); - transaction_manager->monitor = sc_mem_new(sc_monitor, 1); - - if (transaction_manager->transaction_queue == NULL || transaction_manager->monitor == NULL) + if (transaction_manager->transaction_queue == null_ptr) { sc_mem_free(transaction_manager); - return NULL; + return null_ptr; } - sc_queue_init(transaction_manager->transaction_queue); + + transaction_manager->monitor = sc_mem_new(sc_monitor, 1); + if (transaction_manager->monitor == null_ptr) + { + sc_mem_free(transaction_manager->transaction_queue); + sc_mem_free(transaction_manager); + return null_ptr; + } sc_monitor_init(transaction_manager->monitor); + transaction_manager->transaction_counter = 0; return transaction_manager; } + sc_bool sc_transaction_manager_is_initialized() { return transaction_manager != null_ptr; @@ -71,10 +78,10 @@ sc_transaction * sc_transaction_manager_transaction_new() } sc_monitor_acquire_write(transaction_manager->monitor); - sc_uint64 const txn_id = transaction_manager->transaction_counter++; + const sc_uint64 txn_id = transaction_manager->transaction_counter++; sc_monitor_release_write(transaction_manager->monitor); - return sc_transaction_new(&txn_id); + return sc_transaction_new(txn_id); } void sc_transaction_manager_transaction_add(sc_transaction * txn) {} diff --git a/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp b/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp index f5593d8ad1..9ea4e7aa60 100644 --- a/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp +++ b/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp @@ -13,10 +13,6 @@ extern "C" #include } -#ifndef null_ptr -# define null_ptr NULL -#endif - class ScTransactionManagerTest : public ScMemoryTest { protected: From f97767ee931bfaf4b73cfd74ae4969f405d2852a Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Thu, 3 Apr 2025 19:57:43 +0300 Subject: [PATCH 16/51] Linear version history --- .../sc-transaction/sc_element_version.c | 25 ++++++------ .../sc-transaction/sc_element_version.h | 38 ++++++++++--------- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c index d3a5ff7869..3c9ef87a16 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c @@ -1,30 +1,27 @@ #include "sc_element_version.h" -#include #include -sc_element_version * sc_element_create_new_version(sc_element * element, sc_uint64 version_id, sc_type modified_fields) +sc_element_version *sc_element_create_new_version( + sc_element_version *parent, + const sc_element *new_element_data, + const sc_uint64 version_id, + const sc_uint64 transaction_id, + const SC_ELEMENT_MODIFIED_FLAGS modified_fields) { - if (element == NULL) + if (new_element_data == NULL) return NULL; - sc_element_version * new_version = sc_mem_new(sc_element_version, 1); + sc_element_version *new_version = sc_mem_new(sc_element_version, 1); if (new_version == NULL) return NULL; - new_version->data = element; + new_version->data = new_element_data; new_version->version_id = version_id; - new_version->prev_version = element->versions.tail; - new_version->next_version = NULL; + new_version->transaction_id = transaction_id; + new_version->parent_version = parent; new_version->is_committed = SC_FALSE; new_version->modified_fields = modified_fields; - if (element->versions.tail) - element->versions.tail->next_version = new_version; - else - element->versions.head = new_version; - - element->versions.tail = new_version; - return new_version; } diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h index e7125e8968..35f847d019 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h @@ -3,22 +3,6 @@ #include -typedef struct sc_element_version -{ - sc_element* data; - sc_uint64 version_id; - struct sc_element_version * prev_version; - struct sc_element_version * next_version; - sc_bool is_committed; - sc_type modified_fields; -} sc_element_version; - -typedef struct sc_version_chain -{ - sc_element_version * head; - sc_element_version * tail; -} sc_version_chain; - typedef enum { SC_ELEMENT_FLAGS_MODIFIED = 1 << 0, @@ -27,6 +11,26 @@ typedef enum SC_ELEMENT_LINKS_MODIFIED = 1 << 3 } SC_ELEMENT_MODIFIED_FLAGS; -sc_element_version * sc_element_create_new_version(sc_element * element, sc_uint64 version_id, sc_type modified_fields); +typedef struct sc_element_version +{ + const sc_element* data; + sc_uint64 version_id; + sc_uint64 transaction_id; + struct sc_element_version *parent_version; + sc_bool is_committed; + SC_ELEMENT_MODIFIED_FLAGS modified_fields; +} sc_element_version; + +typedef struct sc_version_history +{ + sc_element_version *latest_version; +} sc_version_history; + +sc_element_version * sc_element_create_new_version( + sc_element_version *parent, + const sc_element *new_element_data, + sc_uint64 version_id, + sc_uint64 transaction_id, + SC_ELEMENT_MODIFIED_FLAGS modified_fields); #endif From fd3440bbdd843590e82774a7105174881eb077dd Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Thu, 3 Apr 2025 21:33:39 +0300 Subject: [PATCH 17/51] Transaction buffer operations, refactor --- .../sc-store/sc-transaction/sc_transaction.c | 50 +++++- .../sc-store/sc-transaction/sc_transaction.h | 12 +- .../sc-transaction/sc_transaction_buffer.c | 145 ++++++++------- .../sc-transaction/sc_transaction_buffer.h | 18 +- sc-memory/sc-core/src/sc-store/sc_element.h | 2 +- .../units/common/test_sc_transaction_core.cpp | 169 ------------------ .../units/transaction/test_sc_buffer.cpp | 0 .../units/transaction/test_sc_transaction.cpp | 0 8 files changed, 140 insertions(+), 256 deletions(-) delete mode 100644 sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp create mode 100644 sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp create mode 100644 sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index ce79a28c32..91547904f0 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -1,5 +1,8 @@ #include "sc_transaction.h" +#include "sc-store/sc_element.h" +#include "sc-store/sc_storage_private.h" + #include sc_transaction * sc_transaction_new(const sc_uint64 txn_id) @@ -17,7 +20,7 @@ sc_transaction * sc_transaction_new(const sc_uint64 txn_id) sc_mem_free(txn); return null_ptr; } - sc_transaction_buffer_initialize(txn->transaction_buffer); + sc_transaction_buffer_initialize(txn->transaction_buffer, txn_id); if(!sc_list_init(&txn->elements)) { @@ -54,16 +57,47 @@ void sc_transaction_apply(sc_transaction * txn) {} void sc_transaction_clear(sc_transaction * txn) {} -sc_bool sc_transaction_element_new(sc_transaction * txn, sc_element * element) {} +sc_bool sc_transaction_element_new(const sc_transaction * txn, const sc_addr * addr) +{ + if (txn == null_ptr || addr == null_ptr || txn->transaction_buffer == null_ptr) + return SC_FALSE; + + return sc_transaction_buffer_created_add(txn->transaction_buffer, addr); +} sc_bool sc_transaction_element_change( - sc_element * element, - sc_transaction * txn, - SC_ELEMENT_MODIFIED_FLAGS modified_flags, - sc_element const * new_data) + const sc_addr * addr, + const sc_transaction * txn, + const SC_ELEMENT_MODIFIED_FLAGS modified_flags, + const sc_element * new_data) { + if (txn == null_ptr || addr == null_ptr || txn->transaction_buffer == null_ptr) + return SC_FALSE; + + if (SC_ADDR_IS_EMPTY(*addr)) + return SC_FALSE; + + return sc_transaction_buffer_modified_add(txn->transaction_buffer, addr, new_data, modified_flags); } -sc_bool sc_transaction_element_remove(sc_transaction * txn, sc_addr addr) {} +sc_bool sc_transaction_element_remove(const sc_transaction * txn, const sc_addr * addr) +{ + if (txn == null_ptr || addr == null_ptr || txn->transaction_buffer == null_ptr) + return SC_FALSE; + + if (SC_ADDR_IS_EMPTY(*addr)) + return SC_FALSE; + + return sc_transaction_buffer_removed_add(txn->transaction_buffer, addr); +} + +sc_bool sc_transaction_element_content_set(const sc_transaction * txn, const sc_addr* addr, const sc_stream * content) +{ + if (txn == null_ptr || addr == null_ptr || content == null_ptr || txn->transaction_buffer == null_ptr) + return SC_FALSE; + + if (SC_ADDR_IS_EMPTY(*addr)) + return SC_FALSE; -sc_bool sc_transaction_element_content_set(sc_transaction * txn, sc_addr addr, sc_stream * content) {} \ No newline at end of file + return sc_transaction_buffer_content_set(txn->transaction_buffer, addr, content); +} \ No newline at end of file diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index ce9f1aab12..51e09c6f6b 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -20,14 +20,14 @@ sc_transaction * sc_transaction_new(sc_uint64 txn_id); void sc_transaction_destroy(sc_transaction * txn); // destroy the given transaction -sc_bool sc_transaction_element_new(sc_transaction * txn, sc_element * element); +sc_bool sc_transaction_element_new(const sc_transaction * txn, const sc_addr* addr); sc_bool sc_transaction_element_change( - sc_element * element, - sc_transaction * txn, + const sc_addr * addr, + const sc_transaction * txn, SC_ELEMENT_MODIFIED_FLAGS modified_flags, - sc_element const * new_data); -sc_bool sc_transaction_element_remove(sc_transaction * txn, sc_addr addr); -sc_bool sc_transaction_element_content_set(sc_transaction * txn, sc_addr addr, sc_stream * content); + const sc_element * new_data); +sc_bool sc_transaction_element_remove(const sc_transaction * txn, const sc_addr* addr); +sc_bool sc_transaction_element_content_set(const sc_transaction * txn, const sc_addr* addr, const sc_stream * content); void sc_transaction_commit(sc_transaction * txn); // apply all operations of the transaction on sc-memory diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c index 3e1cdfcdeb..eb67dc4170 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c @@ -1,26 +1,30 @@ #include "sc_transaction_buffer.h" +#include "sc-store/sc_element.h" +#include "sc-store/sc_storage_private.h" #include "sc-store/sc-base/sc_monitor_private.h" #include "sc-store/sc-base/sc_monitor_table.h" #include "sc-store/sc-base/sc_monitor_table_private.h" +#include "sc-store/sc-container/sc_pair.h" #include #include #include #include -typedef struct sc_modified_element { +typedef struct sc_content_version { sc_addr addr; - sc_element_version * version; sc_stream * content; - SC_ELEMENT_MODIFIED_FLAGS flags; -} sc_modified_element; + SC_ELEMENT_MODIFIED_FLAGS SC_ELEMENT_CONTENT_MODIFIED; +} sc_content_version; -sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer) +sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer, sc_uint64 txn_id) { if (transaction_buffer == null_ptr) return SC_FALSE; + transaction_buffer->transaction_id = txn_id; + if (!sc_list_init(&transaction_buffer->new_elements)) return SC_FALSE; @@ -37,30 +41,38 @@ sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buf return SC_FALSE; } + if (!sc_list_init(&transaction_buffer->content_changes)) + { + sc_list_destroy(transaction_buffer->new_elements); + sc_list_destroy(transaction_buffer->modified_elements); + sc_list_destroy(transaction_buffer->deleted_elements); + return SC_FALSE; + } + transaction_buffer->monitor_table = sc_mem_new(sc_monitor_table, 1); if (transaction_buffer->monitor_table == null_ptr) { sc_list_destroy(transaction_buffer->new_elements); sc_list_destroy(transaction_buffer->modified_elements); sc_list_destroy(transaction_buffer->deleted_elements); + sc_list_destroy(transaction_buffer->content_changes); return SC_FALSE; } - _sc_monitor_table_init(transaction_buffer->monitor_table); return SC_TRUE; } -sc_bool sc_transaction_buffer_created_add(const sc_transaction_buffer * buffer, const sc_addr addr) +sc_bool sc_transaction_buffer_created_add(const sc_transaction_buffer * buffer, const sc_addr* addr) { if (buffer == null_ptr || buffer->new_elements == null_ptr) return SC_FALSE; - if (SC_ADDR_IS_EMPTY(addr)) + if (SC_ADDR_IS_EMPTY(*addr)) return SC_FALSE; - const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); - if (transaction_buffer_contains_created(buffer, addr)) + const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); + if (sc_transaction_buffer_contains_created(buffer, addr)) return SC_TRUE; if (sc_list_push_back(buffer->new_elements, (void*)(uintptr_t)addr_hash) == null_ptr) @@ -70,90 +82,65 @@ sc_bool sc_transaction_buffer_created_add(const sc_transaction_buffer * buffer, } sc_bool sc_transaction_buffer_modified_add( - const sc_transaction_buffer * buffer, - const sc_addr addr, - sc_element * element, - sc_stream * content, + const sc_transaction_buffer *buffer, + const sc_addr *addr, + const sc_element *new_element_data, const SC_ELEMENT_MODIFIED_FLAGS flags) { - if (buffer == null_ptr || buffer->modified_elements == null_ptr) + if (buffer == NULL || buffer->modified_elements == NULL) return SC_FALSE; - if (SC_ADDR_IS_EMPTY(addr)) + if (SC_ADDR_IS_EMPTY(*addr)) return SC_FALSE; - const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); + sc_element *element = NULL; + if (sc_storage_get_element_by_addr(*addr, &element) != SC_RESULT_OK || element == NULL) + return SC_FALSE; - sc_monitor* monitor = sc_monitor_table_get_monitor_for_addr(buffer->monitor_table, addr); + sc_monitor *monitor = sc_monitor_table_get_monitor_for_addr(buffer->monitor_table, *addr); if (monitor == NULL) return SC_FALSE; - sc_iterator * it = sc_list_iterator(buffer->modified_elements); - while (sc_iterator_next(it)) - { - sc_modified_element * mod = sc_iterator_get(it); - if (SC_ADDR_LOCAL_TO_INT(mod->addr) == addr_hash) - { - sc_element_version * new_version = sc_element_create_new_version(element, monitor->id, flags); - if (new_version == NULL) - { - sc_iterator_destroy(it); - return SC_FALSE; - } - - new_version->prev_version = mod->version; - mod->version->next_version = new_version; - - mod->version = new_version; - mod->content = content; - mod->flags |= flags; // merge field edit flags - sc_iterator_destroy(it); + sc_monitor_acquire_write(monitor); - monitor->id++; + const sc_uint64 new_version_id = (element->version_history.latest_version != NULL) + ? (element->version_history.latest_version->version_id + 1) + : 0; - return SC_TRUE; - } - } - sc_iterator_destroy(it); + sc_element_version *new_version = sc_element_create_new_version( + element->version_history.latest_version, new_element_data, new_version_id, buffer->transaction_id, flags); - sc_modified_element * new_mod = sc_mem_new(sc_modified_element, 1); - if (new_mod == null_ptr) - return SC_FALSE; - - new_mod->addr = addr; - - new_mod->version = sc_element_create_new_version(element, monitor->id, flags); - if (new_mod->version == NULL) + if (new_version == NULL) { - sc_mem_free(new_mod); + sc_monitor_release_write(monitor); return SC_FALSE; } - new_mod->content = content; - new_mod->flags = flags; + element->version_history.latest_version = new_version; + + monitor->id++; - if (sc_list_push_back(buffer->modified_elements, new_mod) == null_ptr) + const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); + if (sc_list_push_back(buffer->modified_elements, (void *)(uintptr_t)addr_hash) == NULL) { - sc_mem_free(new_mod->version); - sc_mem_free(new_mod); + sc_monitor_release_write(monitor); return SC_FALSE; } - monitor->id++; + sc_monitor_release_write(monitor); return SC_TRUE; } - -sc_bool sc_transaction_buffer_removed_add(const sc_transaction_buffer * buffer, const sc_addr addr) +sc_bool sc_transaction_buffer_removed_add(const sc_transaction_buffer * buffer, const sc_addr* addr) { if (buffer == null_ptr || buffer->deleted_elements == null_ptr) return SC_FALSE; - if (SC_ADDR_IS_EMPTY(addr)) + if (SC_ADDR_IS_EMPTY(*addr)) return SC_FALSE; - const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); + const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); sc_iterator * it = sc_list_iterator(buffer->deleted_elements); while (sc_iterator_next(it)) @@ -173,13 +160,43 @@ sc_bool sc_transaction_buffer_removed_add(const sc_transaction_buffer * buffer, return SC_TRUE; } +sc_bool sc_transaction_buffer_content_set(const sc_transaction_buffer * buffer, const sc_addr* addr, const sc_stream * content) +{ + if (buffer == null_ptr || buffer->new_elements == null_ptr) + return SC_FALSE; + + if (SC_ADDR_IS_EMPTY(*addr)) + return SC_FALSE; + + const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); + + sc_iterator * it = sc_list_iterator(buffer->content_changes); + while (sc_iterator_next(it)) + { + sc_pair* pair = sc_iterator_get(it); + const sc_uint32 stored_hash = (uintptr_t)pair->first; + if (stored_hash == addr_hash) + { + pair->second = (void*)content; + sc_iterator_destroy(it); + return SC_TRUE; + } + } + sc_iterator_destroy(it); + + const sc_pair* content_pair = sc_make_pair((void*)addr_hash, (void*)content); + if (sc_list_push_back(buffer->content_changes, &content_pair) == null_ptr) + return SC_FALSE; + + return SC_TRUE; +} -sc_bool transaction_buffer_contains_created(sc_transaction_buffer const * buffer, sc_addr addr) +sc_bool sc_transaction_buffer_contains_created(sc_transaction_buffer const * buffer, const sc_addr* addr) { if (buffer == null_ptr || buffer->new_elements == null_ptr) return SC_FALSE; - const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); + const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); sc_iterator * it = sc_list_iterator(buffer->new_elements); while (sc_iterator_next(it)) { diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h index 22075db834..311343af51 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h @@ -11,20 +11,22 @@ typedef struct sc_transaction_buffer sc_list * new_elements; sc_list * modified_elements; sc_list * deleted_elements; + sc_list * content_changes; sc_monitor_table * monitor_table; + sc_uint64 transaction_id; } sc_transaction_buffer; -sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer); +sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer, sc_uint64 txn_id); -sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer * buffer, sc_addr addr); +sc_bool sc_transaction_buffer_created_add(const sc_transaction_buffer * buffer, const sc_addr* addr); sc_bool sc_transaction_buffer_modified_add( - sc_transaction_buffer * buffer, - sc_addr addr, - sc_element * element, - sc_stream * content, + const sc_transaction_buffer * buffer, + const sc_addr* addr, + const sc_element * element, SC_ELEMENT_MODIFIED_FLAGS flags); -sc_bool sc_transaction_buffer_removed_add(sc_transaction_buffer * buffer, sc_addr addr); +sc_bool sc_transaction_buffer_removed_add(const sc_transaction_buffer * buffer, const sc_addr* addr); +sc_bool sc_transaction_buffer_content_set(const sc_transaction_buffer * buffer, const sc_addr* addr, const sc_stream * content); -sc_bool transaction_buffer_contains_created(sc_transaction_buffer const * buffer, sc_addr addr); +sc_bool sc_transaction_buffer_contains_created(const sc_transaction_buffer * buffer, const sc_addr* addr); #endif diff --git a/sc-memory/sc-core/src/sc-store/sc_element.h b/sc-memory/sc-core/src/sc-store/sc_element.h index fd9c6ad7c5..aab8408653 100644 --- a/sc-memory/sc-core/src/sc-store/sc_element.h +++ b/sc-memory/sc-core/src/sc-store/sc_element.h @@ -66,7 +66,7 @@ struct _sc_element sc_uint32 incoming_arcs_count; sc_uint32 outgoing_arcs_count; - sc_version_chain versions; + sc_version_history version_history; }; #endif diff --git a/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp b/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp deleted file mode 100644 index 9ea4e7aa60..0000000000 --- a/sc-memory/sc-core/tests/units/common/test_sc_transaction_core.cpp +++ /dev/null @@ -1,169 +0,0 @@ -#include -#include - -extern "C" -{ -#include -#include -#include -#include -#include -#include -#include -#include -} - -class ScTransactionManagerTest : public ScMemoryTest -{ -protected: - void SetUp() override - { - ScMemoryTest::Initialize(); - m_ctx = std::make_unique(); - - sc_transaction_manager_initialize(); - } - - void TearDown() override - { - sc_transaction_shutdown(); - - if (m_ctx) - m_ctx->Destroy(); - - ScMemoryTest::Shutdown(); - } -}; - -TEST_F(ScTransactionManagerTest, InitializationTest) -{ - EXPECT_TRUE(sc_transaction_manager_is_initialized()); -} - -TEST_F(ScTransactionManagerTest, TransactionCreationTest) -{ - sc_transaction * txn = sc_transaction_manager_transaction_new(); - ASSERT_NE(txn, null_ptr) << "Transaction creation failed"; - EXPECT_EQ(txn->transaction_id, 0u); - sc_transaction_destroy(txn); -} - -TEST_F(ScTransactionManagerTest, TransactionCounterIncrementsTest) -{ - sc_transaction * txn1 = sc_transaction_manager_transaction_new(); - sc_transaction * txn2 = sc_transaction_manager_transaction_new(); - ASSERT_NE(txn1, null_ptr); - ASSERT_NE(txn2, null_ptr); - EXPECT_EQ(txn1->transaction_id, 0u); - EXPECT_EQ(txn2->transaction_id, 1u); - sc_transaction_destroy(txn1); - sc_transaction_destroy(txn2); -} - -TEST_F(ScTransactionManagerTest, ShutdownTest) -{ - sc_transaction_shutdown(); - EXPECT_FALSE(sc_transaction_manager_is_initialized()); -} - -TEST_F(ScTransactionManagerTest, TransactionBufferInitializationTest) -{ - sc_transaction * txn = sc_transaction_manager_transaction_new(); - ASSERT_NE(txn, null_ptr); - - ASSERT_NE(txn->transaction_buffer, null_ptr); - ASSERT_NE(txn->transaction_buffer->new_elements, null_ptr); - ASSERT_NE(txn->transaction_buffer->modified_elements, null_ptr); - ASSERT_NE(txn->transaction_buffer->deleted_elements, null_ptr); - - EXPECT_EQ(txn->transaction_buffer->new_elements->size, 0u); - EXPECT_EQ(txn->transaction_buffer->modified_elements->size, 0u); - EXPECT_EQ(txn->transaction_buffer->deleted_elements->size, 0u); - - sc_transaction_destroy(txn); -} - -TEST_F(ScTransactionManagerTest, TransactionMemoryCleanupTest) -{ - sc_transaction * txn = sc_transaction_manager_transaction_new(); - ASSERT_NE(txn, null_ptr); - - sc_element elem = {0}; - sc_list_push_back(txn->transaction_buffer->new_elements, &elem); - sc_list_push_back(txn->transaction_buffer->modified_elements, &elem); - sc_list_push_back(txn->transaction_buffer->deleted_elements, &elem); - - sc_transaction_destroy(txn); -} - -TEST_F(ScTransactionManagerTest, InvalidTransactionCreationTest) -{ - sc_transaction_shutdown(); - sc_transaction * txn = sc_transaction_manager_transaction_new(); - EXPECT_EQ(txn, null_ptr); - sc_transaction_manager_initialize(); -} - -TEST_F(ScTransactionManagerTest, TransactionIdSequenceTest) -{ - constexpr sc_uint32 iterations = 100; - sc_transaction * txns[iterations]; - for (sc_uint32 i = 0; i < iterations; ++i) - { - txns[i] = sc_transaction_manager_transaction_new(); - ASSERT_NE(txns[i], null_ptr); - EXPECT_EQ(txns[i]->transaction_id, i); - } - for (sc_uint32 i = 0; i < iterations; ++i) - sc_transaction_destroy(txns[i]); -} - -TEST_F(ScTransactionManagerTest, AddCreatedElementSuccess) -{ - sc_transaction * txn = sc_transaction_manager_transaction_new(); - ASSERT_NE(txn, null_ptr); - - sc_addr const & addr = sc_storage_node_new(m_ctx.get()->GetRealContext(), sc_type_const_node); - - EXPECT_TRUE(sc_transaction_buffer_created_add(txn->transaction_buffer, addr)); - EXPECT_EQ(txn->transaction_buffer->new_elements->size, 1u); - - sc_struct_node * node = sc_list_front(txn->transaction_buffer->new_elements); - ASSERT_NE(node, null_ptr); - - sc_addr const * stored_addr = static_cast(node->data); - ASSERT_NE(stored_addr, null_ptr); - - EXPECT_EQ(stored_addr->seg, addr.seg); - EXPECT_EQ(stored_addr->offset, addr.offset); - - sc_transaction_destroy(txn); -} - -TEST_F(ScTransactionManagerTest, AddCreatedDuplicateElement) -{ - sc_transaction * txn = sc_transaction_manager_transaction_new(); - ASSERT_NE(txn, null_ptr); - - sc_addr const & addr = sc_storage_node_new(m_ctx.get()->GetRealContext(), sc_type_const_node); - - EXPECT_TRUE(sc_transaction_buffer_created_add(txn->transaction_buffer, addr)); - EXPECT_TRUE(sc_transaction_buffer_created_add(txn->transaction_buffer, addr)); - EXPECT_EQ(txn->transaction_buffer->new_elements->size, 1u); - - sc_transaction_destroy(txn); -} - -TEST_F(ScTransactionManagerTest, AddCreatedInvalidAddress) -{ - sc_transaction * txn = sc_transaction_manager_transaction_new(); - ASSERT_NE(txn, null_ptr); - - EXPECT_FALSE(sc_transaction_buffer_created_add(txn->transaction_buffer, SC_ADDR_EMPTY)); - EXPECT_FALSE(sc_transaction_buffer_created_add(static_cast null_ptr, SC_ADDR_EMPTY)); - - if (txn->transaction_buffer->new_elements) - EXPECT_EQ(txn->transaction_buffer->new_elements->size, 0u); - - sc_transaction_destroy(txn); -} diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp new file mode 100644 index 0000000000..e69de29bb2 From 8e01f6308fb375485010fad2e95cd4fca09ac1b6 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Sat, 5 Apr 2025 18:59:47 +0300 Subject: [PATCH 18/51] Add txn buffer tests, format code, refactor --- .../sc-transaction/sc_element_version.c | 20 ++-- .../sc-transaction/sc_element_version.h | 16 ++-- .../sc-store/sc-transaction/sc_transaction.c | 16 ++-- .../sc-store/sc-transaction/sc_transaction.h | 12 +-- .../sc-transaction/sc_transaction_buffer.c | 76 ++++++++------- .../sc-transaction/sc_transaction_buffer.h | 17 ++-- .../sc-transaction/sc_transaction_manager.c | 3 +- sc-memory/sc-core/tests/CMakeLists.txt | 10 ++ .../units/transaction/test_sc_buffer.cpp | 96 +++++++++++++++++++ 9 files changed, 188 insertions(+), 78 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c index 3c9ef87a16..d1a718a406 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c @@ -2,19 +2,19 @@ #include -sc_element_version *sc_element_create_new_version( - sc_element_version *parent, - const sc_element *new_element_data, - const sc_uint64 version_id, - const sc_uint64 transaction_id, +sc_element_version * sc_element_create_new_version( + sc_element_version * parent, + sc_element const * new_element_data, + sc_uint64 const version_id, + sc_uint64 const transaction_id, const SC_ELEMENT_MODIFIED_FLAGS modified_fields) { - if (new_element_data == NULL) - return NULL; + if (new_element_data == null_ptr) + return null_ptr; - sc_element_version *new_version = sc_mem_new(sc_element_version, 1); - if (new_version == NULL) - return NULL; + sc_element_version * new_version = sc_mem_new(sc_element_version, 1); + if (new_version == null_ptr) + return null_ptr; new_version->data = new_element_data; new_version->version_id = version_id; diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h index 35f847d019..1af234d370 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h @@ -13,24 +13,24 @@ typedef enum typedef struct sc_element_version { - const sc_element* data; + sc_element const * data; sc_uint64 version_id; sc_uint64 transaction_id; - struct sc_element_version *parent_version; + struct sc_element_version * parent_version; sc_bool is_committed; SC_ELEMENT_MODIFIED_FLAGS modified_fields; } sc_element_version; typedef struct sc_version_history { - sc_element_version *latest_version; + sc_element_version * latest_version; } sc_version_history; sc_element_version * sc_element_create_new_version( - sc_element_version *parent, - const sc_element *new_element_data, - sc_uint64 version_id, - sc_uint64 transaction_id, - SC_ELEMENT_MODIFIED_FLAGS modified_fields); + sc_element_version * parent, + sc_element const * new_element_data, + sc_uint64 version_id, + sc_uint64 transaction_id, + SC_ELEMENT_MODIFIED_FLAGS modified_fields); #endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index 91547904f0..b7b84e2df7 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -5,7 +5,7 @@ #include -sc_transaction * sc_transaction_new(const sc_uint64 txn_id) +sc_transaction * sc_transaction_new(sc_uint64 const txn_id) { sc_transaction * txn = sc_mem_new(sc_transaction, 1); if (txn == null_ptr) @@ -22,7 +22,7 @@ sc_transaction * sc_transaction_new(const sc_uint64 txn_id) } sc_transaction_buffer_initialize(txn->transaction_buffer, txn_id); - if(!sc_list_init(&txn->elements)) + if (!sc_list_init(&txn->elements)) { return null_ptr; } @@ -57,7 +57,7 @@ void sc_transaction_apply(sc_transaction * txn) {} void sc_transaction_clear(sc_transaction * txn) {} -sc_bool sc_transaction_element_new(const sc_transaction * txn, const sc_addr * addr) +sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_addr const * addr) { if (txn == null_ptr || addr == null_ptr || txn->transaction_buffer == null_ptr) return SC_FALSE; @@ -66,10 +66,10 @@ sc_bool sc_transaction_element_new(const sc_transaction * txn, const sc_addr * a } sc_bool sc_transaction_element_change( - const sc_addr * addr, - const sc_transaction * txn, + sc_addr const * addr, + sc_transaction const * txn, const SC_ELEMENT_MODIFIED_FLAGS modified_flags, - const sc_element * new_data) + sc_element const * new_data) { if (txn == null_ptr || addr == null_ptr || txn->transaction_buffer == null_ptr) return SC_FALSE; @@ -80,7 +80,7 @@ sc_bool sc_transaction_element_change( return sc_transaction_buffer_modified_add(txn->transaction_buffer, addr, new_data, modified_flags); } -sc_bool sc_transaction_element_remove(const sc_transaction * txn, const sc_addr * addr) +sc_bool sc_transaction_element_remove(sc_transaction const * txn, sc_addr const * addr) { if (txn == null_ptr || addr == null_ptr || txn->transaction_buffer == null_ptr) return SC_FALSE; @@ -91,7 +91,7 @@ sc_bool sc_transaction_element_remove(const sc_transaction * txn, const sc_addr return sc_transaction_buffer_removed_add(txn->transaction_buffer, addr); } -sc_bool sc_transaction_element_content_set(const sc_transaction * txn, const sc_addr* addr, const sc_stream * content) +sc_bool sc_transaction_element_content_set(sc_transaction const * txn, sc_addr const * addr, sc_stream const * content) { if (txn == null_ptr || addr == null_ptr || content == null_ptr || txn->transaction_buffer == null_ptr) return SC_FALSE; diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index 51e09c6f6b..a5c3d90d62 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -20,14 +20,14 @@ sc_transaction * sc_transaction_new(sc_uint64 txn_id); void sc_transaction_destroy(sc_transaction * txn); // destroy the given transaction -sc_bool sc_transaction_element_new(const sc_transaction * txn, const sc_addr* addr); +sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_addr const * addr); sc_bool sc_transaction_element_change( - const sc_addr * addr, - const sc_transaction * txn, + sc_addr const * addr, + sc_transaction const * txn, SC_ELEMENT_MODIFIED_FLAGS modified_flags, - const sc_element * new_data); -sc_bool sc_transaction_element_remove(const sc_transaction * txn, const sc_addr* addr); -sc_bool sc_transaction_element_content_set(const sc_transaction * txn, const sc_addr* addr, const sc_stream * content); + sc_element const * new_data); +sc_bool sc_transaction_element_remove(sc_transaction const * txn, sc_addr const * addr); +sc_bool sc_transaction_element_content_set(sc_transaction const * txn, sc_addr const * addr, sc_stream const * content); void sc_transaction_commit(sc_transaction * txn); // apply all operations of the transaction on sc-memory diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c index eb67dc4170..85cbca5157 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c @@ -12,10 +12,11 @@ #include #include -typedef struct sc_content_version { - sc_addr addr; - sc_stream * content; - SC_ELEMENT_MODIFIED_FLAGS SC_ELEMENT_CONTENT_MODIFIED; +typedef struct sc_content_version +{ + sc_addr addr; + sc_stream * content; + SC_ELEMENT_MODIFIED_FLAGS SC_ELEMENT_CONTENT_MODIFIED; } sc_content_version; sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer, sc_uint64 txn_id) @@ -63,7 +64,7 @@ sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buf return SC_TRUE; } -sc_bool sc_transaction_buffer_created_add(const sc_transaction_buffer * buffer, const sc_addr* addr) +sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer const * buffer, sc_addr const * addr) { if (buffer == null_ptr || buffer->new_elements == null_ptr) return SC_FALSE; @@ -71,46 +72,46 @@ sc_bool sc_transaction_buffer_created_add(const sc_transaction_buffer * buffer, if (SC_ADDR_IS_EMPTY(*addr)) return SC_FALSE; - const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); + sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); if (sc_transaction_buffer_contains_created(buffer, addr)) return SC_TRUE; - if (sc_list_push_back(buffer->new_elements, (void*)(uintptr_t)addr_hash) == null_ptr) + if (sc_list_push_back(buffer->new_elements, (void *)(uintptr_t)addr_hash) == null_ptr) return SC_FALSE; return SC_TRUE; } sc_bool sc_transaction_buffer_modified_add( - const sc_transaction_buffer *buffer, - const sc_addr *addr, - const sc_element *new_element_data, + sc_transaction_buffer const * buffer, + sc_addr const * addr, + sc_element const * new_element_data, const SC_ELEMENT_MODIFIED_FLAGS flags) { - if (buffer == NULL || buffer->modified_elements == NULL) + if (buffer == null_ptr || buffer->modified_elements == null_ptr) return SC_FALSE; if (SC_ADDR_IS_EMPTY(*addr)) return SC_FALSE; - sc_element *element = NULL; - if (sc_storage_get_element_by_addr(*addr, &element) != SC_RESULT_OK || element == NULL) + sc_element * element = null_ptr; + if (sc_storage_get_element_by_addr(*addr, &element) != SC_RESULT_OK || element == null_ptr) return SC_FALSE; - sc_monitor *monitor = sc_monitor_table_get_monitor_for_addr(buffer->monitor_table, *addr); - if (monitor == NULL) + sc_monitor * monitor = sc_monitor_table_get_monitor_for_addr(buffer->monitor_table, *addr); + if (monitor == null_ptr) return SC_FALSE; sc_monitor_acquire_write(monitor); - const sc_uint64 new_version_id = (element->version_history.latest_version != NULL) - ? (element->version_history.latest_version->version_id + 1) - : 0; + sc_uint64 const new_version_id = (element->version_history.latest_version != null_ptr) + ? (element->version_history.latest_version->version_id + 1) + : 0; - sc_element_version *new_version = sc_element_create_new_version( + sc_element_version * new_version = sc_element_create_new_version( element->version_history.latest_version, new_element_data, new_version_id, buffer->transaction_id, flags); - if (new_version == NULL) + if (new_version == null_ptr) { sc_monitor_release_write(monitor); return SC_FALSE; @@ -120,8 +121,8 @@ sc_bool sc_transaction_buffer_modified_add( monitor->id++; - const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); - if (sc_list_push_back(buffer->modified_elements, (void *)(uintptr_t)addr_hash) == NULL) + sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); + if (sc_list_push_back(buffer->modified_elements, (void *)(uintptr_t)addr_hash) == null_ptr) { sc_monitor_release_write(monitor); return SC_FALSE; @@ -132,7 +133,7 @@ sc_bool sc_transaction_buffer_modified_add( return SC_TRUE; } -sc_bool sc_transaction_buffer_removed_add(const sc_transaction_buffer * buffer, const sc_addr* addr) +sc_bool sc_transaction_buffer_removed_add(sc_transaction_buffer const * buffer, sc_addr const * addr) { if (buffer == null_ptr || buffer->deleted_elements == null_ptr) return SC_FALSE; @@ -140,12 +141,12 @@ sc_bool sc_transaction_buffer_removed_add(const sc_transaction_buffer * buffer, if (SC_ADDR_IS_EMPTY(*addr)) return SC_FALSE; - const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); + sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); sc_iterator * it = sc_list_iterator(buffer->deleted_elements); while (sc_iterator_next(it)) { - const sc_uint32 stored_hash = (uintptr_t)sc_iterator_get(it); + sc_uint32 const stored_hash = (uintptr_t)sc_iterator_get(it); if (stored_hash == addr_hash) { sc_iterator_destroy(it); @@ -154,13 +155,16 @@ sc_bool sc_transaction_buffer_removed_add(const sc_transaction_buffer * buffer, } sc_iterator_destroy(it); - if (sc_list_push_back(buffer->deleted_elements, (void*)(uintptr_t)addr_hash) == null_ptr) + if (sc_list_push_back(buffer->deleted_elements, (void *)(uintptr_t)addr_hash) == null_ptr) return SC_FALSE; return SC_TRUE; } -sc_bool sc_transaction_buffer_content_set(const sc_transaction_buffer * buffer, const sc_addr* addr, const sc_stream * content) +sc_bool sc_transaction_buffer_content_set( + sc_transaction_buffer const * buffer, + sc_addr const * addr, + sc_stream const * content) { if (buffer == null_ptr || buffer->new_elements == null_ptr) return SC_FALSE; @@ -168,39 +172,39 @@ sc_bool sc_transaction_buffer_content_set(const sc_transaction_buffer * buffer, if (SC_ADDR_IS_EMPTY(*addr)) return SC_FALSE; - const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); + sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); sc_iterator * it = sc_list_iterator(buffer->content_changes); while (sc_iterator_next(it)) { - sc_pair* pair = sc_iterator_get(it); - const sc_uint32 stored_hash = (uintptr_t)pair->first; + sc_pair * pair = sc_iterator_get(it); + sc_uint32 const stored_hash = (uintptr_t)pair->first; if (stored_hash == addr_hash) { - pair->second = (void*)content; + pair->second = (void *)content; sc_iterator_destroy(it); return SC_TRUE; } } sc_iterator_destroy(it); - const sc_pair* content_pair = sc_make_pair((void*)addr_hash, (void*)content); + sc_pair const * content_pair = sc_make_pair((void *)(uintptr_t)addr_hash, (void *)content); if (sc_list_push_back(buffer->content_changes, &content_pair) == null_ptr) return SC_FALSE; return SC_TRUE; } -sc_bool sc_transaction_buffer_contains_created(sc_transaction_buffer const * buffer, const sc_addr* addr) +sc_bool sc_transaction_buffer_contains_created(sc_transaction_buffer const * buffer, sc_addr const * addr) { if (buffer == null_ptr || buffer->new_elements == null_ptr) return SC_FALSE; - const sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); + sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); sc_iterator * it = sc_list_iterator(buffer->new_elements); while (sc_iterator_next(it)) { - const sc_uint32 stored_hash = (uintptr_t)sc_iterator_get(it); + sc_uint32 const stored_hash = (uintptr_t)sc_iterator_get(it); if (stored_hash == addr_hash) { sc_iterator_destroy(it); @@ -211,5 +215,3 @@ sc_bool sc_transaction_buffer_contains_created(sc_transaction_buffer const * buf return SC_FALSE; } - - diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h index 311343af51..294579ac9b 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h @@ -18,15 +18,18 @@ typedef struct sc_transaction_buffer sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer, sc_uint64 txn_id); -sc_bool sc_transaction_buffer_created_add(const sc_transaction_buffer * buffer, const sc_addr* addr); +sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer const * buffer, sc_addr const * addr); sc_bool sc_transaction_buffer_modified_add( - const sc_transaction_buffer * buffer, - const sc_addr* addr, - const sc_element * element, + sc_transaction_buffer const * buffer, + sc_addr const * addr, + sc_element const * element, SC_ELEMENT_MODIFIED_FLAGS flags); -sc_bool sc_transaction_buffer_removed_add(const sc_transaction_buffer * buffer, const sc_addr* addr); -sc_bool sc_transaction_buffer_content_set(const sc_transaction_buffer * buffer, const sc_addr* addr, const sc_stream * content); +sc_bool sc_transaction_buffer_removed_add(sc_transaction_buffer const * buffer, sc_addr const * addr); +sc_bool sc_transaction_buffer_content_set( + sc_transaction_buffer const * buffer, + sc_addr const * addr, + sc_stream const * content); -sc_bool sc_transaction_buffer_contains_created(const sc_transaction_buffer * buffer, const sc_addr* addr); +sc_bool sc_transaction_buffer_contains_created(sc_transaction_buffer const * buffer, sc_addr const * addr); #endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c index df50c4a2c2..9177431053 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c @@ -41,7 +41,6 @@ sc_transaction_manager * sc_transaction_manager_initialize() return transaction_manager; } - sc_bool sc_transaction_manager_is_initialized() { return transaction_manager != null_ptr; @@ -78,7 +77,7 @@ sc_transaction * sc_transaction_manager_transaction_new() } sc_monitor_acquire_write(transaction_manager->monitor); - const sc_uint64 txn_id = transaction_manager->transaction_counter++; + sc_uint64 const txn_id = transaction_manager->transaction_counter++; sc_monitor_release_write(transaction_manager->monitor); return sc_transaction_new(txn_id); diff --git a/sc-memory/sc-core/tests/CMakeLists.txt b/sc-memory/sc-core/tests/CMakeLists.txt index 103c64e897..093a02e0bd 100644 --- a/sc-memory/sc-core/tests/CMakeLists.txt +++ b/sc-memory/sc-core/tests/CMakeLists.txt @@ -29,3 +29,13 @@ make_tests_from_folder(${CMAKE_CURRENT_SOURCE_DIR}/units/fs-storage if(${SC_CLANG_FORMAT_CODE}) target_clangformat_setup(sc-core-fs-storage-tests) endif() + +make_tests_from_folder(${CMAKE_CURRENT_SOURCE_DIR}/units/transaction + NAME sc-core-transaction-tests + DEPENDS ${glib_LIBRARIES} sc-memory + INCLUDES ${glib_INCLUDE_DIRS} ${SC_CORE_SRC} +) + +if(${SC_CLANG_FORMAT_CODE}) + target_clangformat_setup(sc-core-transaction-tests) +endif() \ No newline at end of file diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp index e69de29bb2..b90abbb485 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp @@ -0,0 +1,96 @@ +#include +#include +#include + +extern "C" +{ +#include +#include +#include +#include +#include +#include +#include +#include +} + +class ScTransactionBufferTest : public ScMemoryTest +{ +protected: + sc_transaction_buffer * buffer = sc_mem_new(sc_transaction_buffer, 1); + + void SetUp() override + { + ScMemoryTest::SetUp(); + ASSERT_TRUE(sc_transaction_buffer_initialize(buffer, 1)); + } + + void TearDown() override + { + ScMemoryTest::TearDown(); + } +}; + +TEST_F(ScTransactionBufferTest, InitializationTest) +{ + EXPECT_NE(buffer->new_elements, nullptr); + EXPECT_NE(buffer->modified_elements, nullptr); + EXPECT_NE(buffer->deleted_elements, nullptr); + EXPECT_NE(buffer->content_changes, nullptr); + EXPECT_NE(buffer->monitor_table, nullptr); + EXPECT_EQ(buffer->transaction_id, 1u); +} + +TEST_F(ScTransactionBufferTest, CreatedAddTest) +{ + sc_addr addr = {1, 1}; + + EXPECT_TRUE(sc_transaction_buffer_created_add(buffer, &addr)); + EXPECT_EQ(buffer->new_elements->size, 1u); + + sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(addr); + EXPECT_EQ(buffer->new_elements->begin->data, reinterpret_cast(addr_hash)); + + EXPECT_TRUE(sc_transaction_buffer_contains_created(buffer, &addr)); +} + +TEST_F(ScTransactionBufferTest, RemovedAddTest) +{ + sc_addr addr = {1, 1}; + + EXPECT_TRUE(sc_transaction_buffer_removed_add(buffer, &addr)); + EXPECT_EQ(buffer->deleted_elements->size, 1u); + + sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(addr); + EXPECT_EQ(buffer->deleted_elements->begin->data, reinterpret_cast(addr_hash)); +} + +TEST_F(ScTransactionBufferTest, ModifiedAddTest) +{ + sc_addr * addr = sc_mem_new(sc_addr, 1); + sc_storage_allocate_new_element(m_ctx->GetRealContext(), addr); + + sc_element * element = sc_mem_new(sc_element, 1); + sc_storage_get_element_by_addr(*addr, &element); + + element->incoming_arcs_count++; + + constexpr SC_ELEMENT_MODIFIED_FLAGS flags = SC_ELEMENT_ARCS_MODIFIED; + + EXPECT_TRUE(sc_transaction_buffer_modified_add(buffer, addr, element, flags)); + EXPECT_EQ(buffer->modified_elements->size, 1); + sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); + EXPECT_EQ(buffer->modified_elements->begin->data, reinterpret_cast(addr_hash)); +} + +TEST_F(ScTransactionBufferTest, ContentSetTest) +{ + sc_addr addr = {1, 4}; + sc_stream * stream = sc_stream_memory_new("test", 4, SC_STREAM_FLAG_READ, SC_FALSE); + ASSERT_NE(stream, nullptr); + + EXPECT_TRUE(sc_transaction_buffer_content_set(buffer, &addr, stream)); + EXPECT_EQ(buffer->content_changes->size, 1u); + + sc_stream_free(stream); +} From 96e1c8f00a23da9b4c8b887cb25fd678b49c09a5 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Sat, 5 Apr 2025 21:05:24 +0300 Subject: [PATCH 19/51] Fix txn buffer content save, tests for sc_transaction --- .../sc-transaction/sc_transaction_buffer.c | 4 +- .../units/transaction/test_sc_buffer.cpp | 27 +++- .../units/transaction/test_sc_transaction.cpp | 149 ++++++++++++++++++ 3 files changed, 173 insertions(+), 7 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c index 85cbca5157..7684c06430 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c @@ -166,7 +166,7 @@ sc_bool sc_transaction_buffer_content_set( sc_addr const * addr, sc_stream const * content) { - if (buffer == null_ptr || buffer->new_elements == null_ptr) + if (buffer == null_ptr || buffer->content_changes == null_ptr) return SC_FALSE; if (SC_ADDR_IS_EMPTY(*addr)) @@ -189,7 +189,7 @@ sc_bool sc_transaction_buffer_content_set( sc_iterator_destroy(it); sc_pair const * content_pair = sc_make_pair((void *)(uintptr_t)addr_hash, (void *)content); - if (sc_list_push_back(buffer->content_changes, &content_pair) == null_ptr) + if (sc_list_push_back(buffer->content_changes, (void*)content_pair) == null_ptr) return SC_FALSE; return SC_TRUE; diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp index b90abbb485..eff7010bce 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp @@ -4,6 +4,7 @@ extern "C" { +#include #include #include #include @@ -43,12 +44,12 @@ TEST_F(ScTransactionBufferTest, InitializationTest) TEST_F(ScTransactionBufferTest, CreatedAddTest) { - sc_addr addr = {1, 1}; + constexpr sc_addr addr = {1, 1}; EXPECT_TRUE(sc_transaction_buffer_created_add(buffer, &addr)); EXPECT_EQ(buffer->new_elements->size, 1u); - sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(addr); + constexpr sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); EXPECT_EQ(buffer->new_elements->begin->data, reinterpret_cast(addr_hash)); EXPECT_TRUE(sc_transaction_buffer_contains_created(buffer, &addr)); @@ -85,12 +86,28 @@ TEST_F(ScTransactionBufferTest, ModifiedAddTest) TEST_F(ScTransactionBufferTest, ContentSetTest) { - sc_addr addr = {1, 4}; - sc_stream * stream = sc_stream_memory_new("test", 4, SC_STREAM_FLAG_READ, SC_FALSE); + constexpr sc_addr addr = {1, 4}; + sc_stream* stream = sc_stream_memory_new("test", 4, SC_STREAM_FLAG_READ, SC_FALSE); ASSERT_NE(stream, nullptr); EXPECT_TRUE(sc_transaction_buffer_content_set(buffer, &addr, stream)); EXPECT_EQ(buffer->content_changes->size, 1u); - sc_stream_free(stream); + constexpr sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); + sc_iterator* it = sc_list_iterator(buffer->content_changes); + sc_bool found = SC_FALSE; + + while (sc_iterator_next(it)) + { + sc_pair* pair = static_cast(sc_iterator_get(it)); + if (reinterpret_cast(pair->first) == addr_hash) + { + EXPECT_EQ(pair->second, stream); + found = SC_TRUE; + break; + } + } + sc_iterator_destroy(it); + + EXPECT_TRUE(found); } diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp index e69de29bb2..29fbbf72db 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp @@ -0,0 +1,149 @@ +#include +#include +#include + +extern "C" +{ +#include +#include +#include +#include +} + +class ScTransactionTest : public ScMemoryTest +{ +protected: + sc_transaction* transaction = nullptr; + sc_uint64 const test_txn_id = 123; + + void SetUp() override + { + ScMemoryTest::SetUp(); + transaction = sc_transaction_new(test_txn_id); + ASSERT_NE(transaction, nullptr); + } + + void TearDown() override + { + if (transaction != nullptr) + sc_transaction_destroy(transaction); + ScMemoryTest::TearDown(); + } +}; + +TEST_F(ScTransactionTest, CreationAndDestruction) +{ + EXPECT_EQ(transaction->transaction_id, test_txn_id); + EXPECT_EQ(transaction->is_committed, SC_FALSE); + EXPECT_NE(transaction->transaction_buffer, nullptr); + EXPECT_NE(transaction->elements, nullptr); +} + +TEST_F(ScTransactionTest, TransactionElementNew) +{ + constexpr sc_addr addr = {1, 2}; + + EXPECT_TRUE(sc_transaction_element_new(transaction, &addr)); + EXPECT_TRUE(sc_transaction_buffer_contains_created(transaction->transaction_buffer, &addr)); + + EXPECT_FALSE(sc_transaction_element_new(nullptr, &addr)); + EXPECT_FALSE(sc_transaction_element_new(transaction, nullptr)); + + constexpr sc_addr empty_addr = {0, 0}; + EXPECT_FALSE(sc_transaction_element_new(transaction, &empty_addr)); +} + +TEST_F(ScTransactionTest, TransactionElementChange) +{ + sc_addr addr; + sc_storage_allocate_new_element(m_ctx->GetRealContext(), &addr); + + sc_element element; + element.flags.type = sc_type_node; + + EXPECT_TRUE(sc_transaction_element_change(&addr, transaction, SC_ELEMENT_ARCS_MODIFIED, &element)); + + constexpr sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); + sc_iterator* it = sc_list_iterator(transaction->transaction_buffer->modified_elements); + sc_bool found = SC_FALSE; + while (sc_iterator_next(it)) + { + if (reinterpret_cast(sc_iterator_get(it)) == addr_hash) + { + found = SC_TRUE; + break; + } + } + sc_iterator_destroy(it); + EXPECT_TRUE(found); + + EXPECT_FALSE(sc_transaction_element_change(nullptr, transaction, SC_ELEMENT_ARCS_MODIFIED, &element)); + EXPECT_FALSE(sc_transaction_element_change(&addr, nullptr, SC_ELEMENT_ARCS_MODIFIED, &element)); +} + +TEST_F(ScTransactionTest, TransactionElementRemove) +{ + constexpr sc_addr addr = {3, 4}; + + EXPECT_TRUE(sc_transaction_element_remove(transaction, &addr)); + + constexpr sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); + sc_iterator* it = sc_list_iterator(transaction->transaction_buffer->deleted_elements); + sc_bool found = SC_FALSE; + while (sc_iterator_next(it)) + { + if (reinterpret_cast(sc_iterator_get(it)) == addr_hash) + { + found = SC_TRUE; + break; + } + } + sc_iterator_destroy(it); + EXPECT_TRUE(found); + + EXPECT_FALSE(sc_transaction_element_remove(nullptr, &addr)); + EXPECT_FALSE(sc_transaction_element_remove(transaction, nullptr)); +} + +TEST_F(ScTransactionTest, TransactionElementContentSet) +{ + constexpr sc_addr addr = {5, 6}; + + sc_stream* stream = sc_stream_memory_new("content", 7, SC_STREAM_FLAG_READ, SC_FALSE); + ASSERT_NE(stream, nullptr); + + EXPECT_TRUE(sc_transaction_element_content_set(transaction, &addr, stream)); + + constexpr sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); + sc_iterator* it = sc_list_iterator(transaction->transaction_buffer->content_changes); + sc_bool found = SC_FALSE; + while (sc_iterator_next(it)) + { + sc_pair* pair = static_cast(sc_iterator_get(it)); + if (reinterpret_cast(pair->first) == addr_hash) + { + EXPECT_EQ(pair->second, stream); + found = SC_TRUE; + break; + } + } + sc_iterator_destroy(it); + EXPECT_TRUE(found); + + EXPECT_FALSE(sc_transaction_element_content_set(nullptr, &addr, stream)); + EXPECT_FALSE(sc_transaction_element_content_set(transaction, nullptr, stream)); + EXPECT_FALSE(sc_transaction_element_content_set(transaction, &addr, nullptr)); +} + +TEST_F(ScTransactionTest, TransactionValidation) +{ + EXPECT_FALSE(sc_transaction_validate(transaction)); +} + +TEST_F(ScTransactionTest, TransactionEdgeCases) +{ + sc_transaction_destroy(nullptr); + + sc_transaction* failed_txn = sc_transaction_new(0); + EXPECT_NE(failed_txn, nullptr); +} \ No newline at end of file From af0f29aa2aebd5d78ea25b8b229e198ad822f584 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 9 Apr 2025 21:32:48 +0300 Subject: [PATCH 20/51] Tests fix --- .../tests/units/transaction/test_sc_buffer.cpp | 6 +++--- .../units/transaction/test_sc_transaction.cpp | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp index eff7010bce..40730f5190 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp @@ -87,19 +87,19 @@ TEST_F(ScTransactionBufferTest, ModifiedAddTest) TEST_F(ScTransactionBufferTest, ContentSetTest) { constexpr sc_addr addr = {1, 4}; - sc_stream* stream = sc_stream_memory_new("test", 4, SC_STREAM_FLAG_READ, SC_FALSE); + sc_stream * stream = sc_stream_memory_new("test", 4, SC_STREAM_FLAG_READ, SC_FALSE); ASSERT_NE(stream, nullptr); EXPECT_TRUE(sc_transaction_buffer_content_set(buffer, &addr, stream)); EXPECT_EQ(buffer->content_changes->size, 1u); constexpr sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); - sc_iterator* it = sc_list_iterator(buffer->content_changes); + sc_iterator * it = sc_list_iterator(buffer->content_changes); sc_bool found = SC_FALSE; while (sc_iterator_next(it)) { - sc_pair* pair = static_cast(sc_iterator_get(it)); + sc_pair * pair = static_cast(sc_iterator_get(it)); if (reinterpret_cast(pair->first) == addr_hash) { EXPECT_EQ(pair->second, stream); diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp index 29fbbf72db..740ee62a6e 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp @@ -13,7 +13,7 @@ extern "C" class ScTransactionTest : public ScMemoryTest { protected: - sc_transaction* transaction = nullptr; + sc_transaction * transaction = nullptr; sc_uint64 const test_txn_id = 123; void SetUp() override @@ -63,8 +63,8 @@ TEST_F(ScTransactionTest, TransactionElementChange) EXPECT_TRUE(sc_transaction_element_change(&addr, transaction, SC_ELEMENT_ARCS_MODIFIED, &element)); - constexpr sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); - sc_iterator* it = sc_list_iterator(transaction->transaction_buffer->modified_elements); + sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); + sc_iterator * it = sc_list_iterator(transaction->transaction_buffer->modified_elements); sc_bool found = SC_FALSE; while (sc_iterator_next(it)) { @@ -88,7 +88,7 @@ TEST_F(ScTransactionTest, TransactionElementRemove) EXPECT_TRUE(sc_transaction_element_remove(transaction, &addr)); constexpr sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); - sc_iterator* it = sc_list_iterator(transaction->transaction_buffer->deleted_elements); + sc_iterator * it = sc_list_iterator(transaction->transaction_buffer->deleted_elements); sc_bool found = SC_FALSE; while (sc_iterator_next(it)) { @@ -109,17 +109,17 @@ TEST_F(ScTransactionTest, TransactionElementContentSet) { constexpr sc_addr addr = {5, 6}; - sc_stream* stream = sc_stream_memory_new("content", 7, SC_STREAM_FLAG_READ, SC_FALSE); + sc_stream * stream = sc_stream_memory_new("content", 7, SC_STREAM_FLAG_READ, SC_FALSE); ASSERT_NE(stream, nullptr); EXPECT_TRUE(sc_transaction_element_content_set(transaction, &addr, stream)); constexpr sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); - sc_iterator* it = sc_list_iterator(transaction->transaction_buffer->content_changes); + sc_iterator * it = sc_list_iterator(transaction->transaction_buffer->content_changes); sc_bool found = SC_FALSE; while (sc_iterator_next(it)) { - sc_pair* pair = static_cast(sc_iterator_get(it)); + sc_pair * pair = static_cast(sc_iterator_get(it)); if (reinterpret_cast(pair->first) == addr_hash) { EXPECT_EQ(pair->second, stream); @@ -144,6 +144,6 @@ TEST_F(ScTransactionTest, TransactionEdgeCases) { sc_transaction_destroy(nullptr); - sc_transaction* failed_txn = sc_transaction_new(0); + sc_transaction * failed_txn = sc_transaction_new(0); EXPECT_NE(failed_txn, nullptr); } \ No newline at end of file From ae7903c18169b714e797ecd307137c9e405a2632 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 9 Apr 2025 21:33:47 +0300 Subject: [PATCH 21/51] Transaction manager queue handling --- .../sc-store/sc-transaction/sc_transaction.c | 6 +- .../sc-store/sc-transaction/sc_transaction.h | 2 +- .../sc-transaction/sc_transaction_buffer.c | 2 +- .../sc-transaction/sc_transaction_manager.c | 143 ++++++++++++++++-- .../sc-transaction/sc_transaction_manager.h | 15 +- 5 files changed, 149 insertions(+), 19 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index b7b84e2df7..5308bb7992 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -1,5 +1,6 @@ #include "sc_transaction.h" +#include "sc_transaction_manager.h" #include "sc-store/sc_element.h" #include "sc-store/sc_storage_private.h" @@ -42,7 +43,10 @@ void sc_transaction_destroy(sc_transaction * txn) void sc_transaction_add_element(sc_transaction * txn, sc_element * element) {} -void sc_transaction_commit(sc_transaction * txn) {} +void sc_transaction_commit(sc_transaction * txn) +{ + sc_transaction_manager_transaction_add(txn); +} void sc_transaction_rollback(sc_transaction * txn) {} diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index a5c3d90d62..00dd83e67e 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -30,7 +30,7 @@ sc_bool sc_transaction_element_remove(sc_transaction const * txn, sc_addr const sc_bool sc_transaction_element_content_set(sc_transaction const * txn, sc_addr const * addr, sc_stream const * content); void sc_transaction_commit(sc_transaction * txn); -// apply all operations of the transaction on sc-memory +// try to apply all operations of the transaction on sc-memory void sc_transaction_rollback(sc_transaction * txn); // rollback the transaction operations diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c index 7684c06430..e109331af5 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c @@ -189,7 +189,7 @@ sc_bool sc_transaction_buffer_content_set( sc_iterator_destroy(it); sc_pair const * content_pair = sc_make_pair((void *)(uintptr_t)addr_hash, (void *)content); - if (sc_list_push_back(buffer->content_changes, (void*)content_pair) == null_ptr) + if (sc_list_push_back(buffer->content_changes, (void *)content_pair) == null_ptr) return SC_FALSE; return SC_TRUE; diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c index 9177431053..980e887f55 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c @@ -1,5 +1,8 @@ #include "sc_transaction_manager.h" +#include "sc-store/sc-base/sc_thread.h" +#include "sc-store/sc-container/sc_struct_node.h" + #include sc_transaction_manager * transaction_manager = null_ptr; @@ -17,28 +20,76 @@ sc_transaction_manager * sc_transaction_manager_initialize() return null_ptr; } - transaction_manager->current_sc_transaction = null_ptr; + transaction_manager->should_stop = SC_FALSE; + transaction_manager->transaction_counter = 0; + transaction_manager->threads = null_ptr; transaction_manager->transaction_queue = sc_mem_new(sc_queue, 1); if (transaction_manager->transaction_queue == null_ptr) { - sc_mem_free(transaction_manager); - return null_ptr; + goto error_cleanup_manager; } + sc_queue_init(transaction_manager->transaction_queue); transaction_manager->monitor = sc_mem_new(sc_monitor, 1); if (transaction_manager->monitor == null_ptr) { - sc_mem_free(transaction_manager->transaction_queue); - sc_mem_free(transaction_manager); - return null_ptr; + goto error_cleanup_queue; } + sc_monitor_init(transaction_manager->monitor); - transaction_manager->transaction_counter = 0; + sc_cond_init(transaction_manager->queue_condition); + sc_mutex_init(transaction_manager->mutex); + + if (sc_list_init(&transaction_manager->threads) != SC_RESULT_OK) + { + goto error_cleanup_threads; + } + + for (int i = 0; i < SC_TRANSACTION_THREAD_COUNT; ++i) + { + sc_thread * thread = g_thread_new("sc_transaction_handler", sc_transaction_handler, transaction_manager); + if (thread == null_ptr) + { + goto error_cleanup_threads; + } + sc_list_push_back(transaction_manager->threads, thread); + } return transaction_manager; + +error_cleanup_threads: + if (transaction_manager->threads != null_ptr) + { + for (sc_struct_node const * it = transaction_manager->threads->begin; it != null_ptr; it = it->next) + { + g_thread_unref(it->data); + } + sc_list_destroy(transaction_manager->threads); + transaction_manager->threads = null_ptr; + } + +error_cleanup_mutex: + sc_mutex_destroy(transaction_manager->mutex); + +error_cleanup_condition: + sc_cond_destroy(transaction_manager->queue_condition); + +error_cleanup_monitor: + sc_monitor_destroy(transaction_manager->monitor); + sc_mem_free(transaction_manager->monitor); + +error_cleanup_queue: + sc_queue_destroy(transaction_manager->transaction_queue); + sc_mem_free(transaction_manager->transaction_queue); + +error_cleanup_manager: + sc_mem_free(transaction_manager); + transaction_manager = null_ptr; + + return null_ptr; } sc_bool sc_transaction_manager_is_initialized() @@ -46,29 +97,57 @@ sc_bool sc_transaction_manager_is_initialized() return transaction_manager != null_ptr; } -void sc_transaction_shutdown() +void sc_transaction_shutdown(sc_transaction_manager * manager) { if (transaction_manager != null_ptr) { + manager->should_stop = SC_TRUE; sc_transaction_manager_destroy(); } } void sc_transaction_manager_destroy() { - if (transaction_manager != null_ptr) + if (transaction_manager == null_ptr) + return; + + transaction_manager->should_stop = SC_TRUE; + + sc_cond_broadcast(transaction_manager->queue_condition); + + if (transaction_manager->threads != null_ptr) + { + for (sc_struct_node const * it = transaction_manager->threads->begin; it != null_ptr; it = it->next) + { + g_thread_join(it->data); + g_thread_unref(it->data); + } + sc_list_destroy(transaction_manager->threads); + transaction_manager->threads = null_ptr; + } + + if (transaction_manager->transaction_queue != null_ptr) { - sc_monitor_acquire_write(transaction_manager->monitor); sc_queue_destroy(transaction_manager->transaction_queue); - sc_monitor_release_write(transaction_manager->monitor); + sc_mem_free(transaction_manager->transaction_queue); + transaction_manager->transaction_queue = null_ptr; + } + if (transaction_manager->monitor != null_ptr) + { sc_monitor_destroy(transaction_manager->monitor); - - sc_mem_free(transaction_manager); - transaction_manager = null_ptr; + sc_mem_free(transaction_manager->monitor); + transaction_manager->monitor = null_ptr; } + + sc_cond_destroy(transaction_manager->queue_condition); + sc_mutex_destroy(transaction_manager->mutex); + + sc_mem_free(transaction_manager); + transaction_manager = null_ptr; } + sc_transaction * sc_transaction_manager_transaction_new() { if (!sc_transaction_manager_is_initialized()) @@ -86,3 +165,39 @@ sc_transaction * sc_transaction_manager_transaction_new() void sc_transaction_manager_transaction_add(sc_transaction * txn) {} void sc_transaction_manager_transaction_execute() {} + +void sc_transaction_handler(sc_transaction_manager * manager) +{ + sc_monitor_acquire_read(manager->monitor); + + while (!manager->should_stop) + { + if (manager->transaction_counter == 0) + { + sc_monitor_release_read(manager->monitor); + sc_mutex_lock(manager->mutex); + sc_cond_wait(manager->queue_condition, manager->mutex); + sc_mutex_unlock(manager->mutex); + sc_monitor_acquire_read(manager->monitor); + continue; + } + + sc_monitor_release_read(manager->monitor); + sc_monitor_acquire_write(manager->monitor); + + if (!manager->should_stop && manager->transaction_counter > 0) + { + sc_transaction * txn = sc_queue_front(manager->transaction_queue); + sc_queue_pop(manager->transaction_queue); + manager->transaction_counter--; + + sc_transaction_manager_transaction_execute(txn); + } + + sc_monitor_release_write(manager->monitor); + sc_monitor_acquire_read(manager->monitor); + } + + sc_monitor_release_read(manager->monitor); +} + diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h index c4c1752c78..b660061aa2 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h @@ -4,12 +4,20 @@ #include #include +// TODO: determinate amount +#define SC_TRANSACTION_THREAD_COUNT 2 +#define SC_TRANSACTION_MANAGER_QUEUE_SIZE 10 + typedef struct sc_transaction_manager { - sc_transaction * current_sc_transaction; sc_queue * transaction_queue; sc_monitor * monitor; + sc_mutex * mutex; sc_uint64 transaction_counter; + sc_list * threads; + + sc_condition * queue_condition; + sc_bool should_stop; } sc_transaction_manager; sc_transaction_manager * sc_transaction_manager_initialize(); @@ -24,7 +32,10 @@ sc_transaction * sc_transaction_manager_transaction_new(); void sc_transaction_manager_transaction_add(sc_transaction * txn); // add transaction to the queue and start operations when the thread is ready void sc_transaction_manager_transaction_execute(); -// try to execute the transaction and wait till it's finished +// execute the transaction and wait till it's finished + +void sc_transaction_handler(sc_transaction_manager * manager); +// method for transaction queue processing by threads void sc_transaction_manager_destroy(); // destroy the transaction manager From e6e59d8eaf166dae87967deae773d98b7aadf10e Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Thu, 10 Apr 2025 13:29:08 +0300 Subject: [PATCH 22/51] Use transaction manager as global, transaction queue add, queue handling fix --- .../sc-transaction/sc_transaction_manager.c | 62 +++++++++++-------- .../sc-transaction/sc_transaction_manager.h | 5 +- .../test_sc_transaction_manager.cpp | 0 3 files changed, 38 insertions(+), 29 deletions(-) create mode 100644 sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c index 980e887f55..b7a14f45c2 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c @@ -21,7 +21,6 @@ sc_transaction_manager * sc_transaction_manager_initialize() } transaction_manager->should_stop = SC_FALSE; - transaction_manager->transaction_counter = 0; transaction_manager->threads = null_ptr; transaction_manager->transaction_queue = sc_mem_new(sc_queue, 1); @@ -45,12 +44,12 @@ sc_transaction_manager * sc_transaction_manager_initialize() if (sc_list_init(&transaction_manager->threads) != SC_RESULT_OK) { - goto error_cleanup_threads; + goto error_cleanup_condition; } for (int i = 0; i < SC_TRANSACTION_THREAD_COUNT; ++i) { - sc_thread * thread = g_thread_new("sc_transaction_handler", sc_transaction_handler, transaction_manager); + sc_thread * thread = g_thread_new("sc_transaction_handler", sc_transaction_handler, 0); if (thread == null_ptr) { goto error_cleanup_threads; @@ -97,11 +96,11 @@ sc_bool sc_transaction_manager_is_initialized() return transaction_manager != null_ptr; } -void sc_transaction_shutdown(sc_transaction_manager * manager) +void sc_transaction_shutdown() { if (transaction_manager != null_ptr) { - manager->should_stop = SC_TRUE; + transaction_manager->should_stop = SC_TRUE; sc_transaction_manager_destroy(); } } @@ -156,48 +155,59 @@ sc_transaction * sc_transaction_manager_transaction_new() } sc_monitor_acquire_write(transaction_manager->monitor); - sc_uint64 const txn_id = transaction_manager->transaction_counter++; + sc_uint64 const txn_id = transaction_manager->transaction_queue->size++; sc_monitor_release_write(transaction_manager->monitor); return sc_transaction_new(txn_id); } -void sc_transaction_manager_transaction_add(sc_transaction * txn) {} +void sc_transaction_manager_transaction_add(sc_transaction * txn) +{ + sc_monitor_acquire_write(transaction_manager->monitor); + + sc_queue_push(transaction_manager->transaction_queue, txn); + + sc_monitor_release_write(transaction_manager->monitor); -void sc_transaction_manager_transaction_execute() {} + sc_cond_signal(transaction_manager->queue_condition); +} + +void sc_transaction_manager_transaction_execute(sc_transaction * txn) +{ + +} -void sc_transaction_handler(sc_transaction_manager * manager) +void sc_transaction_handler() { - sc_monitor_acquire_read(manager->monitor); + sc_monitor_acquire_read(transaction_manager->monitor); - while (!manager->should_stop) + while (!transaction_manager->should_stop) { - if (manager->transaction_counter == 0) + if (transaction_manager->transaction_queue->size == 0) { - sc_monitor_release_read(manager->monitor); - sc_mutex_lock(manager->mutex); - sc_cond_wait(manager->queue_condition, manager->mutex); - sc_mutex_unlock(manager->mutex); - sc_monitor_acquire_read(manager->monitor); + sc_monitor_release_read(transaction_manager->monitor); + sc_mutex_lock(transaction_manager->mutex); + sc_cond_wait(transaction_manager->queue_condition, transaction_manager->mutex); + sc_mutex_unlock(transaction_manager->mutex); + sc_monitor_acquire_read(transaction_manager->monitor); continue; } - sc_monitor_release_read(manager->monitor); - sc_monitor_acquire_write(manager->monitor); + sc_monitor_release_read(transaction_manager->monitor); + sc_monitor_acquire_write(transaction_manager->monitor); - if (!manager->should_stop && manager->transaction_counter > 0) + if (!transaction_manager->should_stop && transaction_manager->transaction_queue->size > 0) { - sc_transaction * txn = sc_queue_front(manager->transaction_queue); - sc_queue_pop(manager->transaction_queue); - manager->transaction_counter--; + sc_transaction * txn = sc_queue_front(transaction_manager->transaction_queue); + sc_queue_pop(transaction_manager->transaction_queue); sc_transaction_manager_transaction_execute(txn); } - sc_monitor_release_write(manager->monitor); - sc_monitor_acquire_read(manager->monitor); + sc_monitor_release_write(transaction_manager->monitor); + sc_monitor_acquire_read(transaction_manager->monitor); } - sc_monitor_release_read(manager->monitor); + sc_monitor_release_read(transaction_manager->monitor); } diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h index b660061aa2..ebafa41476 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h @@ -13,7 +13,6 @@ typedef struct sc_transaction_manager sc_queue * transaction_queue; sc_monitor * monitor; sc_mutex * mutex; - sc_uint64 transaction_counter; sc_list * threads; sc_condition * queue_condition; @@ -31,10 +30,10 @@ sc_transaction * sc_transaction_manager_transaction_new(); // create a new empty sc-transaction void sc_transaction_manager_transaction_add(sc_transaction * txn); // add transaction to the queue and start operations when the thread is ready -void sc_transaction_manager_transaction_execute(); +void sc_transaction_manager_transaction_execute(sc_transaction * txn); // execute the transaction and wait till it's finished -void sc_transaction_handler(sc_transaction_manager * manager); +void sc_transaction_handler(); // method for transaction queue processing by threads void sc_transaction_manager_destroy(); diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp new file mode 100644 index 0000000000..e69de29bb2 From 795c295094c75a43ff785a910f2e6f51c303c6da Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Thu, 10 Apr 2025 15:08:20 +0300 Subject: [PATCH 23/51] Add implementation of wrapper methods for managing GThread threads --- .../sc-core/src/sc-store/sc-base/sc_thread.c | 22 +++++++++++++++++++ .../sc-core/src/sc-store/sc-base/sc_thread.h | 7 ++++++ 2 files changed, 29 insertions(+) create mode 100644 sc-memory/sc-core/src/sc-store/sc-base/sc_thread.c diff --git a/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.c b/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.c new file mode 100644 index 0000000000..07399e20c4 --- /dev/null +++ b/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.c @@ -0,0 +1,22 @@ +/* +* This source file is part of an OSTIS project. For the latest info, see http://ostis.net + * Distributed under the MIT License + * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT) + */ + +#include "sc_thread.h" + +sc_thread * sc_thread_new(sc_thread_name * name, sc_thread_func func, sc_thread_data data) +{ + return g_thread_new(name, func, data); +} + +void sc_thread_join(sc_thread * thread) +{ + g_thread_join(thread); +} + +void sc_thread_unref(sc_thread * thread) +{ + g_thread_unref(thread); +} diff --git a/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.h b/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.h index 6815d08dac..1c35f3bf99 100644 --- a/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.h +++ b/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.h @@ -10,7 +10,14 @@ #include typedef GThread sc_thread; +typedef gpointer sc_thread_data; +typedef gpointer (*sc_thread_func)(sc_thread_data); +typedef const gchar sc_thread_name; #define sc_thread_self g_thread_self +sc_thread * sc_thread_new(sc_thread_name * name, sc_thread_func func, sc_thread_data data); +void sc_thread_join(sc_thread * thread); +void sc_thread_unref(sc_thread * thread); + #endif From 61b15394f0dcb416802762177ae36045ccdc6e28 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Thu, 10 Apr 2025 15:14:10 +0300 Subject: [PATCH 24/51] Use wrapper methods for threads in manager --- .../src/sc-store/sc-transaction/sc_transaction_manager.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c index b7a14f45c2..2d0eb595a4 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c @@ -49,7 +49,7 @@ sc_transaction_manager * sc_transaction_manager_initialize() for (int i = 0; i < SC_TRANSACTION_THREAD_COUNT; ++i) { - sc_thread * thread = g_thread_new("sc_transaction_handler", sc_transaction_handler, 0); + sc_thread * thread = sc_thread_new("sc_transaction_handler", sc_transaction_handler, 0); if (thread == null_ptr) { goto error_cleanup_threads; @@ -64,7 +64,7 @@ sc_transaction_manager * sc_transaction_manager_initialize() { for (sc_struct_node const * it = transaction_manager->threads->begin; it != null_ptr; it = it->next) { - g_thread_unref(it->data); + sc_thread_unref(it->data); } sc_list_destroy(transaction_manager->threads); transaction_manager->threads = null_ptr; @@ -118,8 +118,8 @@ void sc_transaction_manager_destroy() { for (sc_struct_node const * it = transaction_manager->threads->begin; it != null_ptr; it = it->next) { - g_thread_join(it->data); - g_thread_unref(it->data); + sc_thread_join(it->data); + sc_thread_unref(it->data); } sc_list_destroy(transaction_manager->threads); transaction_manager->threads = null_ptr; From cfd7d8d893d5ca8b8b8bd52297ea85fe77a548b1 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Thu, 10 Apr 2025 15:27:09 +0300 Subject: [PATCH 25/51] External memory allocation for the manager --- .../src/sc-store/sc-transaction/sc_transaction_manager.c | 5 +++-- .../src/sc-store/sc-transaction/sc_transaction_manager.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c index 2d0eb595a4..7a0b434bc0 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c @@ -7,14 +7,15 @@ sc_transaction_manager * transaction_manager = null_ptr; -sc_transaction_manager * sc_transaction_manager_initialize() +sc_transaction_manager * sc_transaction_manager_initialize(sc_transaction_manager* manager) { if (sc_transaction_manager_is_initialized()) { return transaction_manager; } - transaction_manager = sc_mem_new(sc_transaction_manager, 1); + transaction_manager = manager; + if (transaction_manager == null_ptr) { return null_ptr; diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h index ebafa41476..b4e4ef7160 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h @@ -19,7 +19,7 @@ typedef struct sc_transaction_manager sc_bool should_stop; } sc_transaction_manager; -sc_transaction_manager * sc_transaction_manager_initialize(); +sc_transaction_manager * sc_transaction_manager_initialize(sc_transaction_manager* manager); // create and initialize the transaction manager sc_bool sc_transaction_manager_is_initialized(); // check if the transaction manager is initialized From 6cf6c416aaf51b4e218d5baf527ac0d6f0f4d6a3 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Thu, 10 Apr 2025 15:33:08 +0300 Subject: [PATCH 26/51] Manager ini returns sc_result --- .../sc-transaction/sc_transaction_manager.c | 14 +++++++------- .../sc-transaction/sc_transaction_manager.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c index 7a0b434bc0..3ac177bbe6 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c @@ -7,18 +7,18 @@ sc_transaction_manager * transaction_manager = null_ptr; -sc_transaction_manager * sc_transaction_manager_initialize(sc_transaction_manager* manager) +sc_result sc_transaction_manager_initialize(sc_transaction_manager* manager) { if (sc_transaction_manager_is_initialized()) { - return transaction_manager; + return SC_RESULT_OK; } transaction_manager = manager; if (transaction_manager == null_ptr) { - return null_ptr; + return SC_RESULT_ERROR_INVALID_PARAMS; } transaction_manager->should_stop = SC_FALSE; @@ -27,7 +27,7 @@ sc_transaction_manager * sc_transaction_manager_initialize(sc_transaction_manage transaction_manager->transaction_queue = sc_mem_new(sc_queue, 1); if (transaction_manager->transaction_queue == null_ptr) { - goto error_cleanup_manager; + return SC_RESULT_ERROR_FULL_MEMORY; } sc_queue_init(transaction_manager->transaction_queue); @@ -45,7 +45,7 @@ sc_transaction_manager * sc_transaction_manager_initialize(sc_transaction_manage if (sc_list_init(&transaction_manager->threads) != SC_RESULT_OK) { - goto error_cleanup_condition; + return SC_RESULT_ERROR_INVALID_STATE; } for (int i = 0; i < SC_TRANSACTION_THREAD_COUNT; ++i) @@ -58,7 +58,7 @@ sc_transaction_manager * sc_transaction_manager_initialize(sc_transaction_manage sc_list_push_back(transaction_manager->threads, thread); } - return transaction_manager; + return SC_RESULT_OK; error_cleanup_threads: if (transaction_manager->threads != null_ptr) @@ -89,7 +89,7 @@ sc_transaction_manager * sc_transaction_manager_initialize(sc_transaction_manage sc_mem_free(transaction_manager); transaction_manager = null_ptr; - return null_ptr; + return SC_RESULT_ERROR; } sc_bool sc_transaction_manager_is_initialized() diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h index b4e4ef7160..006aa42306 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h @@ -19,8 +19,8 @@ typedef struct sc_transaction_manager sc_bool should_stop; } sc_transaction_manager; -sc_transaction_manager * sc_transaction_manager_initialize(sc_transaction_manager* manager); -// create and initialize the transaction manager +sc_result sc_transaction_manager_initialize(sc_transaction_manager* manager); +// initialize the transaction manager sc_bool sc_transaction_manager_is_initialized(); // check if the transaction manager is initialized void sc_transaction_shutdown(); From 90fb0e5efab2da515d3f0008c0fd72cb51d20a44 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Thu, 10 Apr 2025 16:31:47 +0300 Subject: [PATCH 27/51] Manager tests --- .../sc-core/src/sc-store/sc-base/sc_thread.c | 10 ++- .../sc-transaction/sc_transaction_manager.c | 23 ++++++- .../test_sc_transaction_manager.cpp | 63 +++++++++++++++++++ 3 files changed, 92 insertions(+), 4 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.c b/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.c index 07399e20c4..437f97972e 100644 --- a/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.c +++ b/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.c @@ -6,6 +6,8 @@ #include "sc_thread.h" +#include "sc-core/sc_types.h" + sc_thread * sc_thread_new(sc_thread_name * name, sc_thread_func func, sc_thread_data data) { return g_thread_new(name, func, data); @@ -13,10 +15,14 @@ sc_thread * sc_thread_new(sc_thread_name * name, sc_thread_func func, sc_thread_ void sc_thread_join(sc_thread * thread) { - g_thread_join(thread); + if (thread != null_ptr) { + g_thread_join(thread); + } } void sc_thread_unref(sc_thread * thread) { - g_thread_unref(thread); + if (thread != null_ptr) { + g_thread_unref(thread); + } } diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c index 3ac177bbe6..7eafa1d37c 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c @@ -1,5 +1,6 @@ #include "sc_transaction_manager.h" +#include "sc-store/sc-base/sc_condition_private.h" #include "sc-store/sc-base/sc_thread.h" #include "sc-store/sc-container/sc_struct_node.h" @@ -40,7 +41,20 @@ sc_result sc_transaction_manager_initialize(sc_transaction_manager* manager) sc_monitor_init(transaction_manager->monitor); + transaction_manager->queue_condition = sc_mem_new(sc_condition, 1); + if (transaction_manager->queue_condition == null_ptr) + { + goto error_cleanup_monitor; + } + sc_cond_init(transaction_manager->queue_condition); + + transaction_manager->mutex = sc_mem_new(sc_mutex, 1); + if (transaction_manager->mutex == null_ptr) + { + goto error_cleanup_condition; + } + sc_mutex_init(transaction_manager->mutex); if (sc_list_init(&transaction_manager->threads) != SC_RESULT_OK) @@ -73,9 +87,11 @@ sc_result sc_transaction_manager_initialize(sc_transaction_manager* manager) error_cleanup_mutex: sc_mutex_destroy(transaction_manager->mutex); + sc_mem_free(transaction_manager->mutex); error_cleanup_condition: sc_cond_destroy(transaction_manager->queue_condition); + sc_mem_free(transaction_manager->queue_condition); error_cleanup_monitor: sc_monitor_destroy(transaction_manager->monitor); @@ -119,8 +135,11 @@ void sc_transaction_manager_destroy() { for (sc_struct_node const * it = transaction_manager->threads->begin; it != null_ptr; it = it->next) { - sc_thread_join(it->data); - sc_thread_unref(it->data); + if (it->data != null_ptr) { + sc_thread *thread = it->data; + sc_thread_join(thread); + sc_thread_unref(thread); + } } sc_list_destroy(transaction_manager->threads); transaction_manager->threads = null_ptr; diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp index e69de29bb2..bee7d10832 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp @@ -0,0 +1,63 @@ +#include +#include +#include + +extern "C" +{ +#include +#include +} + +class ScTransactionManagerTest : public ScMemoryTest +{ +protected: + sc_transaction_manager* transaction_manager = nullptr; + + void SetUp() override + { + ScMemoryTest::SetUp(); + transaction_manager = sc_mem_new(sc_transaction_manager, 1); + EXPECT_EQ(sc_transaction_manager_initialize(transaction_manager), SC_RESULT_OK); + } + + void TearDown() override + { + sc_transaction_shutdown(); + ScMemoryTest::TearDown(); + } +}; + +TEST_F(ScTransactionManagerTest, Initialization) +{ + ASSERT_NE(transaction_manager, nullptr); + EXPECT_TRUE(sc_transaction_manager_is_initialized()); +} + +TEST_F(ScTransactionManagerTest, Shutdown) +{ + sc_transaction_shutdown(); + EXPECT_FALSE(sc_transaction_manager_is_initialized()); +} + +TEST_F(ScTransactionManagerTest, TransactionNew) +{ + sc_transaction *txn = sc_transaction_manager_transaction_new(); + EXPECT_NE(txn, nullptr); +} + +TEST_F(ScTransactionManagerTest, TransactionAdd) +{ + sc_transaction *txn = sc_transaction_manager_transaction_new(); + EXPECT_NE(txn, nullptr); + sc_transaction_manager_transaction_add(txn); + + sc_monitor_acquire_read(transaction_manager->monitor); + EXPECT_EQ(transaction_manager->transaction_queue->size, 1); + sc_monitor_release_read(transaction_manager->monitor); +} + +TEST_F(ScTransactionManagerTest, TransactionManagerDestroy) +{ + sc_transaction_shutdown(); + EXPECT_FALSE(sc_transaction_manager_is_initialized()); +} From 8f972be6f91e560ec2a844d08cd9f0d0ea7bdc40 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Thu, 10 Apr 2025 20:08:45 +0300 Subject: [PATCH 28/51] Fix txn buffer init and destroy --- .../sc-transaction/sc_transaction_buffer.c | 85 ++++++++++++++----- .../sc-transaction/sc_transaction_buffer.h | 3 +- 2 files changed, 68 insertions(+), 20 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c index e109331af5..b9ad18f8a2 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c @@ -19,49 +19,96 @@ typedef struct sc_content_version SC_ELEMENT_MODIFIED_FLAGS SC_ELEMENT_CONTENT_MODIFIED; } sc_content_version; -sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer, sc_uint64 txn_id) +void sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer, sc_uint64 txn_id) { if (transaction_buffer == null_ptr) - return SC_FALSE; + return; transaction_buffer->transaction_id = txn_id; if (!sc_list_init(&transaction_buffer->new_elements)) - return SC_FALSE; + goto error_nothing; if (!sc_list_init(&transaction_buffer->modified_elements)) + goto error_new_elements; + + if (!sc_list_init(&transaction_buffer->deleted_elements)) + goto error_modified_elements; + + if (!sc_list_init(&transaction_buffer->content_changes)) + goto error_deleted_elements; + + transaction_buffer->monitor_table = sc_mem_new(sc_monitor_table, 1); + if (transaction_buffer->monitor_table == null_ptr) + goto error_content_changes; + + _sc_monitor_table_init(transaction_buffer->monitor_table); + return; + + error_content_changes: + sc_list_destroy(transaction_buffer->content_changes); + error_deleted_elements: + sc_list_destroy(transaction_buffer->deleted_elements); + error_modified_elements: + sc_list_destroy(transaction_buffer->modified_elements); + error_new_elements: + sc_list_destroy(transaction_buffer->new_elements); + error_nothing: + return; +} + +void sc_transaction_buffer_destroy(sc_transaction_buffer * transaction_buffer) +{ + if (transaction_buffer == null_ptr) + return; + + if (transaction_buffer->new_elements != null_ptr) { sc_list_destroy(transaction_buffer->new_elements); - return SC_FALSE; + transaction_buffer->new_elements = null_ptr; } - if (!sc_list_init(&transaction_buffer->deleted_elements)) + if (transaction_buffer->modified_elements != null_ptr) { - sc_list_destroy(transaction_buffer->new_elements); sc_list_destroy(transaction_buffer->modified_elements); - return SC_FALSE; + transaction_buffer->modified_elements = null_ptr; } - if (!sc_list_init(&transaction_buffer->content_changes)) + if (transaction_buffer->deleted_elements != null_ptr) { - sc_list_destroy(transaction_buffer->new_elements); - sc_list_destroy(transaction_buffer->modified_elements); sc_list_destroy(transaction_buffer->deleted_elements); - return SC_FALSE; + transaction_buffer->deleted_elements = null_ptr; } - transaction_buffer->monitor_table = sc_mem_new(sc_monitor_table, 1); - if (transaction_buffer->monitor_table == null_ptr) + if (transaction_buffer->content_changes != null_ptr) { - sc_list_destroy(transaction_buffer->new_elements); - sc_list_destroy(transaction_buffer->modified_elements); - sc_list_destroy(transaction_buffer->deleted_elements); + sc_iterator * it = sc_list_iterator(transaction_buffer->content_changes); + while (sc_iterator_next(it)) + { + sc_pair * pair = sc_iterator_get(it); + if (pair == null_ptr) + continue; + + if (pair->second != null_ptr) + { + sc_stream_free(pair->second); + pair->second = null_ptr; + } + + sc_mem_free(pair); + } + sc_iterator_destroy(it); + sc_list_destroy(transaction_buffer->content_changes); - return SC_FALSE; + transaction_buffer->content_changes = null_ptr; } - _sc_monitor_table_init(transaction_buffer->monitor_table); - return SC_TRUE; + if (transaction_buffer->monitor_table != null_ptr) + { + _sc_monitor_table_destroy(transaction_buffer->monitor_table); + sc_mem_free(transaction_buffer->monitor_table); + transaction_buffer->monitor_table = null_ptr; + } } sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer const * buffer, sc_addr const * addr) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h index 294579ac9b..9fec9de5dc 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h @@ -16,7 +16,8 @@ typedef struct sc_transaction_buffer sc_uint64 transaction_id; } sc_transaction_buffer; -sc_bool sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer, sc_uint64 txn_id); +void sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer, sc_uint64 txn_id); +void sc_transaction_buffer_destroy(sc_transaction_buffer * transaction_buffer); sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer const * buffer, sc_addr const * addr); sc_bool sc_transaction_buffer_modified_add( From 6143ff4853d4e5e738e23afa5681f582942f82c6 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Fri, 11 Apr 2025 13:34:13 +0300 Subject: [PATCH 29/51] Rename txn manager, use var for txn id, highligh the methods for the api --- ...ager.c => sc_memory_transaction_manager.c} | 24 ++++++++++++------- ...ager.h => sc_memory_transaction_manager.h} | 19 ++++++++++----- .../sc-store/sc-transaction/sc_transaction.c | 2 +- 3 files changed, 29 insertions(+), 16 deletions(-) rename sc-memory/sc-core/src/sc-store/sc-transaction/{sc_transaction_manager.c => sc_memory_transaction_manager.c} (89%) rename sc-memory/sc-core/src/sc-store/sc-transaction/{sc_transaction_manager.h => sc_memory_transaction_manager.h} (65%) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c similarity index 89% rename from sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c rename to sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c index 7eafa1d37c..ec3e6882de 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c @@ -1,4 +1,4 @@ -#include "sc_transaction_manager.h" +#include "sc_memory_transaction_manager.h" #include "sc-store/sc-base/sc_condition_private.h" #include "sc-store/sc-base/sc_thread.h" @@ -6,11 +6,11 @@ #include -sc_transaction_manager * transaction_manager = null_ptr; +sc_memory_transaction_manager * transaction_manager = null_ptr; -sc_result sc_transaction_manager_initialize(sc_transaction_manager* manager) +sc_result sc_memory_transaction_manager_initialize(sc_memory_transaction_manager * manager) { - if (sc_transaction_manager_is_initialized()) + if (sc_memory_transaction_manager_is_initialized()) { return SC_RESULT_OK; } @@ -24,6 +24,7 @@ sc_result sc_transaction_manager_initialize(sc_transaction_manager* manager) transaction_manager->should_stop = SC_FALSE; transaction_manager->threads = null_ptr; + transaction_manager->txn_count = 0; transaction_manager->transaction_queue = sc_mem_new(sc_queue, 1); if (transaction_manager->transaction_queue == null_ptr) @@ -108,12 +109,12 @@ sc_result sc_transaction_manager_initialize(sc_transaction_manager* manager) return SC_RESULT_ERROR; } -sc_bool sc_transaction_manager_is_initialized() +sc_bool sc_memory_transaction_manager_is_initialized() { return transaction_manager != null_ptr; } -void sc_transaction_shutdown() +void sc_memory_transaction_shutdown() { if (transaction_manager != null_ptr) { @@ -122,6 +123,11 @@ void sc_transaction_shutdown() } } +sc_memory_transaction_manager * sc_memory_transaction_manager_get() +{ + return transaction_manager; +} + void sc_transaction_manager_destroy() { if (transaction_manager == null_ptr) @@ -167,15 +173,15 @@ void sc_transaction_manager_destroy() } -sc_transaction * sc_transaction_manager_transaction_new() +sc_transaction * sc_memory_transaction_new() { - if (!sc_transaction_manager_is_initialized()) + if (!sc_memory_transaction_manager_is_initialized()) { return null_ptr; } sc_monitor_acquire_write(transaction_manager->monitor); - sc_uint64 const txn_id = transaction_manager->transaction_queue->size++; + sc_uint64 const txn_id = transaction_manager->txn_count++; sc_monitor_release_write(transaction_manager->monitor); return sc_transaction_new(txn_id); diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h similarity index 65% rename from sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h rename to sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h index 006aa42306..0d9f593eb9 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_manager.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h @@ -8,7 +8,7 @@ #define SC_TRANSACTION_THREAD_COUNT 2 #define SC_TRANSACTION_MANAGER_QUEUE_SIZE 10 -typedef struct sc_transaction_manager +typedef struct sc_memory_transaction_manager { sc_queue * transaction_queue; sc_monitor * monitor; @@ -16,18 +16,25 @@ typedef struct sc_transaction_manager sc_list * threads; sc_condition * queue_condition; + sc_uint32 txn_count; sc_bool should_stop; -} sc_transaction_manager; +} sc_memory_transaction_manager; -sc_result sc_transaction_manager_initialize(sc_transaction_manager* manager); +sc_result sc_memory_transaction_manager_initialize(sc_memory_transaction_manager* manager); // initialize the transaction manager -sc_bool sc_transaction_manager_is_initialized(); +sc_bool sc_memory_transaction_manager_is_initialized(); // check if the transaction manager is initialized -void sc_transaction_shutdown(); +void sc_memory_transaction_shutdown(); // shutdown the transaction manager -sc_transaction * sc_transaction_manager_transaction_new(); +sc_memory_transaction_manager * sc_memory_transaction_manager_get(); +// return transaction manager + +sc_transaction * sc_memory_transaction_new(); // create a new empty sc-transaction +sc_result sc_memory_transaction_commit(sc_transaction * txn); +// try to commit transaction (queue->execute->commit) + void sc_transaction_manager_transaction_add(sc_transaction * txn); // add transaction to the queue and start operations when the thread is ready void sc_transaction_manager_transaction_execute(sc_transaction * txn); diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index 5308bb7992..97c027b7ee 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -1,6 +1,6 @@ #include "sc_transaction.h" -#include "sc_transaction_manager.h" +#include "sc_memory_transaction_manager.h" #include "sc-store/sc_element.h" #include "sc-store/sc_storage_private.h" From 63c29a9bc14ceea8ff196a6d834ed2ee48ec28dd Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Fri, 11 Apr 2025 13:36:25 +0300 Subject: [PATCH 30/51] Init txn manager with sc-memory --- sc-memory/sc-core/src/sc_memory.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sc-memory/sc-core/src/sc_memory.c b/sc-memory/sc-core/src/sc_memory.c index 0d5ad1b07f..df9684e735 100644 --- a/sc-memory/sc-core/src/sc_memory.c +++ b/sc-memory/sc-core/src/sc_memory.c @@ -20,11 +20,13 @@ #include "sc-core/sc_types.h" #include "sc-core/sc-base/sc_allocator.h" #include "sc-core/sc-container/sc_string.h" +#include "sc-store/sc-transaction/sc_memory_transaction_manager.h" struct _sc_memory { sc_addr myself_addr; sc_memory_context_manager * context_manager; + sc_memory_transaction_manager * transaction_manager; }; sc_memory * memory = null_ptr; @@ -50,6 +52,14 @@ sc_memory_context * sc_memory_initialize(sc_memory_params const * params, sc_mem goto error; } + sc_memory_transaction_manager * transaction_manager = sc_mem_new(sc_memory_transaction_manager, 1); + if (sc_memory_transaction_manager_initialize(transaction_manager) != SC_RESULT_OK) + { + s_memory_default_ctx = null_ptr; + sc_memory_error("Error while initialize sc-transaction manager"); + goto error; + } + memory = sc_mem_new(sc_memory, 1); sc_storage_start_new_process(); From 6c0bceedeb32c7b7b57dcd9d767e4fa341df4a9b Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Fri, 11 Apr 2025 13:37:36 +0300 Subject: [PATCH 31/51] Update tests --- .../units/transaction/test_sc_buffer.cpp | 3 ++- .../test_sc_transaction_manager.cpp | 24 +++++++++---------- .../test_sc_transaction_memory.cpp | 0 3 files changed, 14 insertions(+), 13 deletions(-) create mode 100644 sc-memory/sc-core/tests/units/transaction/test_sc_transaction_memory.cpp diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp index 40730f5190..fa263b2239 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp @@ -23,7 +23,8 @@ class ScTransactionBufferTest : public ScMemoryTest void SetUp() override { ScMemoryTest::SetUp(); - ASSERT_TRUE(sc_transaction_buffer_initialize(buffer, 1)); + sc_transaction_buffer_initialize(buffer, 1); + ASSERT_NE(buffer, null_ptr); } void TearDown() override diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp index bee7d10832..e893228f70 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp @@ -5,24 +5,24 @@ extern "C" { #include -#include +#include } class ScTransactionManagerTest : public ScMemoryTest { protected: - sc_transaction_manager* transaction_manager = nullptr; + + sc_memory_transaction_manager * transaction_manager = nullptr; void SetUp() override { ScMemoryTest::SetUp(); - transaction_manager = sc_mem_new(sc_transaction_manager, 1); - EXPECT_EQ(sc_transaction_manager_initialize(transaction_manager), SC_RESULT_OK); + transaction_manager = sc_memory_transaction_manager_get(); } void TearDown() override { - sc_transaction_shutdown(); + sc_memory_transaction_shutdown(); ScMemoryTest::TearDown(); } }; @@ -30,24 +30,24 @@ class ScTransactionManagerTest : public ScMemoryTest TEST_F(ScTransactionManagerTest, Initialization) { ASSERT_NE(transaction_manager, nullptr); - EXPECT_TRUE(sc_transaction_manager_is_initialized()); + EXPECT_TRUE(sc_memory_transaction_manager_is_initialized()); } TEST_F(ScTransactionManagerTest, Shutdown) { - sc_transaction_shutdown(); - EXPECT_FALSE(sc_transaction_manager_is_initialized()); + sc_memory_transaction_shutdown(); + EXPECT_FALSE(sc_memory_transaction_manager_is_initialized()); } TEST_F(ScTransactionManagerTest, TransactionNew) { - sc_transaction *txn = sc_transaction_manager_transaction_new(); + sc_transaction *txn = sc_memory_transaction_new(); EXPECT_NE(txn, nullptr); } TEST_F(ScTransactionManagerTest, TransactionAdd) { - sc_transaction *txn = sc_transaction_manager_transaction_new(); + sc_transaction *txn = sc_memory_transaction_new(); EXPECT_NE(txn, nullptr); sc_transaction_manager_transaction_add(txn); @@ -58,6 +58,6 @@ TEST_F(ScTransactionManagerTest, TransactionAdd) TEST_F(ScTransactionManagerTest, TransactionManagerDestroy) { - sc_transaction_shutdown(); - EXPECT_FALSE(sc_transaction_manager_is_initialized()); + sc_memory_transaction_shutdown(); + EXPECT_FALSE(sc_memory_transaction_manager_is_initialized()); } diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_memory.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_memory.cpp new file mode 100644 index 0000000000..e69de29bb2 From 40e6e49a586172628bdfd6e9bcfbf91d97c02ce8 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Fri, 11 Apr 2025 16:28:18 +0300 Subject: [PATCH 32/51] Context is assigned to a transaction, update tests --- .../sc-transaction/sc_memory_transaction_manager.c | 4 ++-- .../sc-transaction/sc_memory_transaction_manager.h | 2 +- .../sc-core/src/sc-store/sc-transaction/sc_transaction.c | 3 ++- .../sc-core/src/sc-store/sc-transaction/sc_transaction.h | 7 ++++++- .../tests/units/transaction/test_sc_transaction.cpp | 4 ++-- .../units/transaction/test_sc_transaction_manager.cpp | 4 ++-- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c index ec3e6882de..5d4c8ecade 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c @@ -173,7 +173,7 @@ void sc_transaction_manager_destroy() } -sc_transaction * sc_memory_transaction_new() +sc_transaction * sc_memory_transaction_new(sc_memory_context * ctx) { if (!sc_memory_transaction_manager_is_initialized()) { @@ -184,7 +184,7 @@ sc_transaction * sc_memory_transaction_new() sc_uint64 const txn_id = transaction_manager->txn_count++; sc_monitor_release_write(transaction_manager->monitor); - return sc_transaction_new(txn_id); + return sc_transaction_new(txn_id, ctx); } void sc_transaction_manager_transaction_add(sc_transaction * txn) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h index 0d9f593eb9..251ad696be 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h @@ -30,7 +30,7 @@ void sc_memory_transaction_shutdown(); sc_memory_transaction_manager * sc_memory_transaction_manager_get(); // return transaction manager -sc_transaction * sc_memory_transaction_new(); +sc_transaction * sc_memory_transaction_new(sc_memory_context * ctx); // create a new empty sc-transaction sc_result sc_memory_transaction_commit(sc_transaction * txn); // try to commit transaction (queue->execute->commit) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index 97c027b7ee..17052b2067 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -6,7 +6,7 @@ #include -sc_transaction * sc_transaction_new(sc_uint64 const txn_id) +sc_transaction * sc_transaction_new(sc_uint64 const txn_id, sc_memory_context * ctx) { sc_transaction * txn = sc_mem_new(sc_transaction, 1); if (txn == null_ptr) @@ -14,6 +14,7 @@ sc_transaction * sc_transaction_new(sc_uint64 const txn_id) txn->transaction_id = txn_id; txn->is_committed = SC_FALSE; + txn->ctx = ctx; txn->transaction_buffer = sc_mem_new(sc_transaction_buffer, 1); if (txn->transaction_buffer == null_ptr) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index 00dd83e67e..6808832280 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -13,21 +13,26 @@ typedef struct sc_transaction sc_bool is_committed; sc_list * elements; sc_transaction_buffer * transaction_buffer; + sc_memory_context * ctx; } sc_transaction; -sc_transaction * sc_transaction_new(sc_uint64 txn_id); +sc_transaction * sc_transaction_new(sc_uint64 txn_id, sc_memory_context * ctx); // create a new transaction void sc_transaction_destroy(sc_transaction * txn); // destroy the given transaction sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_addr const * addr); +// Writes information about adding an item to the buffer sc_bool sc_transaction_element_change( sc_addr const * addr, sc_transaction const * txn, SC_ELEMENT_MODIFIED_FLAGS modified_flags, sc_element const * new_data); +// Writes information about the element change to the buffer sc_bool sc_transaction_element_remove(sc_transaction const * txn, sc_addr const * addr); +// Writes the deletion information to the buffer sc_bool sc_transaction_element_content_set(sc_transaction const * txn, sc_addr const * addr, sc_stream const * content); +// Writes information about content changes to the buffer void sc_transaction_commit(sc_transaction * txn); // try to apply all operations of the transaction on sc-memory diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp index 740ee62a6e..af25c301a6 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp @@ -19,7 +19,7 @@ class ScTransactionTest : public ScMemoryTest void SetUp() override { ScMemoryTest::SetUp(); - transaction = sc_transaction_new(test_txn_id); + transaction = sc_transaction_new(test_txn_id, m_ctx->GetRealContext()); ASSERT_NE(transaction, nullptr); } @@ -144,6 +144,6 @@ TEST_F(ScTransactionTest, TransactionEdgeCases) { sc_transaction_destroy(nullptr); - sc_transaction * failed_txn = sc_transaction_new(0); + sc_transaction * failed_txn = sc_transaction_new(0, m_ctx->GetRealContext()); EXPECT_NE(failed_txn, nullptr); } \ No newline at end of file diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp index e893228f70..82819f9c30 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp @@ -41,13 +41,13 @@ TEST_F(ScTransactionManagerTest, Shutdown) TEST_F(ScTransactionManagerTest, TransactionNew) { - sc_transaction *txn = sc_memory_transaction_new(); + sc_transaction *txn = sc_memory_transaction_new(m_ctx->GetRealContext()); EXPECT_NE(txn, nullptr); } TEST_F(ScTransactionManagerTest, TransactionAdd) { - sc_transaction *txn = sc_memory_transaction_new(); + sc_transaction *txn = sc_memory_transaction_new(m_ctx->GetRealContext()); EXPECT_NE(txn, nullptr); sc_transaction_manager_transaction_add(txn); From fbea119efa15807b60da5134294d6142633b721c Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Fri, 11 Apr 2025 23:39:24 +0300 Subject: [PATCH 33/51] Add example of operation on sc-memory within a transaction --- .../sc-transaction/sc_memory_transaction_operations.c | 11 +++++++++++ .../sc-transaction/sc_memory_transaction_operations.h | 8 ++++++++ 2 files changed, 19 insertions(+) create mode 100644 sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c create mode 100644 sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c new file mode 100644 index 0000000000..213df13871 --- /dev/null +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c @@ -0,0 +1,11 @@ +#include "sc_memory_transaction_operations.h" + +#include "sc-core/sc_memory.h" + +sc_addr sc_memory_transaction_node_new(const sc_transaction * txn, const sc_type type) +{ + sc_result result; + const sc_addr allocated_addr = sc_memory_node_new_ext(txn->ctx, type, &result); + sc_transaction_element_new(txn, &allocated_addr); + return allocated_addr; +} \ No newline at end of file diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h new file mode 100644 index 0000000000..85a822cb4c --- /dev/null +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h @@ -0,0 +1,8 @@ +#ifndef SC_MEMORY_TRANSACTION_OPERATIONS_H +#define SC_MEMORY_TRANSACTION_OPERATIONS_H + +#include "sc_transaction.h" + +sc_addr sc_memory_node_new(const sc_transaction * txn, const sc_type type); + +#endif //SC_MEMORY_TRANSACTION_OPERATIONS_H From 04b869b31c6055ee14365672156b8548331f36b5 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 16 Apr 2025 21:46:32 +0300 Subject: [PATCH 34/51] Remove redundant flags --- .../sc-transaction/sc_element_version.c | 4 +- .../sc-transaction/sc_element_version.h | 20 +-------- .../sc_memory_transaction_operations.c | 43 ++++++++++++++++++- .../sc_memory_transaction_operations.h | 1 - sc-memory/sc-core/src/sc-store/sc_element.h | 1 + 5 files changed, 45 insertions(+), 24 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c index d1a718a406..a7fa134ee4 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c @@ -6,8 +6,7 @@ sc_element_version * sc_element_create_new_version( sc_element_version * parent, sc_element const * new_element_data, sc_uint64 const version_id, - sc_uint64 const transaction_id, - const SC_ELEMENT_MODIFIED_FLAGS modified_fields) + sc_uint64 const transaction_id) { if (new_element_data == null_ptr) return null_ptr; @@ -21,7 +20,6 @@ sc_element_version * sc_element_create_new_version( new_version->transaction_id = transaction_id; new_version->parent_version = parent; new_version->is_committed = SC_FALSE; - new_version->modified_fields = modified_fields; return new_version; } diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h index 1af234d370..1a8168d987 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h @@ -1,15 +1,6 @@ #ifndef SC_ELEMENT_VERSION_H #define SC_ELEMENT_VERSION_H - -#include - -typedef enum -{ - SC_ELEMENT_FLAGS_MODIFIED = 1 << 0, - SC_ELEMENT_ARCS_MODIFIED = 1 << 1, - SC_ELEMENT_CONTENT_MODIFIED = 1 << 2, - SC_ELEMENT_LINKS_MODIFIED = 1 << 3 -} SC_ELEMENT_MODIFIED_FLAGS; +#include "sc-core/sc_types.h" typedef struct sc_element_version { @@ -18,19 +9,12 @@ typedef struct sc_element_version sc_uint64 transaction_id; struct sc_element_version * parent_version; sc_bool is_committed; - SC_ELEMENT_MODIFIED_FLAGS modified_fields; } sc_element_version; -typedef struct sc_version_history -{ - sc_element_version * latest_version; -} sc_version_history; - sc_element_version * sc_element_create_new_version( sc_element_version * parent, sc_element const * new_element_data, sc_uint64 version_id, - sc_uint64 transaction_id, - SC_ELEMENT_MODIFIED_FLAGS modified_fields); + sc_uint64 transaction_id); #endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c index 213df13871..0eb343f21c 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c @@ -1,11 +1,50 @@ #include "sc_memory_transaction_operations.h" #include "sc-core/sc_memory.h" +#include "sc-store/sc_element.h" +#include "sc-store/sc_storage_private.h" sc_addr sc_memory_transaction_node_new(const sc_transaction * txn, const sc_type type) { - sc_result result; - const sc_addr allocated_addr = sc_memory_node_new_ext(txn->ctx, type, &result); + const sc_addr allocated_addr = sc_memory_node_new(txn->ctx, type); sc_transaction_element_new(txn, &allocated_addr); return allocated_addr; +} + +sc_addr sc_memory_transaction_link_new(const sc_transaction * txn) +{ + const sc_addr allocated_addr = sc_memory_link_new(txn->ctx); + sc_transaction_element_new(txn, &allocated_addr); + return allocated_addr; +} + +sc_addr sc_memory_transaction_arc_new(const sc_transaction * txn, const sc_type type, const sc_addr beg, const sc_addr end) +{ + sc_element * beg_new_version; + sc_element * end_new_version; + + sc_addr beg_new_version_addr = SC_ADDR_EMPTY; + beg_new_version = sc_storage_allocate_new_element(txn->ctx, &beg_new_version_addr); + sc_storage_get_element_by_addr(beg, &beg_new_version); + + sc_addr end_new_version_addr = SC_ADDR_EMPTY; + end_new_version = sc_storage_allocate_new_element(txn->ctx, &end_new_version_addr); + sc_storage_get_element_by_addr(beg, &end_new_version); + + const sc_addr allocated_addr = sc_memory_arc_new(txn->ctx, type, beg_new_version_addr, end_new_version_addr); + sc_transaction_element_new(txn, &allocated_addr); + + sc_storage_get_element_by_addr(beg_new_version_addr, &beg_new_version); + sc_storage_get_element_by_addr(beg_new_version_addr, &end_new_version); + + sc_transaction_element_change(&beg, txn, SC_ELEMENT_ARCS_MODIFIED, beg_new_version); + sc_transaction_element_change(&end, txn, SC_ELEMENT_ARCS_MODIFIED, end_new_version); + + return allocated_addr; +} + +sc_addr sc_memory_transaction_element_free(const sc_transaction * txn, const sc_addr addr) +{ + sc_transaction_element_remove(txn, &addr); + return addr; } \ No newline at end of file diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h index 85a822cb4c..193e51c163 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h @@ -3,6 +3,5 @@ #include "sc_transaction.h" -sc_addr sc_memory_node_new(const sc_transaction * txn, const sc_type type); #endif //SC_MEMORY_TRANSACTION_OPERATIONS_H diff --git a/sc-memory/sc-core/src/sc-store/sc_element.h b/sc-memory/sc-core/src/sc-store/sc_element.h index aab8408653..0a8c2edec6 100644 --- a/sc-memory/sc-core/src/sc-store/sc_element.h +++ b/sc-memory/sc-core/src/sc-store/sc_element.h @@ -67,6 +67,7 @@ struct _sc_element sc_uint32 outgoing_arcs_count; sc_version_history version_history; + sc_transaction_version_buffer transaction_buffer; }; #endif From 2d5699189d708c3a50a9ae662c41aa016b4311cc Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Tue, 6 May 2025 20:53:27 +0300 Subject: [PATCH 35/51] Use segment for store element version history --- .../sc-core/src/sc-store/sc-base/sc_thread.c | 12 +++-- .../sc-core/src/sc-store/sc-base/sc_thread.h | 2 +- .../sc_memory_transaction_manager.c | 12 ++--- .../sc_memory_transaction_manager.h | 2 +- .../sc_memory_transaction_operations.c | 22 ++++---- .../sc_memory_transaction_operations.h | 3 +- .../sc-store/sc-transaction/sc_transaction.c | 8 +-- .../sc-store/sc-transaction/sc_transaction.h | 6 +-- .../sc-transaction/sc_transaction_buffer.c | 50 ++++++++--------- .../sc-transaction/sc_transaction_buffer.h | 3 +- sc-memory/sc-core/src/sc-store/sc_element.h | 6 ++- .../sc-core/src/sc-store/sc_version_segment.c | 54 +++++++++++++++++++ .../sc-core/src/sc-store/sc_version_segment.h | 30 +++++++++++ .../units/transaction/test_sc_buffer.cpp | 3 -- .../units/transaction/test_sc_transaction.cpp | 28 ---------- .../test_sc_transaction_manager.cpp | 5 +- 16 files changed, 146 insertions(+), 100 deletions(-) create mode 100644 sc-memory/sc-core/src/sc-store/sc_version_segment.c create mode 100644 sc-memory/sc-core/src/sc-store/sc_version_segment.h diff --git a/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.c b/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.c index 437f97972e..15efa315e2 100644 --- a/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.c +++ b/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.c @@ -1,5 +1,5 @@ /* -* This source file is part of an OSTIS project. For the latest info, see http://ostis.net + * This source file is part of an OSTIS project. For the latest info, see http://ostis.net * Distributed under the MIT License * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT) */ @@ -15,14 +15,16 @@ sc_thread * sc_thread_new(sc_thread_name * name, sc_thread_func func, sc_thread_ void sc_thread_join(sc_thread * thread) { - if (thread != null_ptr) { + if (thread != null_ptr) + { g_thread_join(thread); } } void sc_thread_unref(sc_thread * thread) { - if (thread != null_ptr) { - g_thread_unref(thread); - } + if (thread != null_ptr) + { + g_thread_unref(thread); + } } diff --git a/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.h b/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.h index 1c35f3bf99..2a7e01e327 100644 --- a/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.h +++ b/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.h @@ -12,7 +12,7 @@ typedef GThread sc_thread; typedef gpointer sc_thread_data; typedef gpointer (*sc_thread_func)(sc_thread_data); -typedef const gchar sc_thread_name; +typedef gchar const sc_thread_name; #define sc_thread_self g_thread_self diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c index 5d4c8ecade..ac87466d51 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c @@ -141,8 +141,9 @@ void sc_transaction_manager_destroy() { for (sc_struct_node const * it = transaction_manager->threads->begin; it != null_ptr; it = it->next) { - if (it->data != null_ptr) { - sc_thread *thread = it->data; + if (it->data != null_ptr) + { + sc_thread * thread = it->data; sc_thread_join(thread); sc_thread_unref(thread); } @@ -172,7 +173,6 @@ void sc_transaction_manager_destroy() transaction_manager = null_ptr; } - sc_transaction * sc_memory_transaction_new(sc_memory_context * ctx) { if (!sc_memory_transaction_manager_is_initialized()) @@ -198,10 +198,7 @@ void sc_transaction_manager_transaction_add(sc_transaction * txn) sc_cond_signal(transaction_manager->queue_condition); } -void sc_transaction_manager_transaction_execute(sc_transaction * txn) -{ - -} +void sc_transaction_manager_transaction_execute(sc_transaction * txn) {} void sc_transaction_handler() { @@ -236,4 +233,3 @@ void sc_transaction_handler() sc_monitor_release_read(transaction_manager->monitor); } - diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h index 251ad696be..80c4a03db3 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h @@ -20,7 +20,7 @@ typedef struct sc_memory_transaction_manager sc_bool should_stop; } sc_memory_transaction_manager; -sc_result sc_memory_transaction_manager_initialize(sc_memory_transaction_manager* manager); +sc_result sc_memory_transaction_manager_initialize(sc_memory_transaction_manager * manager); // initialize the transaction manager sc_bool sc_memory_transaction_manager_is_initialized(); // check if the transaction manager is initialized diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c index 0eb343f21c..c7a5533b43 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c @@ -4,21 +4,25 @@ #include "sc-store/sc_element.h" #include "sc-store/sc_storage_private.h" -sc_addr sc_memory_transaction_node_new(const sc_transaction * txn, const sc_type type) +sc_addr sc_memory_transaction_node_new(sc_transaction const * txn, sc_type const type) { - const sc_addr allocated_addr = sc_memory_node_new(txn->ctx, type); + sc_addr const allocated_addr = sc_memory_node_new(txn->ctx, type); sc_transaction_element_new(txn, &allocated_addr); return allocated_addr; } -sc_addr sc_memory_transaction_link_new(const sc_transaction * txn) +sc_addr sc_memory_transaction_link_new(sc_transaction const * txn) { - const sc_addr allocated_addr = sc_memory_link_new(txn->ctx); + sc_addr const allocated_addr = sc_memory_link_new(txn->ctx); sc_transaction_element_new(txn, &allocated_addr); return allocated_addr; } -sc_addr sc_memory_transaction_arc_new(const sc_transaction * txn, const sc_type type, const sc_addr beg, const sc_addr end) +sc_addr sc_memory_transaction_arc_new( + sc_transaction const * txn, + sc_type const type, + sc_addr const beg, + sc_addr const end) { sc_element * beg_new_version; sc_element * end_new_version; @@ -31,19 +35,19 @@ sc_addr sc_memory_transaction_arc_new(const sc_transaction * txn, const sc_type end_new_version = sc_storage_allocate_new_element(txn->ctx, &end_new_version_addr); sc_storage_get_element_by_addr(beg, &end_new_version); - const sc_addr allocated_addr = sc_memory_arc_new(txn->ctx, type, beg_new_version_addr, end_new_version_addr); + sc_addr const allocated_addr = sc_memory_arc_new(txn->ctx, type, beg_new_version_addr, end_new_version_addr); sc_transaction_element_new(txn, &allocated_addr); sc_storage_get_element_by_addr(beg_new_version_addr, &beg_new_version); sc_storage_get_element_by_addr(beg_new_version_addr, &end_new_version); - sc_transaction_element_change(&beg, txn, SC_ELEMENT_ARCS_MODIFIED, beg_new_version); - sc_transaction_element_change(&end, txn, SC_ELEMENT_ARCS_MODIFIED, end_new_version); + sc_transaction_element_change(&beg, txn, beg_new_version); + sc_transaction_element_change(&end, txn, end_new_version); return allocated_addr; } -sc_addr sc_memory_transaction_element_free(const sc_transaction * txn, const sc_addr addr) +sc_addr sc_memory_transaction_element_free(sc_transaction const * txn, sc_addr const addr) { sc_transaction_element_remove(txn, &addr); return addr; diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h index 193e51c163..0e12399130 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h @@ -3,5 +3,4 @@ #include "sc_transaction.h" - -#endif //SC_MEMORY_TRANSACTION_OPERATIONS_H +#endif // SC_MEMORY_TRANSACTION_OPERATIONS_H diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index 17052b2067..79f5ec9273 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -70,11 +70,7 @@ sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_addr const * a return sc_transaction_buffer_created_add(txn->transaction_buffer, addr); } -sc_bool sc_transaction_element_change( - sc_addr const * addr, - sc_transaction const * txn, - const SC_ELEMENT_MODIFIED_FLAGS modified_flags, - sc_element const * new_data) +sc_bool sc_transaction_element_change(sc_addr const * addr, sc_transaction const * txn, sc_element const * new_data) { if (txn == null_ptr || addr == null_ptr || txn->transaction_buffer == null_ptr) return SC_FALSE; @@ -82,7 +78,7 @@ sc_bool sc_transaction_element_change( if (SC_ADDR_IS_EMPTY(*addr)) return SC_FALSE; - return sc_transaction_buffer_modified_add(txn->transaction_buffer, addr, new_data, modified_flags); + return sc_transaction_buffer_modified_add(txn->transaction_buffer, addr, new_data); } sc_bool sc_transaction_element_remove(sc_transaction const * txn, sc_addr const * addr) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index 6808832280..562745ca47 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -23,11 +23,7 @@ void sc_transaction_destroy(sc_transaction * txn); sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_addr const * addr); // Writes information about adding an item to the buffer -sc_bool sc_transaction_element_change( - sc_addr const * addr, - sc_transaction const * txn, - SC_ELEMENT_MODIFIED_FLAGS modified_flags, - sc_element const * new_data); +sc_bool sc_transaction_element_change(sc_addr const * addr, sc_transaction const * txn, sc_element const * new_data); // Writes information about the element change to the buffer sc_bool sc_transaction_element_remove(sc_transaction const * txn, sc_addr const * addr); // Writes the deletion information to the buffer diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c index b9ad18f8a2..5a920af55f 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c @@ -2,7 +2,6 @@ #include "sc-store/sc_element.h" #include "sc-store/sc_storage_private.h" -#include "sc-store/sc-base/sc_monitor_private.h" #include "sc-store/sc-base/sc_monitor_table.h" #include "sc-store/sc-base/sc_monitor_table_private.h" #include "sc-store/sc-container/sc_pair.h" @@ -16,7 +15,6 @@ typedef struct sc_content_version { sc_addr addr; sc_stream * content; - SC_ELEMENT_MODIFIED_FLAGS SC_ELEMENT_CONTENT_MODIFIED; } sc_content_version; void sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer, sc_uint64 txn_id) @@ -45,16 +43,16 @@ void sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer _sc_monitor_table_init(transaction_buffer->monitor_table); return; - error_content_changes: - sc_list_destroy(transaction_buffer->content_changes); - error_deleted_elements: - sc_list_destroy(transaction_buffer->deleted_elements); - error_modified_elements: - sc_list_destroy(transaction_buffer->modified_elements); - error_new_elements: - sc_list_destroy(transaction_buffer->new_elements); - error_nothing: - return; +error_content_changes: + sc_list_destroy(transaction_buffer->content_changes); +error_deleted_elements: + sc_list_destroy(transaction_buffer->deleted_elements); +error_modified_elements: + sc_list_destroy(transaction_buffer->modified_elements); +error_new_elements: + sc_list_destroy(transaction_buffer->new_elements); +error_nothing: + return; } void sc_transaction_buffer_destroy(sc_transaction_buffer * transaction_buffer) @@ -132,8 +130,7 @@ sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer const * buffer, sc_bool sc_transaction_buffer_modified_add( sc_transaction_buffer const * buffer, sc_addr const * addr, - sc_element const * new_element_data, - const SC_ELEMENT_MODIFIED_FLAGS flags) + sc_element const * new_element_data) { if (buffer == null_ptr || buffer->modified_elements == null_ptr) return SC_FALSE; @@ -145,28 +142,32 @@ sc_bool sc_transaction_buffer_modified_add( if (sc_storage_get_element_by_addr(*addr, &element) != SC_RESULT_OK || element == null_ptr) return SC_FALSE; + if (element->version_history == null_ptr) + { + element->version_history = sc_version_segment_new(); + if (element->version_history == null_ptr) + return SC_FALSE; + } + + sc_version_segment * seg = element->version_history; + sc_monitor * monitor = sc_monitor_table_get_monitor_for_addr(buffer->monitor_table, *addr); if (monitor == null_ptr) return SC_FALSE; sc_monitor_acquire_write(monitor); - sc_uint64 const new_version_id = (element->version_history.latest_version != null_ptr) - ? (element->version_history.latest_version->version_id + 1) - : 0; + sc_uint64 const new_version_id = seg->latest_version ? seg->latest_version->version_id + 1 : 0; - sc_element_version * new_version = sc_element_create_new_version( - element->version_history.latest_version, new_element_data, new_version_id, buffer->transaction_id, flags); - - if (new_version == null_ptr) + sc_element_version * new_ver = + sc_version_segment_add(seg, new_element_data, new_version_id, buffer->transaction_id, seg->latest_version); + if (new_ver == null_ptr) { sc_monitor_release_write(monitor); return SC_FALSE; } - element->version_history.latest_version = new_version; - - monitor->id++; + seg->latest_version = new_ver; sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); if (sc_list_push_back(buffer->modified_elements, (void *)(uintptr_t)addr_hash) == null_ptr) @@ -176,7 +177,6 @@ sc_bool sc_transaction_buffer_modified_add( } sc_monitor_release_write(monitor); - return SC_TRUE; } diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h index 9fec9de5dc..dca34538cf 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h @@ -23,8 +23,7 @@ sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer const * buffer, sc_bool sc_transaction_buffer_modified_add( sc_transaction_buffer const * buffer, sc_addr const * addr, - sc_element const * element, - SC_ELEMENT_MODIFIED_FLAGS flags); + sc_element const * element); sc_bool sc_transaction_buffer_removed_add(sc_transaction_buffer const * buffer, sc_addr const * addr); sc_bool sc_transaction_buffer_content_set( sc_transaction_buffer const * buffer, diff --git a/sc-memory/sc-core/src/sc-store/sc_element.h b/sc-memory/sc-core/src/sc-store/sc_element.h index 0a8c2edec6..cbd7a80dd0 100644 --- a/sc-memory/sc-core/src/sc-store/sc_element.h +++ b/sc-memory/sc-core/src/sc-store/sc_element.h @@ -7,6 +7,8 @@ #ifndef _sc_element_h_ #define _sc_element_h_ +#include "sc_version_segment.h" + #include struct _sc_arc_info @@ -66,8 +68,8 @@ struct _sc_element sc_uint32 incoming_arcs_count; sc_uint32 outgoing_arcs_count; - sc_version_history version_history; - sc_transaction_version_buffer transaction_buffer; + sc_version_segment * version_history; + sc_version_segment * transaction_buffer; }; #endif diff --git a/sc-memory/sc-core/src/sc-store/sc_version_segment.c b/sc-memory/sc-core/src/sc-store/sc_version_segment.c new file mode 100644 index 0000000000..06b860aeb3 --- /dev/null +++ b/sc-memory/sc-core/src/sc-store/sc_version_segment.c @@ -0,0 +1,54 @@ +#include "sc_version_segment.h" +#include +#include +#include + +sc_version_segment * sc_version_segment_new(void) +{ + sc_version_segment * segment = sc_mem_new(sc_version_segment, 1); + if (!segment) + return NULL; + sc_mem_set(segment, 0, sizeof(*segment)); + sc_monitor_init(&segment->monitor); + return segment; +} + +void sc_version_segment_free(sc_version_segment * segment) +{ + if (!segment) + return; + sc_monitor_destroy(&segment->monitor); + sc_mem_free(segment); +} + +sc_element_version * sc_version_segment_add( + sc_version_segment * segment, + sc_element const * data, + sc_uint64 const version_id, + sc_uint64 const transaction_id, + sc_element_version * parent) +{ + if (!segment) + return NULL; + + sc_monitor_acquire_write(&segment->monitor); + + if (segment->count >= SC_VERSION_SEGMENT_SIZE) + { + sc_monitor_release_write(&segment->monitor); + return NULL; + } + + sc_element_version * ver = &segment->versions[segment->count++]; + + ver->data = data; + ver->version_id = version_id; + ver->transaction_id = transaction_id; + ver->parent_version = parent; + ver->is_committed = SC_FALSE; + + segment->latest_version = ver; + + sc_monitor_release_write(&segment->monitor); + return ver; +} diff --git a/sc-memory/sc-core/src/sc-store/sc_version_segment.h b/sc-memory/sc-core/src/sc-store/sc_version_segment.h new file mode 100644 index 0000000000..70dd7d5e15 --- /dev/null +++ b/sc-memory/sc-core/src/sc-store/sc_version_segment.h @@ -0,0 +1,30 @@ +#ifndef SC_VERSION_SEGMENT_H +#define SC_VERSION_SEGMENT_H + +#include "sc-base/sc_monitor_private.h" +#include "sc-transaction/sc_element_version.h" + +#include + +#define SC_VERSION_SEGMENT_SIZE 512 + +typedef struct sc_version_segment +{ + sc_element_version versions[SC_VERSION_SEGMENT_SIZE]; + sc_addr_offset count; + sc_monitor monitor; + sc_element_version* latest_version; +} sc_version_segment; + +sc_version_segment * sc_version_segment_new(void); + +void sc_version_segment_free(sc_version_segment * segment); + +sc_element_version * sc_version_segment_add( + sc_version_segment * segment, + sc_element const * data, + sc_uint64 version_id, + sc_uint64 transaction_id, + sc_element_version * parent); + +#endif // SC_VERSION_SEGMENT_H diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp index fa263b2239..21ec754e43 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp @@ -77,9 +77,6 @@ TEST_F(ScTransactionBufferTest, ModifiedAddTest) element->incoming_arcs_count++; - constexpr SC_ELEMENT_MODIFIED_FLAGS flags = SC_ELEMENT_ARCS_MODIFIED; - - EXPECT_TRUE(sc_transaction_buffer_modified_add(buffer, addr, element, flags)); EXPECT_EQ(buffer->modified_elements->size, 1); sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); EXPECT_EQ(buffer->modified_elements->begin->data, reinterpret_cast(addr_hash)); diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp index af25c301a6..8648c59a41 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp @@ -53,34 +53,6 @@ TEST_F(ScTransactionTest, TransactionElementNew) EXPECT_FALSE(sc_transaction_element_new(transaction, &empty_addr)); } -TEST_F(ScTransactionTest, TransactionElementChange) -{ - sc_addr addr; - sc_storage_allocate_new_element(m_ctx->GetRealContext(), &addr); - - sc_element element; - element.flags.type = sc_type_node; - - EXPECT_TRUE(sc_transaction_element_change(&addr, transaction, SC_ELEMENT_ARCS_MODIFIED, &element)); - - sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); - sc_iterator * it = sc_list_iterator(transaction->transaction_buffer->modified_elements); - sc_bool found = SC_FALSE; - while (sc_iterator_next(it)) - { - if (reinterpret_cast(sc_iterator_get(it)) == addr_hash) - { - found = SC_TRUE; - break; - } - } - sc_iterator_destroy(it); - EXPECT_TRUE(found); - - EXPECT_FALSE(sc_transaction_element_change(nullptr, transaction, SC_ELEMENT_ARCS_MODIFIED, &element)); - EXPECT_FALSE(sc_transaction_element_change(&addr, nullptr, SC_ELEMENT_ARCS_MODIFIED, &element)); -} - TEST_F(ScTransactionTest, TransactionElementRemove) { constexpr sc_addr addr = {3, 4}; diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp index 82819f9c30..4c19d9c2c7 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp @@ -11,7 +11,6 @@ extern "C" class ScTransactionManagerTest : public ScMemoryTest { protected: - sc_memory_transaction_manager * transaction_manager = nullptr; void SetUp() override @@ -41,13 +40,13 @@ TEST_F(ScTransactionManagerTest, Shutdown) TEST_F(ScTransactionManagerTest, TransactionNew) { - sc_transaction *txn = sc_memory_transaction_new(m_ctx->GetRealContext()); + sc_transaction * txn = sc_memory_transaction_new(m_ctx->GetRealContext()); EXPECT_NE(txn, nullptr); } TEST_F(ScTransactionManagerTest, TransactionAdd) { - sc_transaction *txn = sc_memory_transaction_new(m_ctx->GetRealContext()); + sc_transaction * txn = sc_memory_transaction_new(m_ctx->GetRealContext()); EXPECT_NE(txn, nullptr); sc_transaction_manager_transaction_add(txn); From 7f4f2633ed1d2e1e85bbf9fcd5dd2961b080ee64 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 7 May 2025 19:17:28 +0300 Subject: [PATCH 36/51] Update --- .../sc-transaction/sc_element_version.h | 23 ++++++++++-- .../sc_memory_transaction_operations.c | 22 ++++++------ .../sc-transaction/sc_transaction_buffer.c | 36 ++++++------------- sc-memory/sc-core/src/sc-store/sc_element.h | 1 - .../sc-core/src/sc-store/sc_version_segment.h | 4 +-- 5 files changed, 44 insertions(+), 42 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h index 1a8168d987..7370d8f6b3 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h @@ -1,19 +1,36 @@ #ifndef SC_ELEMENT_VERSION_H #define SC_ELEMENT_VERSION_H #include "sc-core/sc_types.h" +#include "sc-store/sc_element.h" + +typedef struct sc_element_data +{ + sc_element_flags flags; + + sc_addr first_out_arc; + sc_addr first_in_arc; +#ifdef SC_OPTIMIZE_SEARCHING_INCOMING_CONNECTORS_FROM_STRUCTURES + sc_addr first_in_arc_from_structure; +#endif + + sc_arc_info arc; + + sc_uint32 incoming_arcs_count; + sc_uint32 outgoing_arcs_count; +} sc_element_data; typedef struct sc_element_version { - sc_element const * data; + sc_element_data const * data; sc_uint64 version_id; sc_uint64 transaction_id; struct sc_element_version * parent_version; - sc_bool is_committed; + sc_bool is_committed; // redundant? } sc_element_version; sc_element_version * sc_element_create_new_version( sc_element_version * parent, - sc_element const * new_element_data, + sc_element_data const * new_element_data, sc_uint64 version_id, sc_uint64 transaction_id); diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c index c7a5533b43..af3fd23ff9 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c @@ -24,16 +24,18 @@ sc_addr sc_memory_transaction_arc_new( sc_addr const beg, sc_addr const end) { - sc_element * beg_new_version; - sc_element * end_new_version; - - sc_addr beg_new_version_addr = SC_ADDR_EMPTY; - beg_new_version = sc_storage_allocate_new_element(txn->ctx, &beg_new_version_addr); - sc_storage_get_element_by_addr(beg, &beg_new_version); - - sc_addr end_new_version_addr = SC_ADDR_EMPTY; - end_new_version = sc_storage_allocate_new_element(txn->ctx, &end_new_version_addr); - sc_storage_get_element_by_addr(beg, &end_new_version); + sc_element_data * beg_new_version = null_ptr; + sc_storage_get_element_data_by_addr(beg, &beg_new_version); + sc_element_data * end_new_version = null_ptr; + sc_storage_get_element_data_by_addr(beg, &end_new_version); + + sc_element * beg_el = null_ptr; + sc_storage_get_element_by_addr(beg, &beg_el); + sc_segment * txn_buffer = beg_el->transaction_buffer; + + sc_element * end_el = null_ptr; + sc_storage_get_element_by_addr(beg, &end_el); + sc_segment * txn_buffer = end_el->transaction_buffer; sc_addr const allocated_addr = sc_memory_arc_new(txn->ctx, type, beg_new_version_addr, end_new_version_addr); sc_transaction_element_new(txn, &allocated_addr); diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c index 5a920af55f..3aebeb202d 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c @@ -130,7 +130,7 @@ sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer const * buffer, sc_bool sc_transaction_buffer_modified_add( sc_transaction_buffer const * buffer, sc_addr const * addr, - sc_element const * new_element_data) + sc_element_data const * new_element_data) { if (buffer == null_ptr || buffer->modified_elements == null_ptr) return SC_FALSE; @@ -142,41 +142,25 @@ sc_bool sc_transaction_buffer_modified_add( if (sc_storage_get_element_by_addr(*addr, &element) != SC_RESULT_OK || element == null_ptr) return SC_FALSE; - if (element->version_history == null_ptr) - { - element->version_history = sc_version_segment_new(); - if (element->version_history == null_ptr) - return SC_FALSE; - } - - sc_version_segment * seg = element->version_history; - - sc_monitor * monitor = sc_monitor_table_get_monitor_for_addr(buffer->monitor_table, *addr); - if (monitor == null_ptr) + sc_element_data * snapshot = sc_mem_new(sc_element_data, 1); + if (snapshot == null_ptr) return SC_FALSE; + *snapshot = *new_element_data; - sc_monitor_acquire_write(monitor); - - sc_uint64 const new_version_id = seg->latest_version ? seg->latest_version->version_id + 1 : 0; - - sc_element_version * new_ver = - sc_version_segment_add(seg, new_element_data, new_version_id, buffer->transaction_id, seg->latest_version); - if (new_ver == null_ptr) + sc_pair * pair = sc_make_pair((void *)(uintptr_t)SC_ADDR_LOCAL_TO_INT(*addr), (void *)snapshot); + if (pair == null_ptr) { - sc_monitor_release_write(monitor); + sc_mem_free(snapshot); return SC_FALSE; } - seg->latest_version = new_ver; - - sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); - if (sc_list_push_back(buffer->modified_elements, (void *)(uintptr_t)addr_hash) == null_ptr) + if (sc_list_push_back(buffer->modified_elements, pair) == null_ptr) { - sc_monitor_release_write(monitor); + sc_mem_free(snapshot); + sc_mem_free(pair); return SC_FALSE; } - sc_monitor_release_write(monitor); return SC_TRUE; } diff --git a/sc-memory/sc-core/src/sc-store/sc_element.h b/sc-memory/sc-core/src/sc-store/sc_element.h index cbd7a80dd0..c76d2a32ad 100644 --- a/sc-memory/sc-core/src/sc-store/sc_element.h +++ b/sc-memory/sc-core/src/sc-store/sc_element.h @@ -69,7 +69,6 @@ struct _sc_element sc_uint32 outgoing_arcs_count; sc_version_segment * version_history; - sc_version_segment * transaction_buffer; }; #endif diff --git a/sc-memory/sc-core/src/sc-store/sc_version_segment.h b/sc-memory/sc-core/src/sc-store/sc_version_segment.h index 70dd7d5e15..68d65100f6 100644 --- a/sc-memory/sc-core/src/sc-store/sc_version_segment.h +++ b/sc-memory/sc-core/src/sc-store/sc_version_segment.h @@ -13,7 +13,7 @@ typedef struct sc_version_segment sc_element_version versions[SC_VERSION_SEGMENT_SIZE]; sc_addr_offset count; sc_monitor monitor; - sc_element_version* latest_version; + sc_element_version * latest_version; } sc_version_segment; sc_version_segment * sc_version_segment_new(void); @@ -22,7 +22,7 @@ void sc_version_segment_free(sc_version_segment * segment); sc_element_version * sc_version_segment_add( sc_version_segment * segment, - sc_element const * data, + sc_element_data const * data, sc_uint64 version_id, sc_uint64 transaction_id, sc_element_version * parent); From 271ad889983a2191ff957d1a6ac5fc10cdb0d918 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 7 May 2025 21:47:34 +0300 Subject: [PATCH 37/51] Add sc_storage_get_element_data_by_addr --- sc-memory/sc-core/src/sc-store/sc_storage.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sc-memory/sc-core/src/sc-store/sc_storage.c b/sc-memory/sc-core/src/sc-store/sc_storage.c index 36c7594bdf..1a708d9aa8 100644 --- a/sc-memory/sc-core/src/sc-store/sc_storage.c +++ b/sc-memory/sc-core/src/sc-store/sc_storage.c @@ -173,6 +173,26 @@ sc_result sc_storage_get_element_by_addr(sc_addr addr, sc_element ** el) return result; } +sc_result sc_storage_get_element_data_by_addr(sc_addr addr, sc_element_data * el_data) +{ + sc_element * el = null_ptr; + + if (sc_storage_get_element_by_addr(addr, &el) != SC_RESULT_OK || el == null_ptr) + return SC_RESULT_ERROR; + + el_data->flags = el->flags; + el_data->first_out_arc = el->first_out_arc; + el_data->first_in_arc = el->first_in_arc; +#ifdef SC_OPTIMIZE_SEARCHING_INCOMING_CONNECTORS_FROM_STRUCTURES + el_data->first_in_arc_from_structure = el->first_in_arc_from_structure; +#endif + el_data->arc = el->arc; + el_data->incoming_arcs_count = el->incoming_arcs_count; + el_data->outgoing_arcs_count = el->outgoing_arcs_count; + + return SC_RESULT_OK; +} + sc_result sc_storage_free_element(sc_addr addr) { sc_result result = SC_RESULT_ERROR_ADDR_IS_NOT_VALID; From 21f83c705bda8020ae04b5f3f2e47969bdd94cbd Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 7 May 2025 22:12:32 +0300 Subject: [PATCH 38/51] Fix cyclic inclusion of file headers --- .../src/sc-store/sc-transaction/sc_element_version.c | 2 +- .../src/sc-store/sc-transaction/sc_element_version.h | 3 ++- .../sc-transaction/sc_memory_transaction_operations.c | 7 +++---- .../src/sc-store/sc-transaction/sc_transaction_buffer.h | 2 +- sc-memory/sc-core/src/sc-store/sc_element.h | 7 ++++--- sc-memory/sc-core/src/sc-store/sc_storage.c | 4 +++- sc-memory/sc-core/src/sc-store/sc_storage_private.h | 3 +++ sc-memory/sc-core/src/sc-store/sc_version_segment.h | 2 +- 8 files changed, 18 insertions(+), 12 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c index a7fa134ee4..d1fef6f175 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c @@ -4,7 +4,7 @@ sc_element_version * sc_element_create_new_version( sc_element_version * parent, - sc_element const * new_element_data, + sc_element_data const * new_element_data, sc_uint64 const version_id, sc_uint64 const transaction_id) { diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h index 7370d8f6b3..b38082bc40 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h @@ -1,5 +1,6 @@ #ifndef SC_ELEMENT_VERSION_H #define SC_ELEMENT_VERSION_H + #include "sc-core/sc_types.h" #include "sc-store/sc_element.h" @@ -25,7 +26,7 @@ typedef struct sc_element_version sc_uint64 version_id; sc_uint64 transaction_id; struct sc_element_version * parent_version; - sc_bool is_committed; // redundant? + sc_bool is_committed; // redundant? } sc_element_version; sc_element_version * sc_element_create_new_version( diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c index af3fd23ff9..f98ef2e622 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c @@ -25,17 +25,16 @@ sc_addr sc_memory_transaction_arc_new( sc_addr const end) { sc_element_data * beg_new_version = null_ptr; - sc_storage_get_element_data_by_addr(beg, &beg_new_version); + sc_storage_get_element_data_by_addr(beg, beg_new_version); + sc_element_data * end_new_version = null_ptr; - sc_storage_get_element_data_by_addr(beg, &end_new_version); + sc_storage_get_element_data_by_addr(beg, end_new_version); sc_element * beg_el = null_ptr; sc_storage_get_element_by_addr(beg, &beg_el); - sc_segment * txn_buffer = beg_el->transaction_buffer; sc_element * end_el = null_ptr; sc_storage_get_element_by_addr(beg, &end_el); - sc_segment * txn_buffer = end_el->transaction_buffer; sc_addr const allocated_addr = sc_memory_arc_new(txn->ctx, type, beg_new_version_addr, end_new_version_addr); sc_transaction_element_new(txn, &allocated_addr); diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h index dca34538cf..61726cffcf 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h @@ -23,7 +23,7 @@ sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer const * buffer, sc_bool sc_transaction_buffer_modified_add( sc_transaction_buffer const * buffer, sc_addr const * addr, - sc_element const * element); + sc_element_data const * element); sc_bool sc_transaction_buffer_removed_add(sc_transaction_buffer const * buffer, sc_addr const * addr); sc_bool sc_transaction_buffer_content_set( sc_transaction_buffer const * buffer, diff --git a/sc-memory/sc-core/src/sc-store/sc_element.h b/sc-memory/sc-core/src/sc-store/sc_element.h index c76d2a32ad..911cbdb629 100644 --- a/sc-memory/sc-core/src/sc-store/sc_element.h +++ b/sc-memory/sc-core/src/sc-store/sc_element.h @@ -7,9 +7,7 @@ #ifndef _sc_element_h_ #define _sc_element_h_ -#include "sc_version_segment.h" - -#include +#include "sc-core/sc_types.h" struct _sc_arc_info { @@ -53,6 +51,9 @@ struct _sc_element_flags sc_states states; }; +struct sc_version_segment; +typedef struct sc_version_segment sc_version_segment; + struct _sc_element { sc_element_flags flags; diff --git a/sc-memory/sc-core/src/sc-store/sc_storage.c b/sc-memory/sc-core/src/sc-store/sc_storage.c index 1a708d9aa8..5060a2d950 100644 --- a/sc-memory/sc-core/src/sc-store/sc_storage.c +++ b/sc-memory/sc-core/src/sc-store/sc_storage.c @@ -22,6 +22,8 @@ #include "sc_storage_private.h" #include "sc_memory_private.h" +#include "sc-transaction/sc_element_version.h" + sc_storage * storage = null_ptr; sc_result sc_storage_initialize(sc_memory_params const * params) @@ -173,7 +175,7 @@ sc_result sc_storage_get_element_by_addr(sc_addr addr, sc_element ** el) return result; } -sc_result sc_storage_get_element_data_by_addr(sc_addr addr, sc_element_data * el_data) +sc_result sc_storage_get_element_data_by_addr(sc_addr const addr, sc_element_data * el_data) { sc_element * el = null_ptr; diff --git a/sc-memory/sc-core/src/sc-store/sc_storage_private.h b/sc-memory/sc-core/src/sc-store/sc_storage_private.h index d0957a05c8..b615e67907 100644 --- a/sc-memory/sc-core/src/sc-store/sc_storage_private.h +++ b/sc-memory/sc-core/src/sc-store/sc_storage_private.h @@ -14,6 +14,7 @@ #include "sc-store/sc_storage_dump_manager.h" #include "sc-store/sc-base/sc_monitor_table_private.h" +#include "sc-transaction/sc_element_version.h" struct _sc_storage { @@ -41,6 +42,8 @@ sc_element * sc_storage_allocate_new_element(sc_memory_context const * ctx, sc_a sc_result sc_storage_get_element_by_addr(sc_addr addr, sc_element ** el); +sc_result sc_storage_get_element_data_by_addr(sc_addr addr, sc_element_data * el_data); + sc_result sc_storage_free_element(sc_addr addr); #endif diff --git a/sc-memory/sc-core/src/sc-store/sc_version_segment.h b/sc-memory/sc-core/src/sc-store/sc_version_segment.h index 68d65100f6..428b5c5f12 100644 --- a/sc-memory/sc-core/src/sc-store/sc_version_segment.h +++ b/sc-memory/sc-core/src/sc-store/sc_version_segment.h @@ -22,7 +22,7 @@ void sc_version_segment_free(sc_version_segment * segment); sc_element_version * sc_version_segment_add( sc_version_segment * segment, - sc_element_data const * data, + sc_element const * data, sc_uint64 version_id, sc_uint64 transaction_id, sc_element_version * parent); From 1a46dac959aa7b03c602cfb26ee76c8dd0963c9d Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 7 May 2025 22:48:07 +0300 Subject: [PATCH 39/51] New_elements list in txn_bufer store sc_element_data --- .../sc-transaction/sc_element_version.c | 5 +++ .../sc-transaction/sc_element_version.h | 2 ++ .../sc_memory_transaction_operations.c | 34 +++++++++++++------ .../sc-store/sc-transaction/sc_transaction.c | 7 ++-- .../sc-store/sc-transaction/sc_transaction.h | 2 +- .../sc-transaction/sc_transaction_buffer.c | 11 ++---- .../sc-transaction/sc_transaction_buffer.h | 2 +- .../units/transaction/test_sc_buffer.cpp | 6 ---- .../units/transaction/test_sc_transaction.cpp | 7 ---- 9 files changed, 37 insertions(+), 39 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c index d1fef6f175..110c4f40a6 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c @@ -2,6 +2,11 @@ #include +sc_element_data * sc_element_data_new() +{ + +} + sc_element_version * sc_element_create_new_version( sc_element_version * parent, sc_element_data const * new_element_data, diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h index b38082bc40..2083e44579 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h @@ -20,6 +20,8 @@ typedef struct sc_element_data sc_uint32 outgoing_arcs_count; } sc_element_data; +sc_element_data * sc_element_data_new(); + typedef struct sc_element_version { sc_element_data const * data; diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c index f98ef2e622..04589da3cc 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c @@ -1,14 +1,31 @@ #include "sc_memory_transaction_operations.h" #include "sc-core/sc_memory.h" -#include "sc-store/sc_element.h" #include "sc-store/sc_storage_private.h" -sc_addr sc_memory_transaction_node_new(sc_transaction const * txn, sc_type const type) +sc_result sc_memory_transaction_node_new(sc_transaction const * txn, sc_type const type) { - sc_addr const allocated_addr = sc_memory_node_new(txn->ctx, type); - sc_transaction_element_new(txn, &allocated_addr); - return allocated_addr; + sc_result result; + + if (sc_type_is_not_node(type) && (!sc_type_is(type, sc_type_const) && !sc_type_is(type, sc_type_var))) + { + result = SC_RESULT_ERROR_ELEMENT_IS_NOT_NODE; + return result; + } + + sc_element_data * data = sc_element_data_new(); + if (data == null_ptr) + { + result = SC_RESULT_ERROR_FULL_MEMORY; + return result; + } + + data->flags.type = sc_type_node | type; + + sc_transaction_element_new(txn, data); + + result = SC_RESULT_OK; + return result; } sc_addr sc_memory_transaction_link_new(sc_transaction const * txn) @@ -36,16 +53,11 @@ sc_addr sc_memory_transaction_arc_new( sc_element * end_el = null_ptr; sc_storage_get_element_by_addr(beg, &end_el); - sc_addr const allocated_addr = sc_memory_arc_new(txn->ctx, type, beg_new_version_addr, end_new_version_addr); - sc_transaction_element_new(txn, &allocated_addr); - - sc_storage_get_element_by_addr(beg_new_version_addr, &beg_new_version); - sc_storage_get_element_by_addr(beg_new_version_addr, &end_new_version); sc_transaction_element_change(&beg, txn, beg_new_version); sc_transaction_element_change(&end, txn, end_new_version); - return allocated_addr; + return; } sc_addr sc_memory_transaction_element_free(sc_transaction const * txn, sc_addr const addr) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index 79f5ec9273..a63ff6a157 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -1,7 +1,6 @@ #include "sc_transaction.h" #include "sc_memory_transaction_manager.h" -#include "sc-store/sc_element.h" #include "sc-store/sc_storage_private.h" #include @@ -62,12 +61,12 @@ void sc_transaction_apply(sc_transaction * txn) {} void sc_transaction_clear(sc_transaction * txn) {} -sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_addr const * addr) +sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_element_data const * data) { - if (txn == null_ptr || addr == null_ptr || txn->transaction_buffer == null_ptr) + if (txn == null_ptr || data == null_ptr || txn->transaction_buffer == null_ptr) return SC_FALSE; - return sc_transaction_buffer_created_add(txn->transaction_buffer, addr); + return sc_transaction_buffer_created_add(txn->transaction_buffer, data); } sc_bool sc_transaction_element_change(sc_addr const * addr, sc_transaction const * txn, sc_element const * new_data) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index 562745ca47..1c795b0be5 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -21,7 +21,7 @@ sc_transaction * sc_transaction_new(sc_uint64 txn_id, sc_memory_context * ctx); void sc_transaction_destroy(sc_transaction * txn); // destroy the given transaction -sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_addr const * addr); +sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_element_data const * data); // Writes information about adding an item to the buffer sc_bool sc_transaction_element_change(sc_addr const * addr, sc_transaction const * txn, sc_element const * new_data); // Writes information about the element change to the buffer diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c index 3aebeb202d..e895924029 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c @@ -109,19 +109,12 @@ void sc_transaction_buffer_destroy(sc_transaction_buffer * transaction_buffer) } } -sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer const * buffer, sc_addr const * addr) +sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer const * buffer, sc_element_data const * data) { if (buffer == null_ptr || buffer->new_elements == null_ptr) return SC_FALSE; - if (SC_ADDR_IS_EMPTY(*addr)) - return SC_FALSE; - - sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); - if (sc_transaction_buffer_contains_created(buffer, addr)) - return SC_TRUE; - - if (sc_list_push_back(buffer->new_elements, (void *)(uintptr_t)addr_hash) == null_ptr) + if (sc_list_push_back(buffer->new_elements, (void*)data) == null_ptr) return SC_FALSE; return SC_TRUE; diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h index 61726cffcf..e472b87a5e 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h @@ -19,7 +19,7 @@ typedef struct sc_transaction_buffer void sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer, sc_uint64 txn_id); void sc_transaction_buffer_destroy(sc_transaction_buffer * transaction_buffer); -sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer const * buffer, sc_addr const * addr); +sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer const * buffer, sc_element_data const * data); sc_bool sc_transaction_buffer_modified_add( sc_transaction_buffer const * buffer, sc_addr const * addr, diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp index 21ec754e43..652bc46e69 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp @@ -47,12 +47,6 @@ TEST_F(ScTransactionBufferTest, CreatedAddTest) { constexpr sc_addr addr = {1, 1}; - EXPECT_TRUE(sc_transaction_buffer_created_add(buffer, &addr)); - EXPECT_EQ(buffer->new_elements->size, 1u); - - constexpr sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); - EXPECT_EQ(buffer->new_elements->begin->data, reinterpret_cast(addr_hash)); - EXPECT_TRUE(sc_transaction_buffer_contains_created(buffer, &addr)); } diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp index 8648c59a41..8ecc6fa5d2 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp @@ -43,14 +43,7 @@ TEST_F(ScTransactionTest, TransactionElementNew) { constexpr sc_addr addr = {1, 2}; - EXPECT_TRUE(sc_transaction_element_new(transaction, &addr)); - EXPECT_TRUE(sc_transaction_buffer_contains_created(transaction->transaction_buffer, &addr)); - EXPECT_FALSE(sc_transaction_element_new(nullptr, &addr)); - EXPECT_FALSE(sc_transaction_element_new(transaction, nullptr)); - - constexpr sc_addr empty_addr = {0, 0}; - EXPECT_FALSE(sc_transaction_element_new(transaction, &empty_addr)); } TEST_F(ScTransactionTest, TransactionElementRemove) From 9e5440d2349e8b81f97aa0c10361e5ee72f4744a Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Thu, 8 May 2025 19:52:06 +0300 Subject: [PATCH 40/51] Txn use element data copy in operations, new elements created immediately in sc-memory, monitor table belongs to manager --- .../sc-transaction/sc_element_version.c | 2 +- .../sc_memory_transaction_manager.h | 1 + .../sc_memory_transaction_operations.c | 102 ++++++++++++------ .../sc-store/sc-transaction/sc_transaction.c | 7 +- .../sc-store/sc-transaction/sc_transaction.h | 2 +- .../sc-transaction/sc_transaction_buffer.c | 25 ++--- .../sc-transaction/sc_transaction_buffer.h | 5 +- sc-memory/sc-core/src/sc-store/sc_storage.c | 10 +- .../sc-core/src/sc-store/sc_storage_private.h | 17 +++ .../units/transaction/test_sc_buffer.cpp | 1 - .../units/transaction/test_sc_transaction.cpp | 2 - 11 files changed, 108 insertions(+), 66 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c index 110c4f40a6..6ac9297ce9 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c @@ -4,7 +4,7 @@ sc_element_data * sc_element_data_new() { - + return sc_mem_new(sc_element_data, 1); } sc_element_version * sc_element_create_new_version( diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h index 80c4a03db3..223425dcec 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h @@ -10,6 +10,7 @@ typedef struct sc_memory_transaction_manager { + sc_monitor_table * monitor_table; sc_queue * transaction_queue; sc_monitor * monitor; sc_mutex * mutex; diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c index 04589da3cc..9f5b94d483 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c @@ -1,5 +1,6 @@ #include "sc_memory_transaction_operations.h" +#include "sc_memory_transaction_manager.h" #include "sc-core/sc_memory.h" #include "sc-store/sc_storage_private.h" @@ -7,57 +8,90 @@ sc_result sc_memory_transaction_node_new(sc_transaction const * txn, sc_type con { sc_result result; - if (sc_type_is_not_node(type) && (!sc_type_is(type, sc_type_const) && !sc_type_is(type, sc_type_var))) - { - result = SC_RESULT_ERROR_ELEMENT_IS_NOT_NODE; - return result; - } - - sc_element_data * data = sc_element_data_new(); - if (data == null_ptr) - { - result = SC_RESULT_ERROR_FULL_MEMORY; - return result; - } - - data->flags.type = sc_type_node | type; - - sc_transaction_element_new(txn, data); + sc_addr const allocated_addr = sc_memory_node_new_ext(txn->ctx, type, &result); + sc_transaction_element_new(txn, &allocated_addr); - result = SC_RESULT_OK; return result; } -sc_addr sc_memory_transaction_link_new(sc_transaction const * txn) +sc_result sc_memory_transaction_link_new(sc_transaction const * txn) { - sc_addr const allocated_addr = sc_memory_link_new(txn->ctx); + sc_result result; + + sc_addr const allocated_addr = sc_memory_link_new_ext(txn->ctx, sc_type_const_node_link, &result); sc_transaction_element_new(txn, &allocated_addr); - return allocated_addr; + + return result; } -sc_addr sc_memory_transaction_arc_new( +sc_result sc_memory_transaction_arc_new( sc_transaction const * txn, sc_type const type, - sc_addr const beg, - sc_addr const end) + sc_addr const beg_addr, + sc_addr const end_addr) { - sc_element_data * beg_new_version = null_ptr; - sc_storage_get_element_data_by_addr(beg, beg_new_version); + sc_result result; - sc_element_data * end_new_version = null_ptr; - sc_storage_get_element_data_by_addr(beg, end_new_version); + sc_addr connector_addr = SC_ADDR_EMPTY; - sc_element * beg_el = null_ptr; - sc_storage_get_element_by_addr(beg, &beg_el); + if (sc_type_is_not_connector(type)) + { + return SC_RESULT_ERROR_ELEMENT_IS_NOT_CONNECTOR; + } - sc_element * end_el = null_ptr; - sc_storage_get_element_by_addr(beg, &end_el); + if (SC_ADDR_IS_EMPTY(beg_addr) || SC_ADDR_IS_EMPTY(end_addr)) + { + return SC_RESULT_ERROR_ADDR_IS_NOT_VALID; + } + + sc_element_data *new_beg_ver = null_ptr, *new_end_ver = null_ptr; + + sc_element * arc_el = sc_storage_allocate_new_element(txn->ctx, &connector_addr); + if (arc_el == null_ptr) + { + return SC_RESULT_ERROR_FULL_MEMORY; + } + + arc_el->flags.type = type; + arc_el->arc.begin = beg_addr; + arc_el->arc.end = end_addr; + sc_bool const is_edge = sc_type_has_subtype(type, sc_type_common_edge); + sc_bool const is_not_loop = SC_ADDR_IS_NOT_EQUAL(beg_addr, end_addr); - sc_transaction_element_change(&beg, txn, beg_new_version); - sc_transaction_element_change(&end, txn, end_new_version); + // try to lock begin and end elements + sc_monitor * beg_monitor = + sc_monitor_table_get_monitor_for_addr(sc_memory_transaction_manager_get()->monitor_table, beg_addr); + sc_monitor * end_monitor = + sc_monitor_table_get_monitor_for_addr(sc_memory_transaction_manager_get()->monitor_table, end_addr); + sc_monitor_acquire_write_n(2, beg_monitor, end_monitor); - return; + result = sc_storage_get_element_data_by_addr(beg_addr, new_beg_ver); + if (result != SC_RESULT_OK) + goto error; + + result = sc_storage_get_element_data_by_addr(end_addr, new_end_ver); + if (result != SC_RESULT_OK) + goto error; + + // lock arcs to change output/input list + sc_storage_make_elements_incident_to_arc( + connector_addr, arc_el, beg_addr, new_beg_ver, end_addr, new_end_ver, SC_FALSE, !is_not_loop); + if (is_edge && is_not_loop) + sc_storage_make_elements_incident_to_arc( + connector_addr, arc_el, end_addr, new_end_ver, beg_addr, new_beg_ver, SC_TRUE, SC_FALSE); + +#ifdef SC_OPTIMIZE_SEARCHING_INCOMING_CONNECTORS_FROM_STRUCTURES + if (sc_type_is_structure_and_arc(new_beg_ver->flags.type, type)) + sc_storage_update_structure_arcs(connector_addr, arc_el, beg_addr, end_addr, new_end_ver); +#endif + + return result; + +error: + sc_storage_free_element(connector_addr); + sc_monitor_release_write_n(2, beg_monitor, end_monitor); + return result; } sc_addr sc_memory_transaction_element_free(sc_transaction const * txn, sc_addr const addr) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index a63ff6a157..79f5ec9273 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -1,6 +1,7 @@ #include "sc_transaction.h" #include "sc_memory_transaction_manager.h" +#include "sc-store/sc_element.h" #include "sc-store/sc_storage_private.h" #include @@ -61,12 +62,12 @@ void sc_transaction_apply(sc_transaction * txn) {} void sc_transaction_clear(sc_transaction * txn) {} -sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_element_data const * data) +sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_addr const * addr) { - if (txn == null_ptr || data == null_ptr || txn->transaction_buffer == null_ptr) + if (txn == null_ptr || addr == null_ptr || txn->transaction_buffer == null_ptr) return SC_FALSE; - return sc_transaction_buffer_created_add(txn->transaction_buffer, data); + return sc_transaction_buffer_created_add(txn->transaction_buffer, addr); } sc_bool sc_transaction_element_change(sc_addr const * addr, sc_transaction const * txn, sc_element const * new_data) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index 1c795b0be5..562745ca47 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -21,7 +21,7 @@ sc_transaction * sc_transaction_new(sc_uint64 txn_id, sc_memory_context * ctx); void sc_transaction_destroy(sc_transaction * txn); // destroy the given transaction -sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_element_data const * data); +sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_addr const * addr); // Writes information about adding an item to the buffer sc_bool sc_transaction_element_change(sc_addr const * addr, sc_transaction const * txn, sc_element const * new_data); // Writes information about the element change to the buffer diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c index e895924029..d063ada42e 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c @@ -36,15 +36,8 @@ void sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer if (!sc_list_init(&transaction_buffer->content_changes)) goto error_deleted_elements; - transaction_buffer->monitor_table = sc_mem_new(sc_monitor_table, 1); - if (transaction_buffer->monitor_table == null_ptr) - goto error_content_changes; - - _sc_monitor_table_init(transaction_buffer->monitor_table); return; -error_content_changes: - sc_list_destroy(transaction_buffer->content_changes); error_deleted_elements: sc_list_destroy(transaction_buffer->deleted_elements); error_modified_elements: @@ -100,21 +93,21 @@ void sc_transaction_buffer_destroy(sc_transaction_buffer * transaction_buffer) sc_list_destroy(transaction_buffer->content_changes); transaction_buffer->content_changes = null_ptr; } - - if (transaction_buffer->monitor_table != null_ptr) - { - _sc_monitor_table_destroy(transaction_buffer->monitor_table); - sc_mem_free(transaction_buffer->monitor_table); - transaction_buffer->monitor_table = null_ptr; - } } -sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer const * buffer, sc_element_data const * data) +sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer const * buffer, sc_addr const * addr) { if (buffer == null_ptr || buffer->new_elements == null_ptr) return SC_FALSE; - if (sc_list_push_back(buffer->new_elements, (void*)data) == null_ptr) + if (SC_ADDR_IS_EMPTY(*addr)) + return SC_FALSE; + + sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); + if (sc_transaction_buffer_contains_created(buffer, addr)) + return SC_TRUE; + + if (sc_list_push_back(buffer->new_elements, (void *)(uintptr_t)addr_hash) == null_ptr) return SC_FALSE; return SC_TRUE; diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h index e472b87a5e..2d0ffc0351 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.h @@ -12,18 +12,17 @@ typedef struct sc_transaction_buffer sc_list * modified_elements; sc_list * deleted_elements; sc_list * content_changes; - sc_monitor_table * monitor_table; sc_uint64 transaction_id; } sc_transaction_buffer; void sc_transaction_buffer_initialize(sc_transaction_buffer * transaction_buffer, sc_uint64 txn_id); void sc_transaction_buffer_destroy(sc_transaction_buffer * transaction_buffer); -sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer const * buffer, sc_element_data const * data); +sc_bool sc_transaction_buffer_created_add(sc_transaction_buffer const * buffer, sc_addr const * addr); sc_bool sc_transaction_buffer_modified_add( sc_transaction_buffer const * buffer, sc_addr const * addr, - sc_element_data const * element); + sc_element_data const * element_data); sc_bool sc_transaction_buffer_removed_add(sc_transaction_buffer const * buffer, sc_addr const * addr); sc_bool sc_transaction_buffer_content_set( sc_transaction_buffer const * buffer, diff --git a/sc-memory/sc-core/src/sc-store/sc_storage.c b/sc-memory/sc-core/src/sc-store/sc_storage.c index 5060a2d950..28dd64a301 100644 --- a/sc-memory/sc-core/src/sc-store/sc_storage.c +++ b/sc-memory/sc-core/src/sc-store/sc_storage.c @@ -942,7 +942,7 @@ sc_addr sc_storage_link_new_ext(sc_memory_context const * ctx, sc_type type, sc_ return addr; } -void _sc_storage_make_elements_incident_to_arc( +void sc_storage_make_elements_incident_to_arc( sc_addr connector_addr, sc_element * arc_el, sc_addr beg_addr, @@ -1012,7 +1012,7 @@ void _sc_storage_make_elements_incident_to_arc( } #ifdef SC_OPTIMIZE_SEARCHING_INCOMING_CONNECTORS_FROM_STRUCTURES -void _sc_storage_update_structure_arcs( +void sc_storage_update_structure_arcs( sc_addr connector_addr, sc_element * arc_el, sc_addr beg_addr, @@ -1101,15 +1101,15 @@ sc_addr sc_storage_arc_new_ext( goto error; // lock arcs to change output/input list - _sc_storage_make_elements_incident_to_arc( + sc_storage_make_elements_incident_to_arc( connector_addr, arc_el, beg_addr, beg_el, end_addr, end_el, SC_FALSE, !is_not_loop); if (is_edge && is_not_loop) - _sc_storage_make_elements_incident_to_arc( + sc_storage_make_elements_incident_to_arc( connector_addr, arc_el, end_addr, end_el, beg_addr, beg_el, SC_TRUE, SC_FALSE); #ifdef SC_OPTIMIZE_SEARCHING_INCOMING_CONNECTORS_FROM_STRUCTURES if (sc_type_is_structure_and_arc(beg_el->flags.type, type)) - _sc_storage_update_structure_arcs(connector_addr, arc_el, beg_addr, end_addr, end_el); + sc_storage_update_structure_arcs(connector_addr, arc_el, beg_addr, end_addr, end_el); #endif // emit events diff --git a/sc-memory/sc-core/src/sc-store/sc_storage_private.h b/sc-memory/sc-core/src/sc-store/sc_storage_private.h index b615e67907..4983679177 100644 --- a/sc-memory/sc-core/src/sc-store/sc_storage_private.h +++ b/sc-memory/sc-core/src/sc-store/sc_storage_private.h @@ -46,4 +46,21 @@ sc_result sc_storage_get_element_data_by_addr(sc_addr addr, sc_element_data * el sc_result sc_storage_free_element(sc_addr addr); +void sc_storage_make_elements_incident_to_arc( + sc_addr connector_addr, + sc_element * arc_el, + sc_addr beg_addr, + sc_element * beg_el, + sc_addr end_addr, + sc_element * end_el, + sc_bool is_reverse, + sc_bool is_loop); + +void sc_storage_update_structure_arcs( + sc_addr connector_addr, + sc_element * arc_el, + sc_addr beg_addr, + sc_addr end_addr, + sc_element * end_el); + #endif diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp index 652bc46e69..99e7a85219 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp @@ -39,7 +39,6 @@ TEST_F(ScTransactionBufferTest, InitializationTest) EXPECT_NE(buffer->modified_elements, nullptr); EXPECT_NE(buffer->deleted_elements, nullptr); EXPECT_NE(buffer->content_changes, nullptr); - EXPECT_NE(buffer->monitor_table, nullptr); EXPECT_EQ(buffer->transaction_id, 1u); } diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp index 8ecc6fa5d2..fa3db1502c 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp @@ -42,8 +42,6 @@ TEST_F(ScTransactionTest, CreationAndDestruction) TEST_F(ScTransactionTest, TransactionElementNew) { constexpr sc_addr addr = {1, 2}; - - } TEST_F(ScTransactionTest, TransactionElementRemove) From 37dd131f6fcdc366f88bb98f2700e61394b5d0cb Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Mon, 12 May 2025 19:17:37 +0300 Subject: [PATCH 41/51] Base txn operations, tests, correct manager init --- .../sc_memory_transaction_manager.c | 18 ++- .../sc_memory_transaction_operations.c | 56 ++++--- .../sc_memory_transaction_operations.h | 6 + .../sc-store/sc-transaction/sc_transaction.c | 2 +- .../sc-store/sc-transaction/sc_transaction.h | 2 +- .../test_sc_memory_transaction_operations.cpp | 144 ++++++++++++++++++ ...fer.cpp => test_sc_transaction_buffer.cpp} | 0 7 files changed, 203 insertions(+), 25 deletions(-) create mode 100644 sc-memory/sc-core/tests/units/transaction/test_sc_memory_transaction_operations.cpp rename sc-memory/sc-core/tests/units/transaction/{test_sc_buffer.cpp => test_sc_transaction_buffer.cpp} (100%) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c index ac87466d51..9a815115a2 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c @@ -1,6 +1,8 @@ #include "sc_memory_transaction_manager.h" #include "sc-store/sc-base/sc_condition_private.h" +#include "sc-store/sc-base/sc_monitor_table.h" +#include "sc-store/sc-base/sc_monitor_table_private.h" #include "sc-store/sc-base/sc_thread.h" #include "sc-store/sc-container/sc_struct_node.h" @@ -31,7 +33,6 @@ sc_result sc_memory_transaction_manager_initialize(sc_memory_transaction_manager { return SC_RESULT_ERROR_FULL_MEMORY; } - sc_queue_init(transaction_manager->transaction_queue); transaction_manager->monitor = sc_mem_new(sc_monitor, 1); @@ -39,7 +40,6 @@ sc_result sc_memory_transaction_manager_initialize(sc_memory_transaction_manager { goto error_cleanup_queue; } - sc_monitor_init(transaction_manager->monitor); transaction_manager->queue_condition = sc_mem_new(sc_condition, 1); @@ -47,7 +47,6 @@ sc_result sc_memory_transaction_manager_initialize(sc_memory_transaction_manager { goto error_cleanup_monitor; } - sc_cond_init(transaction_manager->queue_condition); transaction_manager->mutex = sc_mem_new(sc_mutex, 1); @@ -55,9 +54,15 @@ sc_result sc_memory_transaction_manager_initialize(sc_memory_transaction_manager { goto error_cleanup_condition; } - sc_mutex_init(transaction_manager->mutex); + transaction_manager->monitor_table = sc_mem_new(sc_monitor_table, 1); + if (transaction_manager->monitor_table == null_ptr) + { + goto error_cleanup_mutex; + } + _sc_monitor_table_init(transaction_manager->monitor_table); + if (sc_list_init(&transaction_manager->threads) != SC_RESULT_OK) { return SC_RESULT_ERROR_INVALID_STATE; @@ -86,6 +91,9 @@ sc_result sc_memory_transaction_manager_initialize(sc_memory_transaction_manager transaction_manager->threads = null_ptr; } + sc_mem_free(transaction_manager->monitor_table); + transaction_manager->monitor_table = null_ptr; + error_cleanup_mutex: sc_mutex_destroy(transaction_manager->mutex); sc_mem_free(transaction_manager->mutex); @@ -102,8 +110,6 @@ sc_result sc_memory_transaction_manager_initialize(sc_memory_transaction_manager sc_queue_destroy(transaction_manager->transaction_queue); sc_mem_free(transaction_manager->transaction_queue); -error_cleanup_manager: - sc_mem_free(transaction_manager); transaction_manager = null_ptr; return SC_RESULT_ERROR; diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c index 9f5b94d483..462eda77ff 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c @@ -6,8 +6,10 @@ sc_result sc_memory_transaction_node_new(sc_transaction const * txn, sc_type const type) { - sc_result result; + if (txn == null_ptr) + return SC_RESULT_ERROR_INVALID_PARAMS; + sc_result result; sc_addr const allocated_addr = sc_memory_node_new_ext(txn->ctx, type, &result); sc_transaction_element_new(txn, &allocated_addr); @@ -16,8 +18,10 @@ sc_result sc_memory_transaction_node_new(sc_transaction const * txn, sc_type con sc_result sc_memory_transaction_link_new(sc_transaction const * txn) { - sc_result result; + if (txn == null_ptr) + return SC_RESULT_ERROR_INVALID_PARAMS; + sc_result result; sc_addr const allocated_addr = sc_memory_link_new_ext(txn->ctx, sc_type_const_node_link, &result); sc_transaction_element_new(txn, &allocated_addr); @@ -27,11 +31,13 @@ sc_result sc_memory_transaction_link_new(sc_transaction const * txn) sc_result sc_memory_transaction_arc_new( sc_transaction const * txn, sc_type const type, - sc_addr const beg_addr, - sc_addr const end_addr) + sc_addr * const beg_addr, + sc_addr * const end_addr) { - sc_result result; + if (txn == null_ptr) + return SC_RESULT_ERROR_INVALID_PARAMS; + sc_result result; sc_addr connector_addr = SC_ADDR_EMPTY; if (sc_type_is_not_connector(type)) @@ -39,12 +45,21 @@ sc_result sc_memory_transaction_arc_new( return SC_RESULT_ERROR_ELEMENT_IS_NOT_CONNECTOR; } - if (SC_ADDR_IS_EMPTY(beg_addr) || SC_ADDR_IS_EMPTY(end_addr)) + if (beg_addr == null_ptr || end_addr == null_ptr) + { + return SC_RESULT_ERROR_INVALID_PARAMS; + } + + if (SC_ADDR_IS_EMPTY(*beg_addr) || SC_ADDR_IS_EMPTY(*end_addr)) { return SC_RESULT_ERROR_ADDR_IS_NOT_VALID; } - sc_element_data *new_beg_ver = null_ptr, *new_end_ver = null_ptr; + sc_element_data new_beg_ver_val; + sc_element_data new_end_ver_val; + + sc_element_data *new_beg_ver = &new_beg_ver_val; + sc_element_data *new_end_ver = &new_end_ver_val; sc_element * arc_el = sc_storage_allocate_new_element(txn->ctx, &connector_addr); if (arc_el == null_ptr) @@ -53,39 +68,43 @@ sc_result sc_memory_transaction_arc_new( } arc_el->flags.type = type; - arc_el->arc.begin = beg_addr; - arc_el->arc.end = end_addr; + arc_el->arc.begin = *beg_addr; + arc_el->arc.end = *end_addr; sc_bool const is_edge = sc_type_has_subtype(type, sc_type_common_edge); - sc_bool const is_not_loop = SC_ADDR_IS_NOT_EQUAL(beg_addr, end_addr); + sc_bool const is_not_loop = SC_ADDR_IS_NOT_EQUAL(*beg_addr, *end_addr); // try to lock begin and end elements sc_monitor * beg_monitor = - sc_monitor_table_get_monitor_for_addr(sc_memory_transaction_manager_get()->monitor_table, beg_addr); + sc_monitor_table_get_monitor_for_addr(sc_memory_transaction_manager_get()->monitor_table, *beg_addr); sc_monitor * end_monitor = - sc_monitor_table_get_monitor_for_addr(sc_memory_transaction_manager_get()->monitor_table, end_addr); + sc_monitor_table_get_monitor_for_addr(sc_memory_transaction_manager_get()->monitor_table, *end_addr); sc_monitor_acquire_write_n(2, beg_monitor, end_monitor); - result = sc_storage_get_element_data_by_addr(beg_addr, new_beg_ver); + result = sc_storage_get_element_data_by_addr(*beg_addr, new_beg_ver); if (result != SC_RESULT_OK) goto error; - result = sc_storage_get_element_data_by_addr(end_addr, new_end_ver); + result = sc_storage_get_element_data_by_addr(*end_addr, new_end_ver); if (result != SC_RESULT_OK) goto error; // lock arcs to change output/input list sc_storage_make_elements_incident_to_arc( - connector_addr, arc_el, beg_addr, new_beg_ver, end_addr, new_end_ver, SC_FALSE, !is_not_loop); + connector_addr, arc_el, *beg_addr, (sc_element*)new_beg_ver, *end_addr, (sc_element*)new_end_ver, SC_FALSE, !is_not_loop); if (is_edge && is_not_loop) sc_storage_make_elements_incident_to_arc( - connector_addr, arc_el, end_addr, new_end_ver, beg_addr, new_beg_ver, SC_TRUE, SC_FALSE); + connector_addr, arc_el, *end_addr, (sc_element*)new_end_ver, *beg_addr, (sc_element*)new_beg_ver, SC_TRUE, SC_FALSE); #ifdef SC_OPTIMIZE_SEARCHING_INCOMING_CONNECTORS_FROM_STRUCTURES if (sc_type_is_structure_and_arc(new_beg_ver->flags.type, type)) - sc_storage_update_structure_arcs(connector_addr, arc_el, beg_addr, end_addr, new_end_ver); + sc_storage_update_structure_arcs(connector_addr, arc_el, *beg_addr, *end_addr, (sc_element*)new_end_ver); #endif + sc_transaction_element_new(txn, &connector_addr); + sc_transaction_element_change(txn, beg_addr, new_beg_ver); + sc_transaction_element_change(txn, end_addr, new_end_ver); + return result; error: @@ -96,6 +115,9 @@ sc_result sc_memory_transaction_arc_new( sc_addr sc_memory_transaction_element_free(sc_transaction const * txn, sc_addr const addr) { + if (txn == null_ptr) + return addr; + sc_transaction_element_remove(txn, &addr); return addr; } \ No newline at end of file diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h index 0e12399130..ef04a33cb3 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h @@ -3,4 +3,10 @@ #include "sc_transaction.h" +sc_result sc_memory_transaction_node_new(sc_transaction const * txn, sc_type type); +sc_result sc_memory_transaction_link_new(sc_transaction const * txn); +sc_result sc_memory_transaction_arc_new(sc_transaction const * txn, sc_type type, sc_addr * beg_addr, sc_addr * end_addr); +sc_addr sc_memory_transaction_element_free(sc_transaction const * txn, sc_addr addr); + + #endif // SC_MEMORY_TRANSACTION_OPERATIONS_H diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index 79f5ec9273..19e6b0ff5a 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -70,7 +70,7 @@ sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_addr const * a return sc_transaction_buffer_created_add(txn->transaction_buffer, addr); } -sc_bool sc_transaction_element_change(sc_addr const * addr, sc_transaction const * txn, sc_element const * new_data) +sc_bool sc_transaction_element_change(sc_transaction const * txn, sc_addr const * addr, sc_element_data const * new_data) { if (txn == null_ptr || addr == null_ptr || txn->transaction_buffer == null_ptr) return SC_FALSE; diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index 562745ca47..d8cc58a844 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -23,7 +23,7 @@ void sc_transaction_destroy(sc_transaction * txn); sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_addr const * addr); // Writes information about adding an item to the buffer -sc_bool sc_transaction_element_change(sc_addr const * addr, sc_transaction const * txn, sc_element const * new_data); +sc_bool sc_transaction_element_change(sc_transaction const * txn, sc_addr const * addr, sc_element_data const * new_data); // Writes information about the element change to the buffer sc_bool sc_transaction_element_remove(sc_transaction const * txn, sc_addr const * addr); // Writes the deletion information to the buffer diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_memory_transaction_operations.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_memory_transaction_operations.cpp new file mode 100644 index 0000000000..abfaadf01a --- /dev/null +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_memory_transaction_operations.cpp @@ -0,0 +1,144 @@ +#include +#include + +extern "C" { +#include +#include "sc-store/sc-container/sc_pair.h" +#include "sc-store/sc_storage_private.h" +#include "sc-store/sc_version_segment.h" +#include "sc-store/sc-container/sc_struct_node.h" +#include +} + +class ScMemoryTransactionArcNewTest : public ScMemoryTest { +protected: + sc_transaction *transaction = nullptr; + sc_addr beg_addr = {}, end_addr = {}; + + void SetUp() override { + ScMemoryTest::SetUp(); + beg_addr = sc_memory_node_new(m_ctx->GetRealContext(), sc_type_node); + end_addr = sc_memory_node_new(m_ctx->GetRealContext(), sc_type_node); + + transaction = sc_transaction_new(123, m_ctx->GetRealContext()); + ASSERT_NE(transaction, nullptr); + } + + void TearDown() override { + if (transaction) + sc_transaction_destroy(transaction); + ScMemoryTest::TearDown(); + } +}; + +sc_result sc_transaction_buffer_find_new_element(sc_transaction_buffer const * buffer, sc_addr const * addr, sc_uint32 * out_hash) +{ + if (buffer == null_ptr || buffer->new_elements == null_ptr || addr == null_ptr || out_hash == null_ptr) + return SC_RESULT_ERROR_INVALID_PARAMS; + + if (SC_ADDR_IS_EMPTY(*addr)) + return SC_RESULT_ERROR_ADDR_IS_NOT_VALID; + + sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); + sc_iterator * it = sc_list_iterator(buffer->new_elements); + while (sc_iterator_next(it)) + { + sc_uint32 const stored_hash = (uintptr_t)sc_iterator_get(it); + if (stored_hash == addr_hash) + { + *out_hash = stored_hash; + sc_iterator_destroy(it); + return SC_RESULT_OK; + } + } + sc_iterator_destroy(it); + + return SC_RESULT_ERROR_NOT_FOUND; +} + +sc_result sc_transaction_buffer_find_modified_element(sc_transaction_buffer const * buffer, sc_addr const * addr, sc_element_data ** out_data) +{ + if (buffer == null_ptr || buffer->modified_elements == null_ptr || addr == null_ptr || out_data == null_ptr) + return SC_RESULT_ERROR_INVALID_PARAMS; + + if (SC_ADDR_IS_EMPTY(*addr)) + return SC_RESULT_ERROR_ADDR_IS_NOT_VALID; + + sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); + sc_iterator * it = sc_list_iterator(buffer->modified_elements); + while (sc_iterator_next(it)) + { + auto pair = static_cast(sc_iterator_get(it)); + + sc_uint32 stored_hash = reinterpret_cast(pair->first); + if (stored_hash == addr_hash) + { + *out_data = static_cast(pair->second); + sc_iterator_destroy(it); + return SC_RESULT_OK; + } + } + sc_iterator_destroy(it); + + return SC_RESULT_ERROR_NOT_FOUND; +} + +TEST_F(ScMemoryTransactionArcNewTest, ValidParams) { + EXPECT_EQ(sc_memory_transaction_arc_new(transaction, sc_type_pos_arc, &beg_addr, &end_addr), SC_RESULT_OK); +} + +TEST_F(ScMemoryTransactionArcNewTest, InvalidAddress) { + sc_addr empty_addr = SC_ADDR_EMPTY; + + EXPECT_EQ(sc_memory_transaction_arc_new(transaction, sc_type_pos_arc, &empty_addr, &end_addr), + SC_RESULT_ERROR_ADDR_IS_NOT_VALID); + EXPECT_EQ(sc_memory_transaction_arc_new(transaction, sc_type_pos_arc, &beg_addr, &empty_addr), + SC_RESULT_ERROR_ADDR_IS_NOT_VALID); +} + +TEST_F(ScMemoryTransactionArcNewTest, InvalidType) { + EXPECT_EQ(sc_memory_transaction_arc_new(transaction, sc_type_node, &beg_addr, &end_addr), + SC_RESULT_ERROR_ELEMENT_IS_NOT_CONNECTOR); +} + +TEST_F(ScMemoryTransactionArcNewTest, NullParams) { + EXPECT_EQ(sc_memory_transaction_arc_new(nullptr, sc_type_pos_arc, &beg_addr, &end_addr), + SC_RESULT_ERROR_INVALID_PARAMS); + EXPECT_EQ(sc_memory_transaction_arc_new(transaction, sc_type_pos_arc, nullptr, &end_addr), + SC_RESULT_ERROR_INVALID_PARAMS); + EXPECT_EQ(sc_memory_transaction_arc_new(transaction, sc_type_pos_arc, &beg_addr, nullptr), + SC_RESULT_ERROR_INVALID_PARAMS); +} + +TEST_F(ScMemoryTransactionArcNewTest, BufferCheck) +{ + sc_element * beg_el_before = nullptr; + sc_storage_get_element_by_addr(beg_addr, &beg_el_before); + + sc_element * end_el_before = nullptr; + sc_storage_get_element_by_addr(end_addr, &end_el_before); + + EXPECT_EQ(sc_memory_transaction_arc_new(transaction, sc_type_pos_arc, &beg_addr, &end_addr), SC_RESULT_OK); + + sc_element * beg_el_after = nullptr; + sc_storage_get_element_by_addr(beg_addr, &beg_el_after); + + sc_element * end_el_after = nullptr; + sc_storage_get_element_by_addr(end_addr, &end_el_after); + + EXPECT_EQ(beg_el_after->outgoing_arcs_count, beg_el_after->outgoing_arcs_count); + EXPECT_EQ(beg_el_after->incoming_arcs_count, beg_el_after->incoming_arcs_count); + + sc_element_data * beg_el_ver = nullptr; + sc_transaction_buffer_find_modified_element(transaction->transaction_buffer, &beg_addr, &beg_el_ver); + + sc_element_data * end_el_ver = nullptr; + sc_transaction_buffer_find_modified_element(transaction->transaction_buffer, &end_addr, &end_el_ver); + + const size_t beg_diff = beg_el_ver->outgoing_arcs_count - beg_el_after->outgoing_arcs_count; + const size_t end_diff = end_el_ver->incoming_arcs_count - end_el_after->incoming_arcs_count; + + EXPECT_EQ(beg_diff, 1); + EXPECT_EQ(end_diff, 1); +} + diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_buffer.cpp similarity index 100% rename from sc-memory/sc-core/tests/units/transaction/test_sc_buffer.cpp rename to sc-memory/sc-core/tests/units/transaction/test_sc_transaction_buffer.cpp From a32c7e44a6e248211d1c3c3f47f0f533fb275e5d Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Mon, 12 May 2025 23:25:48 +0300 Subject: [PATCH 42/51] Transaction validation process logic --- .../sc_memory_transaction_manager.c | 63 +++++++++++++- .../sc_memory_transaction_manager.h | 5 ++ .../sc_memory_transaction_operations.c | 5 ++ .../sc-store/sc-transaction/sc_transaction.c | 87 +++++++++++++++++-- .../sc-store/sc-transaction/sc_transaction.h | 6 +- .../sc-transaction/sc_transaction_buffer.c | 2 +- 6 files changed, 157 insertions(+), 11 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c index 9a815115a2..ca8c7d7535 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c @@ -1,5 +1,6 @@ #include "sc_memory_transaction_manager.h" +#include "sc-store/sc_storage.h" #include "sc-store/sc-base/sc_condition_private.h" #include "sc-store/sc-base/sc_monitor_table.h" #include "sc-store/sc-base/sc_monitor_table_private.h" @@ -204,7 +205,35 @@ void sc_transaction_manager_transaction_add(sc_transaction * txn) sc_cond_signal(transaction_manager->queue_condition); } -void sc_transaction_manager_transaction_execute(sc_transaction * txn) {} +void sc_transaction_manager_block_elements(sc_hash_table * elements) +{ + // block with monitor table +} + +void sc_transaction_manager_unblock_elements(sc_hash_table * elements) +{ + // unlock +} + +void sc_transaction_manager_transaction_execute(sc_transaction * txn) +{ + sc_monitor_acquire_read(transaction_manager->monitor); + + if (!sc_transaction_elements_intersect(txn, transaction_manager->processed_elements)) + { + sc_transaction_manager_block_elements(txn->elements); + + if (sc_transaction_validate(txn)) + { + sc_transaction_apply(txn); + } + + sc_transaction_manager_unblock_elements(txn->elements); + } + + sc_transaction_manager_transaction_add(txn); + +} void sc_transaction_handler() { @@ -239,3 +268,35 @@ void sc_transaction_handler() sc_monitor_release_read(transaction_manager->monitor); } + +sc_bool sc_transaction_elements_intersect(sc_transaction const * txn, sc_hash_table * processed_elements) +{ + if (txn == null_ptr || txn->elements == null_ptr || processed_elements == null_ptr) + return SC_FALSE; + + sc_hash_table * smaller_table = sc_hash_table_size(txn->elements) <= sc_hash_table_size(processed_elements) + ? txn->elements + : processed_elements; + sc_hash_table * larger_table = smaller_table == txn->elements ? processed_elements : txn->elements; + + sc_monitor * txn_monitor = txn->monitor; + sc_monitor * processed_monitor = sc_memory_transaction_manager_get()->monitor; + + sc_monitor_acquire_read_n(2, txn_monitor, processed_monitor); + + sc_hash_table_iterator iter; + sc_hash_table_iterator_init(&iter, smaller_table); + void *key, *value; + + while (sc_hash_table_iterator_next(&iter, &key, &value)) + { + if (sc_hash_table_get(larger_table, key) != null_ptr) + { + sc_monitor_release_read_n(2, txn_monitor, processed_monitor); + return SC_TRUE; + } + } + + sc_monitor_release_read_n(2, txn_monitor, processed_monitor); + return SC_FALSE; +} \ No newline at end of file diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h index 223425dcec..5f2eb0e82f 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.h @@ -1,6 +1,7 @@ #ifndef SC_TRANSACTION_MANAGER_H #define SC_TRANSACTION_MANAGER_H +#include "sc-store/sc-container/sc_hash_table.h" #include #include @@ -19,6 +20,8 @@ typedef struct sc_memory_transaction_manager sc_condition * queue_condition; sc_uint32 txn_count; sc_bool should_stop; + + sc_hash_table * processed_elements; } sc_memory_transaction_manager; sc_result sc_memory_transaction_manager_initialize(sc_memory_transaction_manager * manager); @@ -47,4 +50,6 @@ void sc_transaction_handler(); void sc_transaction_manager_destroy(); // destroy the transaction manager +sc_bool sc_transaction_elements_intersect(sc_transaction const * txn, sc_hash_table * processed_elements); + #endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c index 462eda77ff..1d0f3d29df 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c @@ -81,6 +81,11 @@ sc_result sc_memory_transaction_arc_new( sc_monitor_table_get_monitor_for_addr(sc_memory_transaction_manager_get()->monitor_table, *end_addr); sc_monitor_acquire_write_n(2, beg_monitor, end_monitor); + if (beg_monitor == null_ptr) + return SC_RESULT_ERROR; + if (end_monitor == null_ptr) + return SC_RESULT_ERROR; + result = sc_storage_get_element_data_by_addr(*beg_addr, new_beg_ver); if (result != SC_RESULT_OK) goto error; diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index 19e6b0ff5a..0d3840835c 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -3,29 +3,57 @@ #include "sc_memory_transaction_manager.h" #include "sc-store/sc_element.h" #include "sc-store/sc_storage_private.h" +#include "sc-store/sc-container/sc_pair.h" #include sc_transaction * sc_transaction_new(sc_uint64 const txn_id, sc_memory_context * ctx) { - sc_transaction * txn = sc_mem_new(sc_transaction, 1); + sc_transaction * txn = _sc_mem_new(sizeof(sc_transaction)); if (txn == null_ptr) return null_ptr; + if (ctx == null_ptr) + { + sc_mem_free(txn); + return null_ptr; + } + txn->transaction_id = txn_id; txn->is_committed = SC_FALSE; txn->ctx = ctx; - txn->transaction_buffer = sc_mem_new(sc_transaction_buffer, 1); + txn->monitor = _sc_mem_new(sizeof(sc_monitor)); + if (txn->monitor == null_ptr) + { + sc_mem_free(txn); + return null_ptr; + } + sc_monitor_init(txn->monitor); + + txn->transaction_buffer = _sc_mem_new(sizeof(sc_transaction_buffer)); if (txn->transaction_buffer == null_ptr) { + sc_monitor_destroy(txn->monitor); + sc_mem_free(txn->monitor); sc_mem_free(txn); return null_ptr; } sc_transaction_buffer_initialize(txn->transaction_buffer, txn_id); - if (!sc_list_init(&txn->elements)) + txn->elements = sc_hash_table_init( + sc_hash_table_default_hash_func, + sc_hash_table_default_equal_func, + null_ptr, + null_ptr + ); + if (txn->elements == null_ptr) { + sc_transaction_buffer_destroy(txn->transaction_buffer); + sc_mem_free(txn->transaction_buffer); + sc_monitor_destroy(txn->monitor); + sc_mem_free(txn->monitor); + sc_mem_free(txn); return null_ptr; } @@ -36,8 +64,20 @@ void sc_transaction_destroy(sc_transaction * txn) { if (txn != null_ptr) { - sc_list_destroy(txn->elements); - + if (txn->transaction_buffer != null_ptr) + { + sc_transaction_buffer_destroy(txn->transaction_buffer); + sc_mem_free(txn->transaction_buffer); + } + if (txn->elements != null_ptr) + { + sc_hash_table_destroy(txn->elements); + } + if (txn->monitor != null_ptr) + { + sc_monitor_destroy(txn->monitor); + sc_mem_free(txn->monitor); + } sc_mem_free(txn); } } @@ -51,9 +91,36 @@ void sc_transaction_commit(sc_transaction * txn) void sc_transaction_rollback(sc_transaction * txn) {} +sc_bool _sc_transaction_validate_modify_elements(sc_list const * elements_list) +{ + sc_iterator * it = sc_list_iterator(elements_list); + if (sc_iterator_next(it)) + { + sc_pair const * pair = sc_iterator_get(it); + + sc_addr const * element_addr = pair->first; + sc_element_data const * snapshot = pair->second; + + sc_element * element = null_ptr; + sc_storage_get_element_by_addr(*element_addr, &element); + + sc_element_data * current_data = null_ptr; + sc_storage_get_element_data_by_addr(*element_addr, current_data); + + if (current_data != snapshot) + { + return SC_FALSE; + } + } + + return SC_TRUE; +} + sc_bool sc_transaction_validate(sc_transaction * txn) { - return SC_FALSE; + if (!_sc_transaction_validate_modify_elements(txn->transaction_buffer->modified_elements)) return SC_FALSE; + + return SC_TRUE; } void sc_transaction_merge(sc_transaction * txn) {} @@ -67,6 +134,8 @@ sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_addr const * a if (txn == null_ptr || addr == null_ptr || txn->transaction_buffer == null_ptr) return SC_FALSE; + sc_hash_table_insert(txn->elements, (void*)addr, null_ptr); + return sc_transaction_buffer_created_add(txn->transaction_buffer, addr); } @@ -78,6 +147,8 @@ sc_bool sc_transaction_element_change(sc_transaction const * txn, sc_addr const if (SC_ADDR_IS_EMPTY(*addr)) return SC_FALSE; + sc_hash_table_insert(txn->elements, (void*)addr, null_ptr); + return sc_transaction_buffer_modified_add(txn->transaction_buffer, addr, new_data); } @@ -89,6 +160,8 @@ sc_bool sc_transaction_element_remove(sc_transaction const * txn, sc_addr const if (SC_ADDR_IS_EMPTY(*addr)) return SC_FALSE; + sc_hash_table_insert(txn->elements, (void*)addr, null_ptr); + return sc_transaction_buffer_removed_add(txn->transaction_buffer, addr); } @@ -100,5 +173,7 @@ sc_bool sc_transaction_element_content_set(sc_transaction const * txn, sc_addr c if (SC_ADDR_IS_EMPTY(*addr)) return SC_FALSE; + sc_hash_table_insert(txn->elements, (void*)addr, null_ptr); + return sc_transaction_buffer_content_set(txn->transaction_buffer, addr, content); } \ No newline at end of file diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index d8cc58a844..93df69a880 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -1,17 +1,17 @@ #ifndef SC_TRANSACTION_H #define SC_TRANSACTION_H +#include "sc-store/sc-container/sc_hash_table.h" #include #include - #include -#include typedef struct sc_transaction { sc_uint64 transaction_id; sc_bool is_committed; - sc_list * elements; + sc_hash_table * elements; + sc_monitor * monitor; sc_transaction_buffer * transaction_buffer; sc_memory_context * ctx; } sc_transaction; diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c index d063ada42e..c694be24ec 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c @@ -133,7 +133,7 @@ sc_bool sc_transaction_buffer_modified_add( return SC_FALSE; *snapshot = *new_element_data; - sc_pair * pair = sc_make_pair((void *)(uintptr_t)SC_ADDR_LOCAL_TO_INT(*addr), (void *)snapshot); + sc_pair * pair = sc_make_pair((void *)(uintptr_t)SC_ADDR_LOCAL_TO_INT(*addr), snapshot); if (pair == null_ptr) { sc_mem_free(snapshot); From 43a195989389b262d61c144377e8fb12d7f5238b Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Tue, 13 May 2025 23:56:39 +0300 Subject: [PATCH 43/51] Txn commit logic, fix sc-element init, txn state, add version logic (basic: add to current) --- .../sc-transaction/sc_element_version.c | 9 +- .../sc-transaction/sc_element_version.h | 3 +- .../sc_memory_transaction_manager.c | 28 ++++-- .../sc-store/sc-transaction/sc_transaction.c | 97 ++++++++++++++++--- .../sc-store/sc-transaction/sc_transaction.h | 17 ++-- sc-memory/sc-core/src/sc-store/sc_storage.c | 5 + .../sc-core/src/sc-store/sc_version_segment.c | 53 +++++----- .../sc-core/src/sc-store/sc_version_segment.h | 15 ++- .../test_sc_memory_transaction_operations.cpp | 30 +++++- 9 files changed, 188 insertions(+), 69 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c index 6ac9297ce9..34cd626fab 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c @@ -1,5 +1,7 @@ #include "sc_element_version.h" +#include "sc-store/sc_version_segment.h" + #include sc_element_data * sc_element_data_new() @@ -8,9 +10,8 @@ sc_element_data * sc_element_data_new() } sc_element_version * sc_element_create_new_version( - sc_element_version * parent, + sc_element * element, sc_element_data const * new_element_data, - sc_uint64 const version_id, sc_uint64 const transaction_id) { if (new_element_data == null_ptr) @@ -21,9 +22,9 @@ sc_element_version * sc_element_create_new_version( return null_ptr; new_version->data = new_element_data; - new_version->version_id = version_id; new_version->transaction_id = transaction_id; - new_version->parent_version = parent; + new_version->version_id = sc_version_segment_get_next_version_id(element); + new_version->parent_version = element->version_history->current_version; new_version->is_committed = SC_FALSE; return new_version; diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h index 2083e44579..cebcf19545 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h @@ -32,9 +32,8 @@ typedef struct sc_element_version } sc_element_version; sc_element_version * sc_element_create_new_version( - sc_element_version * parent, + sc_element * element, sc_element_data const * new_element_data, - sc_uint64 version_id, sc_uint64 transaction_id); #endif diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c index ca8c7d7535..4b91511ea5 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c @@ -194,6 +194,16 @@ sc_transaction * sc_memory_transaction_new(sc_memory_context * ctx) return sc_transaction_new(txn_id, ctx); } +sc_result sc_memory_transaction_commit(sc_transaction * txn) +{ + if (txn == null_ptr) + return SC_RESULT_ERROR_INVALID_PARAMS; + + sc_transaction_manager_transaction_add(txn); + return SC_RESULT_OK; +} + + void sc_transaction_manager_transaction_add(sc_transaction * txn) { sc_monitor_acquire_write(transaction_manager->monitor); @@ -217,8 +227,6 @@ void sc_transaction_manager_unblock_elements(sc_hash_table * elements) void sc_transaction_manager_transaction_execute(sc_transaction * txn) { - sc_monitor_acquire_read(transaction_manager->monitor); - if (!sc_transaction_elements_intersect(txn, transaction_manager->processed_elements)) { sc_transaction_manager_block_elements(txn->elements); @@ -230,9 +238,8 @@ void sc_transaction_manager_transaction_execute(sc_transaction * txn) sc_transaction_manager_unblock_elements(txn->elements); } - - sc_transaction_manager_transaction_add(txn); - + else + txn->state = SC_TRANSACTION_FAILED; } void sc_transaction_handler() @@ -260,6 +267,8 @@ void sc_transaction_handler() sc_queue_pop(transaction_manager->transaction_queue); sc_transaction_manager_transaction_execute(txn); + + txn->state = SC_TRANSACTION_EXECUTED; } sc_monitor_release_write(transaction_manager->monitor); @@ -282,7 +291,8 @@ sc_bool sc_transaction_elements_intersect(sc_transaction const * txn, sc_hash_ta sc_monitor * txn_monitor = txn->monitor; sc_monitor * processed_monitor = sc_memory_transaction_manager_get()->monitor; - sc_monitor_acquire_read_n(2, txn_monitor, processed_monitor); + sc_monitor_acquire_read(processed_monitor); + sc_monitor_acquire_read(txn_monitor); sc_hash_table_iterator iter; sc_hash_table_iterator_init(&iter, smaller_table); @@ -292,11 +302,13 @@ sc_bool sc_transaction_elements_intersect(sc_transaction const * txn, sc_hash_ta { if (sc_hash_table_get(larger_table, key) != null_ptr) { - sc_monitor_release_read_n(2, txn_monitor, processed_monitor); + sc_monitor_release_read(txn_monitor); + sc_monitor_release_read(processed_monitor); return SC_TRUE; } } - sc_monitor_release_read_n(2, txn_monitor, processed_monitor); + sc_monitor_release_read(txn_monitor); + sc_monitor_release_read(processed_monitor); return SC_FALSE; } \ No newline at end of file diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index 0d3840835c..33abfa5230 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -3,6 +3,7 @@ #include "sc_memory_transaction_manager.h" #include "sc-store/sc_element.h" #include "sc-store/sc_storage_private.h" +#include "sc-store/sc_version_segment.h" #include "sc-store/sc-container/sc_pair.h" #include @@ -22,6 +23,7 @@ sc_transaction * sc_transaction_new(sc_uint64 const txn_id, sc_memory_context * txn->transaction_id = txn_id; txn->is_committed = SC_FALSE; txn->ctx = ctx; + txn->state = SC_TRANSACTION_PENDING; txn->monitor = _sc_mem_new(sizeof(sc_monitor)); if (txn->monitor == null_ptr) @@ -82,32 +84,69 @@ void sc_transaction_destroy(sc_transaction * txn) } } -void sc_transaction_add_element(sc_transaction * txn, sc_element * element) {} - -void sc_transaction_commit(sc_transaction * txn) +sc_bool _sc_transaction_validate_data(sc_element_data const * data1, sc_element_data const * data2) { - sc_transaction_manager_transaction_add(txn); -} + if (data1 == null_ptr || data2 == null_ptr) + return SC_FALSE; + + if (data1->flags.states != data2->flags.states || + data1->first_out_arc.seg != data2->first_out_arc.seg || + data1->first_out_arc.offset != data2->first_out_arc.offset || + data1->first_in_arc.seg != data2->first_in_arc.seg || + data1->first_in_arc.offset != data2->first_in_arc.offset || +#ifdef SC_OPTIMIZE_SEARCHING_INCOMING_CONNECTORS_FROM_STRUCTURES + data1->first_in_arc_from_structure.seg != data2->first_in_arc_from_structure.seg || + data1->first_in_arc_from_structure.offset != data2->first_in_arc_from_structure.offset || +#endif + data1->arc.begin.seg != data2->arc.begin.seg || + data1->arc.begin.offset != data2->arc.begin.offset || + data1->arc.end.seg != data2->arc.end.seg || + data1->arc.end.offset != data2->arc.end.offset || + data1->arc.next_begin_out_arc.seg != data2->arc.next_begin_out_arc.seg || + data1->arc.next_begin_out_arc.offset != data2->arc.next_begin_out_arc.offset || + data1->arc.prev_begin_out_arc.seg != data2->arc.prev_begin_out_arc.seg || + data1->arc.prev_begin_out_arc.offset != data2->arc.prev_begin_out_arc.offset || + data1->arc.next_begin_in_arc.seg != data2->arc.next_begin_in_arc.seg || + data1->arc.next_begin_in_arc.offset != data2->arc.next_begin_in_arc.offset || + data1->arc.next_end_out_arc.seg != data2->arc.next_end_out_arc.seg || + data1->arc.next_end_out_arc.offset != data2->arc.next_end_out_arc.offset || + data1->arc.next_end_in_arc.seg != data2->arc.next_end_in_arc.seg || + data1->arc.next_end_in_arc.offset != data2->arc.next_end_in_arc.offset || + data1->arc.prev_end_in_arc.seg != data2->arc.prev_end_in_arc.seg || + data1->arc.prev_end_in_arc.offset != data2->arc.prev_end_in_arc.offset || +#ifdef SC_OPTIMIZE_SEARCHING_INCOMING_CONNECTORS_FROM_STRUCTURES + data1->arc.prev_in_arc_from_structure.seg != data2->arc.prev_in_arc_from_structure.seg || + data1->arc.prev_in_arc_from_structure.offset != data2->arc.prev_in_arc_from_structure.offset || + data1->arc.next_in_arc_from_structure.seg != data2->arc.next_in_arc_from_structure.seg || + data1->arc.next_in_arc_from_structure.offset != data2->arc.next_in_arc_from_structure.offset || +#endif + data1->incoming_arcs_count != data2->incoming_arcs_count || + data1->outgoing_arcs_count != data2->outgoing_arcs_count) + { + return SC_FALSE; + } -void sc_transaction_rollback(sc_transaction * txn) {} + return SC_TRUE; +} sc_bool _sc_transaction_validate_modify_elements(sc_list const * elements_list) { sc_iterator * it = sc_list_iterator(elements_list); - if (sc_iterator_next(it)) + while (sc_iterator_next(it)) { sc_pair const * pair = sc_iterator_get(it); - sc_addr const * element_addr = pair->first; + sc_addr element_addr; + SC_ADDR_LOCAL_FROM_INT((uintptr_t)pair->first, element_addr); sc_element_data const * snapshot = pair->second; - sc_element * element = null_ptr; - sc_storage_get_element_by_addr(*element_addr, &element); + sc_element * element; + sc_storage_get_element_by_addr(element_addr, &element); - sc_element_data * current_data = null_ptr; - sc_storage_get_element_data_by_addr(*element_addr, current_data); + sc_element_data * current_data = sc_element_data_new(); + sc_storage_get_element_data_by_addr(element_addr, current_data); - if (current_data != snapshot) + if (_sc_transaction_validate_data(snapshot, current_data)) { return SC_FALSE; } @@ -123,9 +162,37 @@ sc_bool sc_transaction_validate(sc_transaction * txn) return SC_TRUE; } -void sc_transaction_merge(sc_transaction * txn) {} +void _sc_transaction_apply_modified_elements(sc_list const * elements_list, sc_uint64 const txn_id) +{ + sc_iterator * it = sc_list_iterator(elements_list); + while (sc_iterator_next(it)) + { + sc_pair const * pair = sc_iterator_get(it); + + sc_addr element_addr; + SC_ADDR_LOCAL_FROM_INT((uintptr_t)pair->first, element_addr); + + sc_element * element = null_ptr; + sc_storage_get_element_by_addr(element_addr, &element); + + sc_element_data const * new_data = pair->second; + + sc_element_version const * new_version = sc_element_create_new_version(element, new_data, txn_id); + + sc_version_segment_add(element->version_history, new_version); + } +} + +void _sc_transaction_apply_deleted_elements(sc_list const * elements_list) +{ -void sc_transaction_apply(sc_transaction * txn) {} +} + +void sc_transaction_apply(sc_transaction const * txn) +{ + _sc_transaction_apply_modified_elements(txn->transaction_buffer->modified_elements, txn->transaction_id); + _sc_transaction_apply_deleted_elements(txn->transaction_buffer->deleted_elements); +} void sc_transaction_clear(sc_transaction * txn) {} diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index 93df69a880..31d37dbc6c 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -6,10 +6,18 @@ #include #include +typedef enum _sc_transaction_state +{ + SC_TRANSACTION_PENDING, + SC_TRANSACTION_EXECUTED, + SC_TRANSACTION_FAILED +} sc_transaction_state; + typedef struct sc_transaction { sc_uint64 transaction_id; sc_bool is_committed; + sc_transaction_state state; sc_hash_table * elements; sc_monitor * monitor; sc_transaction_buffer * transaction_buffer; @@ -30,16 +38,9 @@ sc_bool sc_transaction_element_remove(sc_transaction const * txn, sc_addr const sc_bool sc_transaction_element_content_set(sc_transaction const * txn, sc_addr const * addr, sc_stream const * content); // Writes information about content changes to the buffer -void sc_transaction_commit(sc_transaction * txn); -// try to apply all operations of the transaction on sc-memory -void sc_transaction_rollback(sc_transaction * txn); -// rollback the transaction operations - sc_bool sc_transaction_validate(sc_transaction * txn); // check if the transaction can be applied based on element versions and free segments -void sc_transaction_merge(sc_transaction * txn); -// check versions of all elements in the transaction and try to merge them -void sc_transaction_apply(sc_transaction * txn); +void sc_transaction_apply(sc_transaction const * txn); // apply all operations (merged versions, allocated spaces) to sc-memory void sc_transaction_clear(sc_transaction * txn); // deletes all transaction items and clears them without performing a commit diff --git a/sc-memory/sc-core/src/sc-store/sc_storage.c b/sc-memory/sc-core/src/sc-store/sc_storage.c index 28dd64a301..df2f42c519 100644 --- a/sc-memory/sc-core/src/sc-store/sc_storage.c +++ b/sc-memory/sc-core/src/sc-store/sc_storage.c @@ -21,6 +21,7 @@ #include "sc_storage_private.h" #include "sc_memory_private.h" +#include "sc_version_segment.h" #include "sc-transaction/sc_element_version.h" @@ -433,7 +434,11 @@ sc_element * sc_storage_allocate_new_element(sc_memory_context const * ctx, sc_a } if (element != null_ptr) + { element->flags.states |= SC_STATE_ELEMENT_EXIST; + // Add param to select usage of version history? + element->version_history = sc_version_segment_new(); + } return element; } diff --git a/sc-memory/sc-core/src/sc-store/sc_version_segment.c b/sc-memory/sc-core/src/sc-store/sc_version_segment.c index 06b860aeb3..4b52057b96 100644 --- a/sc-memory/sc-core/src/sc-store/sc_version_segment.c +++ b/sc-memory/sc-core/src/sc-store/sc_version_segment.c @@ -7,9 +7,15 @@ sc_version_segment * sc_version_segment_new(void) { sc_version_segment * segment = sc_mem_new(sc_version_segment, 1); if (!segment) - return NULL; + return null_ptr; sc_mem_set(segment, 0, sizeof(*segment)); - sc_monitor_init(&segment->monitor); + segment->monitor = _sc_mem_new(sizeof(sc_monitor)); + if (segment->monitor == null_ptr) + { + sc_mem_free(segment); + return null_ptr; + } + sc_monitor_init(segment->monitor); return segment; } @@ -21,34 +27,35 @@ void sc_version_segment_free(sc_version_segment * segment) sc_mem_free(segment); } -sc_element_version * sc_version_segment_add( +sc_uint64 sc_version_segment_get_next_version_id(sc_element const * element) +{ + sc_version_segment const * segment = element->version_history; + sc_monitor * monitor = segment->monitor; + + sc_monitor_acquire_read(monitor); + sc_uint64 const next_version_id = segment->count; + sc_monitor_release_read(monitor); + + return next_version_id; +} + +void sc_version_segment_add( sc_version_segment * segment, - sc_element const * data, - sc_uint64 const version_id, - sc_uint64 const transaction_id, - sc_element_version * parent) + sc_element_version const * new_version) { - if (!segment) - return NULL; + if (segment == null_ptr || new_version == null_ptr) + return; - sc_monitor_acquire_write(&segment->monitor); + sc_monitor_acquire_write(segment->monitor); if (segment->count >= SC_VERSION_SEGMENT_SIZE) { - sc_monitor_release_write(&segment->monitor); - return NULL; + sc_monitor_release_write(segment->monitor); + return; } - sc_element_version * ver = &segment->versions[segment->count++]; - - ver->data = data; - ver->version_id = version_id; - ver->transaction_id = transaction_id; - ver->parent_version = parent; - ver->is_committed = SC_FALSE; - - segment->latest_version = ver; + segment->versions[segment->count++] = *new_version->data; + segment->current_version = new_version; - sc_monitor_release_write(&segment->monitor); - return ver; + sc_monitor_release_write(segment->monitor); } diff --git a/sc-memory/sc-core/src/sc-store/sc_version_segment.h b/sc-memory/sc-core/src/sc-store/sc_version_segment.h index 428b5c5f12..024243aeb2 100644 --- a/sc-memory/sc-core/src/sc-store/sc_version_segment.h +++ b/sc-memory/sc-core/src/sc-store/sc_version_segment.h @@ -10,21 +10,20 @@ typedef struct sc_version_segment { - sc_element_version versions[SC_VERSION_SEGMENT_SIZE]; + sc_element_data versions[SC_VERSION_SEGMENT_SIZE]; sc_addr_offset count; - sc_monitor monitor; - sc_element_version * latest_version; + sc_monitor * monitor; + sc_element_version * current_version; } sc_version_segment; sc_version_segment * sc_version_segment_new(void); void sc_version_segment_free(sc_version_segment * segment); -sc_element_version * sc_version_segment_add( +sc_uint64 sc_version_segment_get_next_version_id(sc_element const * element); + +void sc_version_segment_add( sc_version_segment * segment, - sc_element const * data, - sc_uint64 version_id, - sc_uint64 transaction_id, - sc_element_version * parent); + sc_element_version const * new_version); #endif // SC_VERSION_SEGMENT_H diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_memory_transaction_operations.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_memory_transaction_operations.cpp index abfaadf01a..fb304610d1 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_memory_transaction_operations.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_memory_transaction_operations.cpp @@ -6,7 +6,7 @@ extern "C" { #include "sc-store/sc-container/sc_pair.h" #include "sc-store/sc_storage_private.h" #include "sc-store/sc_version_segment.h" -#include "sc-store/sc-container/sc_struct_node.h" +#include "sc-store/sc-transaction/sc_memory_transaction_manager.h" #include } @@ -142,3 +142,31 @@ TEST_F(ScMemoryTransactionArcNewTest, BufferCheck) EXPECT_EQ(end_diff, 1); } +TEST_F(ScMemoryTransactionArcNewTest, FullTxnTest) +{ + EXPECT_EQ(sc_memory_transaction_arc_new(transaction, sc_type_pos_arc, &beg_addr, &end_addr), SC_RESULT_OK); + + sc_element * beg_el_before = nullptr; + sc_storage_get_element_by_addr(beg_addr, &beg_el_before); + sc_element * end_el_before = nullptr; + sc_storage_get_element_by_addr(end_addr, &end_el_before); + + EXPECT_EQ(sc_hash_table_size(transaction->elements), 3); + EXPECT_EQ(beg_el_before->version_history->count, 0); + EXPECT_EQ(end_el_before->version_history->count, 0); + + EXPECT_EQ(sc_memory_transaction_commit(transaction), SC_RESULT_OK); + + while (transaction->state != SC_TRANSACTION_EXECUTED) + { + } + + sc_element * beg_el_after = nullptr; + sc_storage_get_element_by_addr(beg_addr, &beg_el_after); + sc_element * end_el_after = nullptr; + sc_storage_get_element_by_addr(end_addr, &end_el_after); + + + EXPECT_EQ(beg_el_before->version_history->count, 1); + EXPECT_EQ(end_el_before->version_history->count, 1); +} \ No newline at end of file From 9d6304b0e0f3acbb4a501e9212885a4e12c47033 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 14 May 2025 00:03:50 +0300 Subject: [PATCH 44/51] Delete element txn logic, format code --- .../sc-transaction/sc_element_version.c | 2 +- .../sc-transaction/sc_element_version.h | 2 +- .../sc_memory_transaction_manager.c | 6 +- .../sc_memory_transaction_operations.c | 24 ++++- .../sc_memory_transaction_operations.h | 7 +- .../sc-store/sc-transaction/sc_transaction.c | 91 ++++++++++--------- .../sc-store/sc-transaction/sc_transaction.h | 5 +- .../sc-transaction/sc_transaction_buffer.c | 2 - .../sc-core/src/sc-store/sc_version_segment.c | 6 +- .../sc-core/src/sc-store/sc_version_segment.h | 4 +- .../test_sc_memory_transaction_operations.cpp | 68 ++++++++------ 11 files changed, 125 insertions(+), 92 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c index 34cd626fab..f023d1028a 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.c @@ -10,7 +10,7 @@ sc_element_data * sc_element_data_new() } sc_element_version * sc_element_create_new_version( - sc_element * element, + sc_element const * element, sc_element_data const * new_element_data, sc_uint64 const transaction_id) { diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h index cebcf19545..3334ba310b 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_element_version.h @@ -32,7 +32,7 @@ typedef struct sc_element_version } sc_element_version; sc_element_version * sc_element_create_new_version( - sc_element * element, + sc_element const * element, sc_element_data const * new_element_data, sc_uint64 transaction_id); diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c index 4b91511ea5..1731577d19 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c @@ -203,7 +203,6 @@ sc_result sc_memory_transaction_commit(sc_transaction * txn) return SC_RESULT_OK; } - void sc_transaction_manager_transaction_add(sc_transaction * txn) { sc_monitor_acquire_write(transaction_manager->monitor); @@ -283,9 +282,8 @@ sc_bool sc_transaction_elements_intersect(sc_transaction const * txn, sc_hash_ta if (txn == null_ptr || txn->elements == null_ptr || processed_elements == null_ptr) return SC_FALSE; - sc_hash_table * smaller_table = sc_hash_table_size(txn->elements) <= sc_hash_table_size(processed_elements) - ? txn->elements - : processed_elements; + sc_hash_table * smaller_table = + sc_hash_table_size(txn->elements) <= sc_hash_table_size(processed_elements) ? txn->elements : processed_elements; sc_hash_table * larger_table = smaller_table == txn->elements ? processed_elements : txn->elements; sc_monitor * txn_monitor = txn->monitor; diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c index 1d0f3d29df..81287b06fb 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c @@ -58,8 +58,8 @@ sc_result sc_memory_transaction_arc_new( sc_element_data new_beg_ver_val; sc_element_data new_end_ver_val; - sc_element_data *new_beg_ver = &new_beg_ver_val; - sc_element_data *new_end_ver = &new_end_ver_val; + sc_element_data * new_beg_ver = &new_beg_ver_val; + sc_element_data * new_end_ver = &new_end_ver_val; sc_element * arc_el = sc_storage_allocate_new_element(txn->ctx, &connector_addr); if (arc_el == null_ptr) @@ -96,14 +96,28 @@ sc_result sc_memory_transaction_arc_new( // lock arcs to change output/input list sc_storage_make_elements_incident_to_arc( - connector_addr, arc_el, *beg_addr, (sc_element*)new_beg_ver, *end_addr, (sc_element*)new_end_ver, SC_FALSE, !is_not_loop); + connector_addr, + arc_el, + *beg_addr, + (sc_element *)new_beg_ver, + *end_addr, + (sc_element *)new_end_ver, + SC_FALSE, + !is_not_loop); if (is_edge && is_not_loop) sc_storage_make_elements_incident_to_arc( - connector_addr, arc_el, *end_addr, (sc_element*)new_end_ver, *beg_addr, (sc_element*)new_beg_ver, SC_TRUE, SC_FALSE); + connector_addr, + arc_el, + *end_addr, + (sc_element *)new_end_ver, + *beg_addr, + (sc_element *)new_beg_ver, + SC_TRUE, + SC_FALSE); #ifdef SC_OPTIMIZE_SEARCHING_INCOMING_CONNECTORS_FROM_STRUCTURES if (sc_type_is_structure_and_arc(new_beg_ver->flags.type, type)) - sc_storage_update_structure_arcs(connector_addr, arc_el, *beg_addr, *end_addr, (sc_element*)new_end_ver); + sc_storage_update_structure_arcs(connector_addr, arc_el, *beg_addr, *end_addr, (sc_element *)new_end_ver); #endif sc_transaction_element_new(txn, &connector_addr); diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h index ef04a33cb3..8aaf51a1c8 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h @@ -5,8 +5,11 @@ sc_result sc_memory_transaction_node_new(sc_transaction const * txn, sc_type type); sc_result sc_memory_transaction_link_new(sc_transaction const * txn); -sc_result sc_memory_transaction_arc_new(sc_transaction const * txn, sc_type type, sc_addr * beg_addr, sc_addr * end_addr); +sc_result sc_memory_transaction_arc_new( + sc_transaction const * txn, + sc_type type, + sc_addr * beg_addr, + sc_addr * end_addr); sc_addr sc_memory_transaction_element_free(sc_transaction const * txn, sc_addr addr); - #endif // SC_MEMORY_TRANSACTION_OPERATIONS_H diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index 33abfa5230..3a1324df95 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -1,6 +1,7 @@ #include "sc_transaction.h" #include "sc_memory_transaction_manager.h" +#include "sc-core/sc_memory.h" #include "sc-store/sc_element.h" #include "sc-store/sc_storage_private.h" #include "sc-store/sc_version_segment.h" @@ -43,12 +44,8 @@ sc_transaction * sc_transaction_new(sc_uint64 const txn_id, sc_memory_context * } sc_transaction_buffer_initialize(txn->transaction_buffer, txn_id); - txn->elements = sc_hash_table_init( - sc_hash_table_default_hash_func, - sc_hash_table_default_equal_func, - null_ptr, - null_ptr - ); + txn->elements = + sc_hash_table_init(sc_hash_table_default_hash_func, sc_hash_table_default_equal_func, null_ptr, null_ptr); if (txn->elements == null_ptr) { sc_transaction_buffer_destroy(txn->transaction_buffer); @@ -89,39 +86,36 @@ sc_bool _sc_transaction_validate_data(sc_element_data const * data1, sc_element_ if (data1 == null_ptr || data2 == null_ptr) return SC_FALSE; - if (data1->flags.states != data2->flags.states || - data1->first_out_arc.seg != data2->first_out_arc.seg || - data1->first_out_arc.offset != data2->first_out_arc.offset || - data1->first_in_arc.seg != data2->first_in_arc.seg || - data1->first_in_arc.offset != data2->first_in_arc.offset || + if (data1->flags.states != data2->flags.states || data1->first_out_arc.seg != data2->first_out_arc.seg + || data1->first_out_arc.offset != data2->first_out_arc.offset + || data1->first_in_arc.seg != data2->first_in_arc.seg || data1->first_in_arc.offset != data2->first_in_arc.offset + || #ifdef SC_OPTIMIZE_SEARCHING_INCOMING_CONNECTORS_FROM_STRUCTURES - data1->first_in_arc_from_structure.seg != data2->first_in_arc_from_structure.seg || - data1->first_in_arc_from_structure.offset != data2->first_in_arc_from_structure.offset || + data1->first_in_arc_from_structure.seg != data2->first_in_arc_from_structure.seg + || data1->first_in_arc_from_structure.offset != data2->first_in_arc_from_structure.offset || #endif - data1->arc.begin.seg != data2->arc.begin.seg || - data1->arc.begin.offset != data2->arc.begin.offset || - data1->arc.end.seg != data2->arc.end.seg || - data1->arc.end.offset != data2->arc.end.offset || - data1->arc.next_begin_out_arc.seg != data2->arc.next_begin_out_arc.seg || - data1->arc.next_begin_out_arc.offset != data2->arc.next_begin_out_arc.offset || - data1->arc.prev_begin_out_arc.seg != data2->arc.prev_begin_out_arc.seg || - data1->arc.prev_begin_out_arc.offset != data2->arc.prev_begin_out_arc.offset || - data1->arc.next_begin_in_arc.seg != data2->arc.next_begin_in_arc.seg || - data1->arc.next_begin_in_arc.offset != data2->arc.next_begin_in_arc.offset || - data1->arc.next_end_out_arc.seg != data2->arc.next_end_out_arc.seg || - data1->arc.next_end_out_arc.offset != data2->arc.next_end_out_arc.offset || - data1->arc.next_end_in_arc.seg != data2->arc.next_end_in_arc.seg || - data1->arc.next_end_in_arc.offset != data2->arc.next_end_in_arc.offset || - data1->arc.prev_end_in_arc.seg != data2->arc.prev_end_in_arc.seg || - data1->arc.prev_end_in_arc.offset != data2->arc.prev_end_in_arc.offset || + data1->arc.begin.seg != data2->arc.begin.seg || data1->arc.begin.offset != data2->arc.begin.offset + || data1->arc.end.seg != data2->arc.end.seg || data1->arc.end.offset != data2->arc.end.offset + || data1->arc.next_begin_out_arc.seg != data2->arc.next_begin_out_arc.seg + || data1->arc.next_begin_out_arc.offset != data2->arc.next_begin_out_arc.offset + || data1->arc.prev_begin_out_arc.seg != data2->arc.prev_begin_out_arc.seg + || data1->arc.prev_begin_out_arc.offset != data2->arc.prev_begin_out_arc.offset + || data1->arc.next_begin_in_arc.seg != data2->arc.next_begin_in_arc.seg + || data1->arc.next_begin_in_arc.offset != data2->arc.next_begin_in_arc.offset + || data1->arc.next_end_out_arc.seg != data2->arc.next_end_out_arc.seg + || data1->arc.next_end_out_arc.offset != data2->arc.next_end_out_arc.offset + || data1->arc.next_end_in_arc.seg != data2->arc.next_end_in_arc.seg + || data1->arc.next_end_in_arc.offset != data2->arc.next_end_in_arc.offset + || data1->arc.prev_end_in_arc.seg != data2->arc.prev_end_in_arc.seg + || data1->arc.prev_end_in_arc.offset != data2->arc.prev_end_in_arc.offset || #ifdef SC_OPTIMIZE_SEARCHING_INCOMING_CONNECTORS_FROM_STRUCTURES - data1->arc.prev_in_arc_from_structure.seg != data2->arc.prev_in_arc_from_structure.seg || - data1->arc.prev_in_arc_from_structure.offset != data2->arc.prev_in_arc_from_structure.offset || - data1->arc.next_in_arc_from_structure.seg != data2->arc.next_in_arc_from_structure.seg || - data1->arc.next_in_arc_from_structure.offset != data2->arc.next_in_arc_from_structure.offset || + data1->arc.prev_in_arc_from_structure.seg != data2->arc.prev_in_arc_from_structure.seg + || data1->arc.prev_in_arc_from_structure.offset != data2->arc.prev_in_arc_from_structure.offset + || data1->arc.next_in_arc_from_structure.seg != data2->arc.next_in_arc_from_structure.seg + || data1->arc.next_in_arc_from_structure.offset != data2->arc.next_in_arc_from_structure.offset || #endif - data1->incoming_arcs_count != data2->incoming_arcs_count || - data1->outgoing_arcs_count != data2->outgoing_arcs_count) + data1->incoming_arcs_count != data2->incoming_arcs_count + || data1->outgoing_arcs_count != data2->outgoing_arcs_count) { return SC_FALSE; } @@ -157,7 +151,8 @@ sc_bool _sc_transaction_validate_modify_elements(sc_list const * elements_list) sc_bool sc_transaction_validate(sc_transaction * txn) { - if (!_sc_transaction_validate_modify_elements(txn->transaction_buffer->modified_elements)) return SC_FALSE; + if (!_sc_transaction_validate_modify_elements(txn->transaction_buffer->modified_elements)) + return SC_FALSE; return SC_TRUE; } @@ -183,15 +178,22 @@ void _sc_transaction_apply_modified_elements(sc_list const * elements_list, sc_u } } -void _sc_transaction_apply_deleted_elements(sc_list const * elements_list) +void _sc_transaction_apply_deleted_elements(sc_list const * elements_list, sc_memory_context * ctx) { + sc_iterator * it = sc_list_iterator(elements_list); + while (sc_iterator_next(it)) + { + sc_addr element_addr; + SC_ADDR_LOCAL_FROM_INT((uintptr_t)sc_iterator_get(it), element_addr); + sc_memory_element_free(ctx, element_addr); + } } void sc_transaction_apply(sc_transaction const * txn) { _sc_transaction_apply_modified_elements(txn->transaction_buffer->modified_elements, txn->transaction_id); - _sc_transaction_apply_deleted_elements(txn->transaction_buffer->deleted_elements); + _sc_transaction_apply_deleted_elements(txn->transaction_buffer->deleted_elements, txn->ctx); } void sc_transaction_clear(sc_transaction * txn) {} @@ -201,12 +203,15 @@ sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_addr const * a if (txn == null_ptr || addr == null_ptr || txn->transaction_buffer == null_ptr) return SC_FALSE; - sc_hash_table_insert(txn->elements, (void*)addr, null_ptr); + sc_hash_table_insert(txn->elements, (void *)addr, null_ptr); return sc_transaction_buffer_created_add(txn->transaction_buffer, addr); } -sc_bool sc_transaction_element_change(sc_transaction const * txn, sc_addr const * addr, sc_element_data const * new_data) +sc_bool sc_transaction_element_change( + sc_transaction const * txn, + sc_addr const * addr, + sc_element_data const * new_data) { if (txn == null_ptr || addr == null_ptr || txn->transaction_buffer == null_ptr) return SC_FALSE; @@ -214,7 +219,7 @@ sc_bool sc_transaction_element_change(sc_transaction const * txn, sc_addr const if (SC_ADDR_IS_EMPTY(*addr)) return SC_FALSE; - sc_hash_table_insert(txn->elements, (void*)addr, null_ptr); + sc_hash_table_insert(txn->elements, (void *)addr, null_ptr); return sc_transaction_buffer_modified_add(txn->transaction_buffer, addr, new_data); } @@ -227,7 +232,7 @@ sc_bool sc_transaction_element_remove(sc_transaction const * txn, sc_addr const if (SC_ADDR_IS_EMPTY(*addr)) return SC_FALSE; - sc_hash_table_insert(txn->elements, (void*)addr, null_ptr); + sc_hash_table_insert(txn->elements, (void *)addr, null_ptr); return sc_transaction_buffer_removed_add(txn->transaction_buffer, addr); } @@ -240,7 +245,7 @@ sc_bool sc_transaction_element_content_set(sc_transaction const * txn, sc_addr c if (SC_ADDR_IS_EMPTY(*addr)) return SC_FALSE; - sc_hash_table_insert(txn->elements, (void*)addr, null_ptr); + sc_hash_table_insert(txn->elements, (void *)addr, null_ptr); return sc_transaction_buffer_content_set(txn->transaction_buffer, addr, content); } \ No newline at end of file diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h index 31d37dbc6c..2b1c23f3d0 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.h @@ -31,7 +31,10 @@ void sc_transaction_destroy(sc_transaction * txn); sc_bool sc_transaction_element_new(sc_transaction const * txn, sc_addr const * addr); // Writes information about adding an item to the buffer -sc_bool sc_transaction_element_change(sc_transaction const * txn, sc_addr const * addr, sc_element_data const * new_data); +sc_bool sc_transaction_element_change( + sc_transaction const * txn, + sc_addr const * addr, + sc_element_data const * new_data); // Writes information about the element change to the buffer sc_bool sc_transaction_element_remove(sc_transaction const * txn, sc_addr const * addr); // Writes the deletion information to the buffer diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c index c694be24ec..b7f450e777 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction_buffer.c @@ -1,9 +1,7 @@ #include "sc_transaction_buffer.h" -#include "sc-store/sc_element.h" #include "sc-store/sc_storage_private.h" #include "sc-store/sc-base/sc_monitor_table.h" -#include "sc-store/sc-base/sc_monitor_table_private.h" #include "sc-store/sc-container/sc_pair.h" #include diff --git a/sc-memory/sc-core/src/sc-store/sc_version_segment.c b/sc-memory/sc-core/src/sc-store/sc_version_segment.c index 4b52057b96..db548b44d6 100644 --- a/sc-memory/sc-core/src/sc-store/sc_version_segment.c +++ b/sc-memory/sc-core/src/sc-store/sc_version_segment.c @@ -23,7 +23,7 @@ void sc_version_segment_free(sc_version_segment * segment) { if (!segment) return; - sc_monitor_destroy(&segment->monitor); + sc_monitor_destroy(segment->monitor); sc_mem_free(segment); } @@ -39,9 +39,7 @@ sc_uint64 sc_version_segment_get_next_version_id(sc_element const * element) return next_version_id; } -void sc_version_segment_add( - sc_version_segment * segment, - sc_element_version const * new_version) +void sc_version_segment_add(sc_version_segment * segment, sc_element_version * new_version) { if (segment == null_ptr || new_version == null_ptr) return; diff --git a/sc-memory/sc-core/src/sc-store/sc_version_segment.h b/sc-memory/sc-core/src/sc-store/sc_version_segment.h index 024243aeb2..253f8cfd9d 100644 --- a/sc-memory/sc-core/src/sc-store/sc_version_segment.h +++ b/sc-memory/sc-core/src/sc-store/sc_version_segment.h @@ -22,8 +22,6 @@ void sc_version_segment_free(sc_version_segment * segment); sc_uint64 sc_version_segment_get_next_version_id(sc_element const * element); -void sc_version_segment_add( - sc_version_segment * segment, - sc_element_version const * new_version); +void sc_version_segment_add(sc_version_segment * segment, sc_element_version * new_version); #endif // SC_VERSION_SEGMENT_H diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_memory_transaction_operations.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_memory_transaction_operations.cpp index fb304610d1..1186f1bd3e 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_memory_transaction_operations.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_memory_transaction_operations.cpp @@ -1,7 +1,8 @@ #include #include -extern "C" { +extern "C" +{ #include #include "sc-store/sc-container/sc_pair.h" #include "sc-store/sc_storage_private.h" @@ -10,12 +11,14 @@ extern "C" { #include } -class ScMemoryTransactionArcNewTest : public ScMemoryTest { +class ScMemoryTransactionArcNewTest : public ScMemoryTest +{ protected: - sc_transaction *transaction = nullptr; + sc_transaction * transaction = nullptr; sc_addr beg_addr = {}, end_addr = {}; - void SetUp() override { + void SetUp() override + { ScMemoryTest::SetUp(); beg_addr = sc_memory_node_new(m_ctx->GetRealContext(), sc_type_node); end_addr = sc_memory_node_new(m_ctx->GetRealContext(), sc_type_node); @@ -24,14 +27,18 @@ class ScMemoryTransactionArcNewTest : public ScMemoryTest { ASSERT_NE(transaction, nullptr); } - void TearDown() override { + void TearDown() override + { if (transaction) sc_transaction_destroy(transaction); ScMemoryTest::TearDown(); } }; -sc_result sc_transaction_buffer_find_new_element(sc_transaction_buffer const * buffer, sc_addr const * addr, sc_uint32 * out_hash) +sc_result sc_transaction_buffer_find_new_element( + sc_transaction_buffer const * buffer, + sc_addr const * addr, + sc_uint32 * out_hash) { if (buffer == null_ptr || buffer->new_elements == null_ptr || addr == null_ptr || out_hash == null_ptr) return SC_RESULT_ERROR_INVALID_PARAMS; @@ -56,7 +63,10 @@ sc_result sc_transaction_buffer_find_new_element(sc_transaction_buffer const * b return SC_RESULT_ERROR_NOT_FOUND; } -sc_result sc_transaction_buffer_find_modified_element(sc_transaction_buffer const * buffer, sc_addr const * addr, sc_element_data ** out_data) +sc_result sc_transaction_buffer_find_modified_element( + sc_transaction_buffer const * buffer, + sc_addr const * addr, + sc_element_data ** out_data) { if (buffer == null_ptr || buffer->modified_elements == null_ptr || addr == null_ptr || out_data == null_ptr) return SC_RESULT_ERROR_INVALID_PARAMS; @@ -83,31 +93,38 @@ sc_result sc_transaction_buffer_find_modified_element(sc_transaction_buffer cons return SC_RESULT_ERROR_NOT_FOUND; } -TEST_F(ScMemoryTransactionArcNewTest, ValidParams) { +TEST_F(ScMemoryTransactionArcNewTest, ValidParams) +{ EXPECT_EQ(sc_memory_transaction_arc_new(transaction, sc_type_pos_arc, &beg_addr, &end_addr), SC_RESULT_OK); } -TEST_F(ScMemoryTransactionArcNewTest, InvalidAddress) { +TEST_F(ScMemoryTransactionArcNewTest, InvalidAddress) +{ sc_addr empty_addr = SC_ADDR_EMPTY; - EXPECT_EQ(sc_memory_transaction_arc_new(transaction, sc_type_pos_arc, &empty_addr, &end_addr), - SC_RESULT_ERROR_ADDR_IS_NOT_VALID); - EXPECT_EQ(sc_memory_transaction_arc_new(transaction, sc_type_pos_arc, &beg_addr, &empty_addr), - SC_RESULT_ERROR_ADDR_IS_NOT_VALID); + EXPECT_EQ( + sc_memory_transaction_arc_new(transaction, sc_type_pos_arc, &empty_addr, &end_addr), + SC_RESULT_ERROR_ADDR_IS_NOT_VALID); + EXPECT_EQ( + sc_memory_transaction_arc_new(transaction, sc_type_pos_arc, &beg_addr, &empty_addr), + SC_RESULT_ERROR_ADDR_IS_NOT_VALID); } -TEST_F(ScMemoryTransactionArcNewTest, InvalidType) { - EXPECT_EQ(sc_memory_transaction_arc_new(transaction, sc_type_node, &beg_addr, &end_addr), - SC_RESULT_ERROR_ELEMENT_IS_NOT_CONNECTOR); +TEST_F(ScMemoryTransactionArcNewTest, InvalidType) +{ + EXPECT_EQ( + sc_memory_transaction_arc_new(transaction, sc_type_node, &beg_addr, &end_addr), + SC_RESULT_ERROR_ELEMENT_IS_NOT_CONNECTOR); } -TEST_F(ScMemoryTransactionArcNewTest, NullParams) { - EXPECT_EQ(sc_memory_transaction_arc_new(nullptr, sc_type_pos_arc, &beg_addr, &end_addr), - SC_RESULT_ERROR_INVALID_PARAMS); - EXPECT_EQ(sc_memory_transaction_arc_new(transaction, sc_type_pos_arc, nullptr, &end_addr), - SC_RESULT_ERROR_INVALID_PARAMS); - EXPECT_EQ(sc_memory_transaction_arc_new(transaction, sc_type_pos_arc, &beg_addr, nullptr), - SC_RESULT_ERROR_INVALID_PARAMS); +TEST_F(ScMemoryTransactionArcNewTest, NullParams) +{ + EXPECT_EQ( + sc_memory_transaction_arc_new(nullptr, sc_type_pos_arc, &beg_addr, &end_addr), SC_RESULT_ERROR_INVALID_PARAMS); + EXPECT_EQ( + sc_memory_transaction_arc_new(transaction, sc_type_pos_arc, nullptr, &end_addr), SC_RESULT_ERROR_INVALID_PARAMS); + EXPECT_EQ( + sc_memory_transaction_arc_new(transaction, sc_type_pos_arc, &beg_addr, nullptr), SC_RESULT_ERROR_INVALID_PARAMS); } TEST_F(ScMemoryTransactionArcNewTest, BufferCheck) @@ -135,8 +152,8 @@ TEST_F(ScMemoryTransactionArcNewTest, BufferCheck) sc_element_data * end_el_ver = nullptr; sc_transaction_buffer_find_modified_element(transaction->transaction_buffer, &end_addr, &end_el_ver); - const size_t beg_diff = beg_el_ver->outgoing_arcs_count - beg_el_after->outgoing_arcs_count; - const size_t end_diff = end_el_ver->incoming_arcs_count - end_el_after->incoming_arcs_count; + size_t const beg_diff = beg_el_ver->outgoing_arcs_count - beg_el_after->outgoing_arcs_count; + size_t const end_diff = end_el_ver->incoming_arcs_count - end_el_after->incoming_arcs_count; EXPECT_EQ(beg_diff, 1); EXPECT_EQ(end_diff, 1); @@ -166,7 +183,6 @@ TEST_F(ScMemoryTransactionArcNewTest, FullTxnTest) sc_element * end_el_after = nullptr; sc_storage_get_element_by_addr(end_addr, &end_el_after); - EXPECT_EQ(beg_el_before->version_history->count, 1); EXPECT_EQ(end_el_before->version_history->count, 1); } \ No newline at end of file From 9cc97a175edec158e35238315b672a633a356285 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 14 May 2025 00:34:17 +0300 Subject: [PATCH 45/51] Add sc_thread_sleep (glib) --- sc-memory/sc-core/src/sc-store/sc-base/sc_thread.c | 5 +++++ sc-memory/sc-core/src/sc-store/sc-base/sc_thread.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.c b/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.c index 15efa315e2..01d91a64b1 100644 --- a/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.c +++ b/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.c @@ -28,3 +28,8 @@ void sc_thread_unref(sc_thread * thread) g_thread_unref(thread); } } + +void sc_thread_sleep(sc_uint32 milliseconds) +{ + g_usleep((gulong)milliseconds * 1000); +} diff --git a/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.h b/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.h index 2a7e01e327..d2aa0569b3 100644 --- a/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.h +++ b/sc-memory/sc-core/src/sc-store/sc-base/sc_thread.h @@ -7,6 +7,8 @@ #ifndef _sc_thread_h_ #define _sc_thread_h_ +#include "sc-core/sc_types.h" + #include typedef GThread sc_thread; @@ -19,5 +21,6 @@ typedef gchar const sc_thread_name; sc_thread * sc_thread_new(sc_thread_name * name, sc_thread_func func, sc_thread_data data); void sc_thread_join(sc_thread * thread); void sc_thread_unref(sc_thread * thread); +void sc_thread_sleep(sc_uint32 milliseconds); #endif From 2ce15b7dfd9686607925c2b57ab36fba00065576 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 14 May 2025 01:39:04 +0300 Subject: [PATCH 46/51] Fix txn_manager init, fix txn validation, rewrite buffer tests, start txn_manager tests --- .../sc_memory_transaction_manager.c | 28 +++++- .../sc-store/sc-transaction/sc_transaction.c | 4 +- .../test_sc_transaction_buffer.cpp | 74 +++++++++++---- .../test_sc_transaction_manager.cpp | 92 ++++++++++++++++++- 4 files changed, 171 insertions(+), 27 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c index 1731577d19..c715a760b6 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c @@ -64,9 +64,16 @@ sc_result sc_memory_transaction_manager_initialize(sc_memory_transaction_manager } _sc_monitor_table_init(transaction_manager->monitor_table); + transaction_manager->processed_elements = sc_hash_table_init( + sc_hash_table_default_hash_func, sc_hash_table_default_equal_func, null_ptr, null_ptr); + if (transaction_manager->processed_elements == null_ptr) + { + goto error_cleanup_monitor_table; + } + if (sc_list_init(&transaction_manager->threads) != SC_RESULT_OK) { - return SC_RESULT_ERROR_INVALID_STATE; + goto error_cleanup_hash_table; } for (int i = 0; i < SC_TRANSACTION_THREAD_COUNT; ++i) @@ -92,6 +99,11 @@ sc_result sc_memory_transaction_manager_initialize(sc_memory_transaction_manager transaction_manager->threads = null_ptr; } +error_cleanup_hash_table: + sc_hash_table_destroy(transaction_manager->processed_elements); + transaction_manager->processed_elements = null_ptr; + +error_cleanup_monitor_table: sc_mem_free(transaction_manager->monitor_table); transaction_manager->monitor_table = null_ptr; @@ -257,6 +269,8 @@ void sc_transaction_handler() continue; } + // TODO fix deadlock here (txn_manager monitor) in test thread safety + sc_monitor_release_read(transaction_manager->monitor); sc_monitor_acquire_write(transaction_manager->monitor); @@ -265,13 +279,18 @@ void sc_transaction_handler() sc_transaction * txn = sc_queue_front(transaction_manager->transaction_queue); sc_queue_pop(transaction_manager->transaction_queue); + sc_monitor_release_write(transaction_manager->monitor); + sc_monitor_acquire_read(transaction_manager->monitor); + sc_transaction_manager_transaction_execute(txn); txn->state = SC_TRANSACTION_EXECUTED; } - - sc_monitor_release_write(transaction_manager->monitor); - sc_monitor_acquire_read(transaction_manager->monitor); + else + { + sc_monitor_release_write(transaction_manager->monitor); + sc_monitor_acquire_read(transaction_manager->monitor); + } } sc_monitor_release_read(transaction_manager->monitor); @@ -289,7 +308,6 @@ sc_bool sc_transaction_elements_intersect(sc_transaction const * txn, sc_hash_ta sc_monitor * txn_monitor = txn->monitor; sc_monitor * processed_monitor = sc_memory_transaction_manager_get()->monitor; - sc_monitor_acquire_read(processed_monitor); sc_monitor_acquire_read(txn_monitor); sc_hash_table_iterator iter; diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c index 3a1324df95..6f3b18c0d1 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_transaction.c @@ -151,6 +151,8 @@ sc_bool _sc_transaction_validate_modify_elements(sc_list const * elements_list) sc_bool sc_transaction_validate(sc_transaction * txn) { + if (sc_hash_table_size(txn->elements) == 0) + return SC_FALSE; if (!_sc_transaction_validate_modify_elements(txn->transaction_buffer->modified_elements)) return SC_FALSE; @@ -172,7 +174,7 @@ void _sc_transaction_apply_modified_elements(sc_list const * elements_list, sc_u sc_element_data const * new_data = pair->second; - sc_element_version const * new_version = sc_element_create_new_version(element, new_data, txn_id); + sc_element_version * new_version = sc_element_create_new_version(element, new_data, txn_id); sc_version_segment_add(element->version_history, new_version); } diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_buffer.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_buffer.cpp index 99e7a85219..7ce5f9e85b 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_buffer.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_buffer.cpp @@ -18,17 +18,19 @@ extern "C" class ScTransactionBufferTest : public ScMemoryTest { protected: - sc_transaction_buffer * buffer = sc_mem_new(sc_transaction_buffer, 1); + sc_transaction_buffer* buffer = sc_mem_new(sc_transaction_buffer, 1); void SetUp() override { ScMemoryTest::SetUp(); sc_transaction_buffer_initialize(buffer, 1); - ASSERT_NE(buffer, null_ptr); + ASSERT_NE(buffer, nullptr); } void TearDown() override { + sc_transaction_buffer_destroy(buffer); + sc_mem_free(buffer); ScMemoryTest::TearDown(); } }; @@ -45,52 +47,69 @@ TEST_F(ScTransactionBufferTest, InitializationTest) TEST_F(ScTransactionBufferTest, CreatedAddTest) { constexpr sc_addr addr = {1, 1}; - + EXPECT_TRUE(sc_transaction_buffer_created_add(buffer, &addr)); EXPECT_TRUE(sc_transaction_buffer_contains_created(buffer, &addr)); } TEST_F(ScTransactionBufferTest, RemovedAddTest) { - sc_addr addr = {1, 1}; - + constexpr sc_addr addr = {1, 1}; EXPECT_TRUE(sc_transaction_buffer_removed_add(buffer, &addr)); EXPECT_EQ(buffer->deleted_elements->size, 1u); - sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(addr); - EXPECT_EQ(buffer->deleted_elements->begin->data, reinterpret_cast(addr_hash)); + sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); + EXPECT_EQ(reinterpret_cast(buffer->deleted_elements->begin->data), addr_hash); + + // Test duplicate addition + EXPECT_TRUE(sc_transaction_buffer_removed_add(buffer, &addr)); + EXPECT_EQ(buffer->deleted_elements->size, 1u); // Size should not increase } TEST_F(ScTransactionBufferTest, ModifiedAddTest) { - sc_addr * addr = sc_mem_new(sc_addr, 1); - sc_storage_allocate_new_element(m_ctx->GetRealContext(), addr); + sc_addr addr; + sc_storage_allocate_new_element(m_ctx->GetRealContext(), &addr); - sc_element * element = sc_mem_new(sc_element, 1); - sc_storage_get_element_by_addr(*addr, &element); + sc_element* element; + sc_storage_get_element_by_addr(addr, &element); element->incoming_arcs_count++; + sc_element_data const new_data = { + .flags = element->flags, + .first_out_arc = element->first_out_arc, + .first_in_arc = element->first_in_arc, + #ifdef SC_OPTIMIZE_SEARCHING_INCOMING_CONNECTORS_FROM_STRUCTURES + .first_in_arc_from_structure = element->first_in_arc_from_structure, + #endif + .arc = element->arc, + .incoming_arcs_count = element->incoming_arcs_count, + .outgoing_arcs_count = element->outgoing_arcs_count + }; + + EXPECT_TRUE(sc_transaction_buffer_modified_add(buffer, &addr, &new_data)); + EXPECT_EQ(buffer->modified_elements->size, 1u); - EXPECT_EQ(buffer->modified_elements->size, 1); - sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(*addr); - EXPECT_EQ(buffer->modified_elements->begin->data, reinterpret_cast(addr_hash)); + sc_uint32 const addr_hash = SC_ADDR_LOCAL_TO_INT(addr); + auto const pair = static_cast(buffer->modified_elements->begin->data); + EXPECT_EQ(reinterpret_cast(pair->first), addr_hash); } TEST_F(ScTransactionBufferTest, ContentSetTest) { constexpr sc_addr addr = {1, 4}; - sc_stream * stream = sc_stream_memory_new("test", 4, SC_STREAM_FLAG_READ, SC_FALSE); + sc_stream* stream = sc_stream_memory_new("test", 4, SC_STREAM_FLAG_READ, SC_FALSE); ASSERT_NE(stream, nullptr); EXPECT_TRUE(sc_transaction_buffer_content_set(buffer, &addr, stream)); EXPECT_EQ(buffer->content_changes->size, 1u); constexpr sc_uint32 addr_hash = SC_ADDR_LOCAL_TO_INT(addr); - sc_iterator * it = sc_list_iterator(buffer->content_changes); + sc_iterator* it = sc_list_iterator(buffer->content_changes); sc_bool found = SC_FALSE; while (sc_iterator_next(it)) { - sc_pair * pair = static_cast(sc_iterator_get(it)); + sc_pair* pair = static_cast(sc_iterator_get(it)); if (reinterpret_cast(pair->first) == addr_hash) { EXPECT_EQ(pair->second, stream); @@ -99,6 +118,25 @@ TEST_F(ScTransactionBufferTest, ContentSetTest) } } sc_iterator_destroy(it); + EXPECT_TRUE(found); + // Test content update + sc_stream* new_stream = sc_stream_memory_new("new_test", 8, SC_STREAM_FLAG_READ, SC_FALSE); + EXPECT_TRUE(sc_transaction_buffer_content_set(buffer, &addr, new_stream)); + EXPECT_EQ(buffer->content_changes->size, 1u); // Size should not increase + + it = sc_list_iterator(buffer->content_changes); + found = SC_FALSE; + while (sc_iterator_next(it)) + { + auto const pair = static_cast(sc_iterator_get(it)); + if (reinterpret_cast(pair->first) == addr_hash) + { + EXPECT_EQ(pair->second, new_stream); + found = SC_TRUE; + break; + } + } + sc_iterator_destroy(it); EXPECT_TRUE(found); -} +} \ No newline at end of file diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp index 4c19d9c2c7..3b058e9e23 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction_manager.cpp @@ -4,6 +4,7 @@ extern "C" { +#include "sc-store/sc-base/sc_thread.h" #include #include } @@ -17,6 +18,12 @@ class ScTransactionManagerTest : public ScMemoryTest { ScMemoryTest::SetUp(); transaction_manager = sc_memory_transaction_manager_get(); + if (!sc_memory_transaction_manager_is_initialized()) + { + sc_memory_transaction_manager * manager = sc_mem_new(sc_memory_transaction_manager, 1); + sc_memory_transaction_manager_initialize(manager); + } + transaction_manager = sc_memory_transaction_manager_get(); } void TearDown() override @@ -26,24 +33,34 @@ class ScTransactionManagerTest : public ScMemoryTest } }; +// Test Initialization TEST_F(ScTransactionManagerTest, Initialization) { ASSERT_NE(transaction_manager, nullptr); EXPECT_TRUE(sc_memory_transaction_manager_is_initialized()); } +// Test Shutdown TEST_F(ScTransactionManagerTest, Shutdown) { sc_memory_transaction_shutdown(); EXPECT_FALSE(sc_memory_transaction_manager_is_initialized()); + EXPECT_EQ(sc_memory_transaction_manager_get(), nullptr); } +// Test Transaction Creation TEST_F(ScTransactionManagerTest, TransactionNew) { - sc_transaction * txn = sc_memory_transaction_new(m_ctx->GetRealContext()); - EXPECT_NE(txn, nullptr); + sc_transaction * txn1 = sc_memory_transaction_new(m_ctx->GetRealContext()); + EXPECT_NE(txn1, nullptr); + EXPECT_EQ(txn1->transaction_id, 0); // First transaction should have ID 0 + + sc_transaction * txn2 = sc_memory_transaction_new(m_ctx->GetRealContext()); + EXPECT_NE(txn2, nullptr); + EXPECT_EQ(txn2->transaction_id, 1); // Second transaction should have ID 1 } +// Test Transaction Addition to Queue TEST_F(ScTransactionManagerTest, TransactionAdd) { sc_transaction * txn = sc_memory_transaction_new(m_ctx->GetRealContext()); @@ -52,11 +69,80 @@ TEST_F(ScTransactionManagerTest, TransactionAdd) sc_monitor_acquire_read(transaction_manager->monitor); EXPECT_EQ(transaction_manager->transaction_queue->size, 1); + auto * queued_txn = static_cast(sc_queue_front(transaction_manager->transaction_queue)); + EXPECT_EQ(queued_txn, txn); sc_monitor_release_read(transaction_manager->monitor); } +// Test Transaction Processing +TEST_F(ScTransactionManagerTest, TransactionProcessing) +{ + sc_transaction * txn = sc_memory_transaction_new(m_ctx->GetRealContext()); + EXPECT_NE(txn, nullptr); + + // Add an element to txn->elements to simulate real usage + sc_hash_table_insert(txn->elements, (void*)1, (void*)1); + + sc_transaction_manager_transaction_add(txn); + + // Wait for transaction to be processed + while (transaction_manager->transaction_queue->size > 0) + { + sc_thread_sleep(10); // Sleep for 10ms + } + + EXPECT_EQ(txn->state, SC_TRANSACTION_EXECUTED); +} + +// Test Element Intersection +TEST_F(ScTransactionManagerTest, ElementIntersection) +{ + sc_transaction * txn = sc_memory_transaction_new(m_ctx->GetRealContext()); + EXPECT_NE(txn, nullptr); + + // Add intersecting element + sc_hash_table_insert(txn->elements, (void*)1, (void*)1); + sc_hash_table_insert(transaction_manager->processed_elements, (void*)1, (void*)1); + + EXPECT_TRUE(sc_transaction_elements_intersect(txn, transaction_manager->processed_elements)); + + // Remove intersection + sc_hash_table_remove(txn->elements, (void*)1); + EXPECT_FALSE(sc_transaction_elements_intersect(txn, transaction_manager->processed_elements)); + + sc_hash_table_destroy(transaction_manager->processed_elements); +} + +// Test Thread Safety with Multiple Transactions +TEST_F(ScTransactionManagerTest, ThreadSafety) +{ + constexpr int num_transactions = 10; + sc_transaction * transactions[num_transactions]; + + for (int i = 0; i < num_transactions; ++i) + { + transactions[i] = sc_memory_transaction_new(m_ctx->GetRealContext()); + EXPECT_NE(transactions[i], nullptr); + sc_hash_table_insert(transactions[i]->elements, (void*)(i + 1), (void*)(i + 1)); // Unique element per transaction + sc_transaction_manager_transaction_add(transactions[i]); + } + + // Wait for all transactions to be processed + while (transaction_manager->transaction_queue->size > 0) + { + sc_thread_sleep(10); // Sleep for 10ms + } + + for (int i = 0; i < num_transactions; ++i) + { + EXPECT_EQ(transactions[i]->state, SC_TRANSACTION_EXECUTED); + } +} + +// Test Transaction Manager Destroy TEST_F(ScTransactionManagerTest, TransactionManagerDestroy) { sc_memory_transaction_shutdown(); EXPECT_FALSE(sc_memory_transaction_manager_is_initialized()); -} + EXPECT_EQ(sc_memory_transaction_manager_get(), nullptr); +} \ No newline at end of file From 5ce3646a2c197a119efeda50841720930205af49 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 14 May 2025 13:28:34 +0300 Subject: [PATCH 47/51] Fix deadlock in txn_handler and intersect --- .../sc_memory_transaction_manager.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c index c715a760b6..e768650113 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_manager.c @@ -221,9 +221,9 @@ void sc_transaction_manager_transaction_add(sc_transaction * txn) sc_queue_push(transaction_manager->transaction_queue, txn); - sc_monitor_release_write(transaction_manager->monitor); - sc_cond_signal(transaction_manager->queue_condition); + + sc_monitor_release_write(transaction_manager->monitor); } void sc_transaction_manager_block_elements(sc_hash_table * elements) @@ -255,32 +255,25 @@ void sc_transaction_manager_transaction_execute(sc_transaction * txn) void sc_transaction_handler() { - sc_monitor_acquire_read(transaction_manager->monitor); - while (!transaction_manager->should_stop) { + sc_monitor_acquire_write(transaction_manager->monitor); + if (transaction_manager->transaction_queue->size == 0) { - sc_monitor_release_read(transaction_manager->monitor); + sc_monitor_release_write(transaction_manager->monitor); sc_mutex_lock(transaction_manager->mutex); sc_cond_wait(transaction_manager->queue_condition, transaction_manager->mutex); sc_mutex_unlock(transaction_manager->mutex); - sc_monitor_acquire_read(transaction_manager->monitor); continue; } - // TODO fix deadlock here (txn_manager monitor) in test thread safety - - sc_monitor_release_read(transaction_manager->monitor); - sc_monitor_acquire_write(transaction_manager->monitor); - if (!transaction_manager->should_stop && transaction_manager->transaction_queue->size > 0) { sc_transaction * txn = sc_queue_front(transaction_manager->transaction_queue); sc_queue_pop(transaction_manager->transaction_queue); sc_monitor_release_write(transaction_manager->monitor); - sc_monitor_acquire_read(transaction_manager->monitor); sc_transaction_manager_transaction_execute(txn); @@ -289,7 +282,6 @@ void sc_transaction_handler() else { sc_monitor_release_write(transaction_manager->monitor); - sc_monitor_acquire_read(transaction_manager->monitor); } } @@ -309,6 +301,7 @@ sc_bool sc_transaction_elements_intersect(sc_transaction const * txn, sc_hash_ta sc_monitor * processed_monitor = sc_memory_transaction_manager_get()->monitor; sc_monitor_acquire_read(txn_monitor); + sc_monitor_acquire_read(processed_monitor); sc_hash_table_iterator iter; sc_hash_table_iterator_init(&iter, smaller_table); From 6310a812a6cbf1dda711a0a61c74395117281a61 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Wed, 14 May 2025 13:40:46 +0300 Subject: [PATCH 48/51] Fix monitor lock in txn operation --- .../sc-store/sc-transaction/sc_memory_transaction_operations.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c index 81287b06fb..f6fb55738f 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c @@ -124,6 +124,8 @@ sc_result sc_memory_transaction_arc_new( sc_transaction_element_change(txn, beg_addr, new_beg_ver); sc_transaction_element_change(txn, end_addr, new_end_ver); + sc_monitor_release_write_n(2, beg_monitor, end_monitor); + return result; error: From e71d400cd85f5d4e6b21a0c02bc939333b15fe04 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Thu, 15 May 2025 16:01:40 +0300 Subject: [PATCH 49/51] Benchmark tests --- .../sc-core/tests/benchmark/CMakeLists.txt | 40 +++++++++++++ sc-memory/sc-core/tests/benchmark/main.cpp | 53 ++++++++++++++++++ .../tests/benchmark/units/memory_test.hpp | 56 +++++++++++++++++++ .../test_sc_transaction_add_node.hpp | 12 ++++ 4 files changed, 161 insertions(+) create mode 100644 sc-memory/sc-core/tests/benchmark/CMakeLists.txt create mode 100644 sc-memory/sc-core/tests/benchmark/main.cpp create mode 100644 sc-memory/sc-core/tests/benchmark/units/memory_test.hpp create mode 100644 sc-memory/sc-core/tests/benchmark/units/transaction/test_sc_transaction_add_node.hpp diff --git a/sc-memory/sc-core/tests/benchmark/CMakeLists.txt b/sc-memory/sc-core/tests/benchmark/CMakeLists.txt new file mode 100644 index 0000000000..307c40d4b8 --- /dev/null +++ b/sc-memory/sc-core/tests/benchmark/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.10) +project(sc-memory-benchmarks) + +# Находим необходимые зависимости +find_package(benchmark REQUIRED) +find_package(ScMemory REQUIRED) + +# Собираем все исходники бенчмарков +file(GLOB_RECURSE BENCHMARK_SOURCES + "*.cpp" + "units/*/*.hpp" +) + +# Создаем единый исполняемый файл для всех бенчмарков +add_executable(sc-memory-benchmarks ${BENCHMARK_SOURCES}) + +# Подключаем зависимости +target_link_libraries(sc-memory-benchmarks + PRIVATE + ScMemory::sc-memory + benchmark::benchmark +) + +# Добавляем тест в CTest +add_test( + NAME sc-memory-benchmarks + COMMAND sc-memory-benchmarks +) + +# Настройка clang-format если нужно +if(SC_CLANG_FORMAT_CODE) + target_clangformat_setup(sc-memory-benchmarks) +endif() + +# Указываем пути для включения заголовочных файлов +target_include_directories(sc-memory-benchmarks + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${benchmark_INCLUDE_DIRS} +) \ No newline at end of file diff --git a/sc-memory/sc-core/tests/benchmark/main.cpp b/sc-memory/sc-core/tests/benchmark/main.cpp new file mode 100644 index 0000000000..4201e0d903 --- /dev/null +++ b/sc-memory/sc-core/tests/benchmark/main.cpp @@ -0,0 +1,53 @@ +#include "benchmark/benchmark.h" +#include "units/transaction/test_sc_transaction_add_node.hpp" + +#include + +template +void BM_MemoryThreaded(benchmark::State & state) +{ + static std::atomic_int ctxNum = {0}; + BMType test; + if (state.thread_index() == 0) + test.Initialize(); + + auto start = std::chrono::high_resolution_clock::now(); + uint32_t iterations = 0; + for (auto t : state) + { + state.PauseTiming(); + if (!test.HasContext()) + { + test.InitContext(); + ctxNum.fetch_add(1); + } + state.ResumeTiming(); + + test.Run(); + ++iterations; + } + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration elapsed = end - start; + std::stringstream stream; + stream << state.max_iterations << " " << elapsed.count() << std::endl; + std::cout << stream.str(); + + state.counters["rate"] = benchmark::Counter(iterations, benchmark::Counter::kIsRate); + if (state.thread_index() == 0) + { + while (ctxNum.load() != 0); + test.Shutdown(); + } + else + { + test.DestroyContext(); + ctxNum.fetch_add(-1); + } +} + +int constexpr kNodeIters = 1000000; + +BENCHMARK_TEMPLATE(BM_MemoryThreaded, TestGenerateNode) +->Threads(1) +->Iterations(kNodeIters) +->Unit(benchmark::TimeUnit::kMicrosecond); \ No newline at end of file diff --git a/sc-memory/sc-core/tests/benchmark/units/memory_test.hpp b/sc-memory/sc-core/tests/benchmark/units/memory_test.hpp new file mode 100644 index 0000000000..11144807de --- /dev/null +++ b/sc-memory/sc-core/tests/benchmark/units/memory_test.hpp @@ -0,0 +1,56 @@ +/* +* This source file is part of an OSTIS project. For the latest info, see http://ostis.net +* Distributed under the MIT License +* (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT) +*/ + +#pragma once + +#include +#include "sc-memory/sc_memory.hpp" +#include "sc-core/sc_memory.h" + +class TestMemory +{ +public: + void Initialize(size_t objectsNum = 0) + { + sc_memory_params params; + sc_memory_params_clear(¶ms); + params.clear = SC_TRUE; + params.storage = "test_repo"; + + ScMemory::LogMute(); + ScMemory::Initialize(params); + + InitContext(); + Setup(objectsNum); + } + + void Shutdown() + { + m_ctx.reset(); + + ScMemory::Shutdown(false); + } + + void InitContext() + { + m_ctx = std::make_unique(); + } + + void DestroyContext() + { + m_ctx.reset(); + } + + bool HasContext() const + { + return static_cast(m_ctx); + } + + virtual void Setup(size_t objectsNum) {} + +protected: + std::unique_ptr m_ctx {}; +}; \ No newline at end of file diff --git a/sc-memory/sc-core/tests/benchmark/units/transaction/test_sc_transaction_add_node.hpp b/sc-memory/sc-core/tests/benchmark/units/transaction/test_sc_transaction_add_node.hpp new file mode 100644 index 0000000000..5a9c661508 --- /dev/null +++ b/sc-memory/sc-core/tests/benchmark/units/transaction/test_sc_transaction_add_node.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "../memory_test.hpp" + +class TestGenerateNode : public TestMemory +{ +public: + void Run() + { + m_ctx->GenerateNode(ScType::ConstNode); + } +}; \ No newline at end of file From 09117397b11766e97b34d64580e8e2148aa68b24 Mon Sep 17 00:00:00 2001 From: IRomanchuk06 Date: Tue, 20 May 2025 20:25:31 +0300 Subject: [PATCH 50/51] Txn operations return sc_addr --- .../sc_memory_transaction_operations.c | 32 +++++++++---------- .../sc_memory_transaction_operations.h | 6 ++-- sc-memory/sc-core/tests/CMakeLists.txt | 10 ++++++ .../units/transaction/test_sc_transaction.cpp | 1 - 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c index f6fb55738f..e9efedd1fa 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.c @@ -4,55 +4,55 @@ #include "sc-core/sc_memory.h" #include "sc-store/sc_storage_private.h" -sc_result sc_memory_transaction_node_new(sc_transaction const * txn, sc_type const type) +sc_addr sc_memory_transaction_node_new(sc_transaction const * txn, sc_type const type) { if (txn == null_ptr) - return SC_RESULT_ERROR_INVALID_PARAMS; + return SC_ADDR_EMPTY; sc_result result; sc_addr const allocated_addr = sc_memory_node_new_ext(txn->ctx, type, &result); sc_transaction_element_new(txn, &allocated_addr); - return result; + return allocated_addr; } -sc_result sc_memory_transaction_link_new(sc_transaction const * txn) +sc_addr sc_memory_transaction_link_new(sc_transaction const * txn) { if (txn == null_ptr) - return SC_RESULT_ERROR_INVALID_PARAMS; + return SC_ADDR_EMPTY; sc_result result; sc_addr const allocated_addr = sc_memory_link_new_ext(txn->ctx, sc_type_const_node_link, &result); sc_transaction_element_new(txn, &allocated_addr); - return result; + return allocated_addr; } -sc_result sc_memory_transaction_arc_new( +sc_addr sc_memory_transaction_arc_new( sc_transaction const * txn, sc_type const type, sc_addr * const beg_addr, sc_addr * const end_addr) { if (txn == null_ptr) - return SC_RESULT_ERROR_INVALID_PARAMS; + return SC_ADDR_EMPTY; sc_result result; sc_addr connector_addr = SC_ADDR_EMPTY; if (sc_type_is_not_connector(type)) { - return SC_RESULT_ERROR_ELEMENT_IS_NOT_CONNECTOR; + return SC_ADDR_EMPTY; } if (beg_addr == null_ptr || end_addr == null_ptr) { - return SC_RESULT_ERROR_INVALID_PARAMS; + return SC_ADDR_EMPTY; } if (SC_ADDR_IS_EMPTY(*beg_addr) || SC_ADDR_IS_EMPTY(*end_addr)) { - return SC_RESULT_ERROR_ADDR_IS_NOT_VALID; + return SC_ADDR_EMPTY; } sc_element_data new_beg_ver_val; @@ -64,7 +64,7 @@ sc_result sc_memory_transaction_arc_new( sc_element * arc_el = sc_storage_allocate_new_element(txn->ctx, &connector_addr); if (arc_el == null_ptr) { - return SC_RESULT_ERROR_FULL_MEMORY; + return SC_ADDR_EMPTY; } arc_el->flags.type = type; @@ -82,9 +82,9 @@ sc_result sc_memory_transaction_arc_new( sc_monitor_acquire_write_n(2, beg_monitor, end_monitor); if (beg_monitor == null_ptr) - return SC_RESULT_ERROR; + return SC_ADDR_EMPTY; if (end_monitor == null_ptr) - return SC_RESULT_ERROR; + return SC_ADDR_EMPTY; result = sc_storage_get_element_data_by_addr(*beg_addr, new_beg_ver); if (result != SC_RESULT_OK) @@ -126,12 +126,12 @@ sc_result sc_memory_transaction_arc_new( sc_monitor_release_write_n(2, beg_monitor, end_monitor); - return result; + return connector_addr; error: sc_storage_free_element(connector_addr); sc_monitor_release_write_n(2, beg_monitor, end_monitor); - return result; + return connector_addr; } sc_addr sc_memory_transaction_element_free(sc_transaction const * txn, sc_addr const addr) diff --git a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h index 8aaf51a1c8..0aec831b85 100644 --- a/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h +++ b/sc-memory/sc-core/src/sc-store/sc-transaction/sc_memory_transaction_operations.h @@ -3,9 +3,9 @@ #include "sc_transaction.h" -sc_result sc_memory_transaction_node_new(sc_transaction const * txn, sc_type type); -sc_result sc_memory_transaction_link_new(sc_transaction const * txn); -sc_result sc_memory_transaction_arc_new( +sc_addr sc_memory_transaction_node_new(sc_transaction const * txn, sc_type type); +sc_addr sc_memory_transaction_link_new(sc_transaction const * txn); +sc_addr sc_memory_transaction_arc_new( sc_transaction const * txn, sc_type type, sc_addr * beg_addr, diff --git a/sc-memory/sc-core/tests/CMakeLists.txt b/sc-memory/sc-core/tests/CMakeLists.txt index 093a02e0bd..0319b79721 100644 --- a/sc-memory/sc-core/tests/CMakeLists.txt +++ b/sc-memory/sc-core/tests/CMakeLists.txt @@ -38,4 +38,14 @@ make_tests_from_folder(${CMAKE_CURRENT_SOURCE_DIR}/units/transaction if(${SC_CLANG_FORMAT_CODE}) target_clangformat_setup(sc-core-transaction-tests) +endif() + +make_tests_from_folder(${CMAKE_CURRENT_SOURCE_DIR}/benchmark + NAME sc-core-transaction-benchmark-tests + DEPENDS ${glib_LIBRARIES} sc-memory + INCLUDES ${glib_INCLUDE_DIRS} ${SC_CORE_SRC} +) + +if(${SC_CLANG_FORMAT_CODE}) + target_clangformat_setup(sc-core-transaction-benchmark-tests) endif() \ No newline at end of file diff --git a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp index fa3db1502c..b43e86ac21 100644 --- a/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp +++ b/sc-memory/sc-core/tests/units/transaction/test_sc_transaction.cpp @@ -5,7 +5,6 @@ extern "C" { #include -#include #include #include } From a06434ec26a732d25e4dd76e4ccccf4f1c342480 Mon Sep 17 00:00:00 2001 From: NikitaZotov Date: Tue, 9 Sep 2025 15:28:12 +0300 Subject: [PATCH 51/51] [ci] Fix cmake install --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6e42e382aa..c204136b2d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -71,7 +71,7 @@ jobs: - name: Install compilers (macOS) if: runner.os == 'macOS' - run: brew install cmake ninja ccache + run: brew install ninja ccache - name: Set Conan remote run: |