1 /* 2 * Simple transactions API 3 * 4 * Copyright (c) 2021 Virtuozzo International GmbH. 5 * 6 * Author: 7 * Sementsov-Ogievskiy Vladimir <vsementsov@virtuozzo.com> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 23 #include "qemu/osdep.h" 24 25 #include "qemu/transactions.h" 26 #include "qemu/queue.h" 27 28 typedef struct TransactionAction { 29 TransactionActionDrv *drv; 30 void *opaque; 31 QSLIST_ENTRY(TransactionAction) entry; 32 } TransactionAction; 33 34 struct Transaction { 35 QSLIST_HEAD(, TransactionAction) actions; 36 }; 37 38 Transaction *tran_new(void) 39 { 40 Transaction *tran = g_new(Transaction, 1); 41 42 QSLIST_INIT(&tran->actions); 43 44 return tran; 45 } 46 47 void tran_add(Transaction *tran, TransactionActionDrv *drv, void *opaque) 48 { 49 TransactionAction *act; 50 51 act = g_new(TransactionAction, 1); 52 *act = (TransactionAction) { 53 .drv = drv, 54 .opaque = opaque 55 }; 56 57 QSLIST_INSERT_HEAD(&tran->actions, act, entry); 58 } 59 60 void tran_abort(Transaction *tran) 61 { 62 TransactionAction *act, *next; 63 64 QSLIST_FOREACH(act, &tran->actions, entry) { 65 if (act->drv->abort) { 66 act->drv->abort(act->opaque); 67 } 68 } 69 70 QSLIST_FOREACH_SAFE(act, &tran->actions, entry, next) { 71 if (act->drv->clean) { 72 act->drv->clean(act->opaque); 73 } 74 75 g_free(act); 76 } 77 78 g_free(tran); 79 } 80 81 void tran_commit(Transaction *tran) 82 { 83 TransactionAction *act, *next; 84 85 QSLIST_FOREACH(act, &tran->actions, entry) { 86 if (act->drv->commit) { 87 act->drv->commit(act->opaque); 88 } 89 } 90 91 QSLIST_FOREACH_SAFE(act, &tran->actions, entry, next) { 92 if (act->drv->clean) { 93 act->drv->clean(act->opaque); 94 } 95 96 g_free(act); 97 } 98 99 g_free(tran); 100 } 101