Hash :
586a96a8
Author :
Thomas de Grivel
Date :
2024-06-27T14:56:25
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
/* c3
* Copyright 2022-2024 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 "types.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);
}
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);
transaction->log = NULL;
transaction->next = facts->transaction;
facts->transaction = transaction;
}