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_SAFE(act, &tran->actions, entry, next) { 65 if (act->drv->abort) { 66 act->drv->abort(act->opaque); 67 } 68 69 if (act->drv->clean) { 70 act->drv->clean(act->opaque); 71 } 72 73 g_free(act); 74 } 75 76 g_free(tran); 77 } 78 79 void tran_commit(Transaction *tran) 80 { 81 TransactionAction *act, *next; 82 83 QSLIST_FOREACH_SAFE(act, &tran->actions, entry, next) { 84 if (act->drv->commit) { 85 act->drv->commit(act->opaque); 86 } 87 88 if (act->drv->clean) { 89 act->drv->clean(act->opaque); 90 } 91 92 g_free(act); 93 } 94 95 g_free(tran); 96 } 97