Hash :
6c1aa873
Author :
Thomas de Grivel
Date :
2025-04-17T12:41:42
lock transactions rw
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
/* kc3
* Copyright from 2022 to 2025 kmx.io <contact@kmx.io>
*
* Permission is hereby granted to use this software granted the above
* copyright notice and this permission paragraph are included in all
* copies and substantial portions of this software.
*
* THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
* PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
* AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
* THIS SOFTWARE.
*/
#include <stdlib.h>
#include "assert.h"
#include "fact.h"
#include "fact_action.h"
#include "facts.h"
#include "facts_transaction.h"
#include "list.h"
#include "rwlock.h"
s_facts_transaction * facts_transaction_clean
(s_facts_transaction *transaction)
{
assert(transaction);
fact_action_delete_all(transaction->log);
return transaction->next;
}
void facts_transaction_end (s_facts *facts,
s_facts_transaction *transaction)
{
assert(facts);
assert(transaction);
if (facts->transaction != transaction) {
err_puts("facts_transaction_end: transaction mismatch");
assert(! "facts_transaction_end: transaction mismatch");
abort();
}
facts->transaction = facts_transaction_clean(transaction);
#if HAVE_PTHREAD
rwlock_unlock_w(&facts->rwlock);
#endif
}
bool facts_transaction_find (s_facts *facts,
const s_facts_transaction *transaction)
{
const s_facts_transaction *t;
t = facts->transaction;
while (t) {
if (t == transaction)
return true;
t = t->next;
}
err_puts("facts_transaction_find: transaction not found");
assert(! "facts_transaction_find: transaction not found");
return false;
}
s_facts_transaction * facts_transaction_init
(s_facts_transaction *transaction)
{
s_facts_transaction tmp = {0};
*transaction = tmp;
return transaction;
}
s_facts * facts_transaction_rollback
(s_facts *facts, const s_facts_transaction *transaction)
{
bool b;
s_fact fact;
s_fact_action *log;
s_facts_transaction *t;
if (! facts_transaction_find(facts, transaction))
return NULL;
t = facts->transaction;
while (t) {
log = t->log;
while (log) {
switch (log->action) {
case FACT_ACTION_ADD:
if (! facts_remove_fact(facts, &log->fact, &b) ||
! b) {
abort();
return NULL;
}
break;
case FACT_ACTION_REMOVE:
if (! facts_add_fact(facts, &log->fact)) {
abort();
return NULL;
}
break;
case FACT_ACTION_REPLACE:
fact_init(&fact, log->fact.subject, log->fact.predicate,
&log->object);
if (! facts_replace_fact(facts, &fact)) {
abort();
return NULL;
}
}
log = log->next;
}
if (t == transaction) {
facts_transaction_end(facts, t);
return facts;
}
facts_transaction_end(facts, t);
t = facts->transaction;
}
err_puts("facts_transaction_rollback: no transaction in facts");
assert(! "facts_transaction_rollback: no transaction in facts");
abort();
return NULL;
}
void facts_transaction_start (s_facts *facts,
s_facts_transaction *transaction)
{
assert(facts);
assert(transaction);
#if HAVE_PTHREAD
if (! rwlock_w(&facts->rwlock))
return;
#endif
transaction->log = NULL;
transaction->next = facts->transaction;
facts->transaction = transaction;
}