Message ID | 20210317143529.615584-9-vsementsov@virtuozzo.com |
---|---|
State | New |
Headers | show |
Series | block: update graph permissions update | expand |
Am 17.03.2021 um 15:35 hat Vladimir Sementsov-Ogievskiy geschrieben: > Add simple transaction API to use in further update of block graph > operations. > > Supposed usage is: > > - "prepare" is main function of the action and it should make the main > effect of the action to be visible for the following actions, keeping > possibility of roll-back, saving necessary things in action state, > which is prepended to the action list (to do that, prepare func > should call tran_add()). So, driver struct doesn't include "prepare" > field, as it is supposed to be called directly. > > - commit/rollback is supposed to be called for the list of action > states, to commit/rollback all the actions in reverse order > > - When possible "commit" should not make visible effect for other > actions, which make possible transparent logical interaction between > actions. > > Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> > --- > include/qemu/transactions.h | 63 ++++++++++++++++++++++++ > util/transactions.c | 96 +++++++++++++++++++++++++++++++++++++ > MAINTAINERS | 6 +++ > util/meson.build | 1 + > 4 files changed, 166 insertions(+) > create mode 100644 include/qemu/transactions.h > create mode 100644 util/transactions.c > > diff --git a/include/qemu/transactions.h b/include/qemu/transactions.h > new file mode 100644 > index 0000000000..e7add9637f > --- /dev/null > +++ b/include/qemu/transactions.h > @@ -0,0 +1,63 @@ > +/* > + * Simple transactions API > + * > + * Copyright (c) 2021 Virtuozzo International GmbH. > + * > + * Author: > + * Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. If not, see <http://www.gnu.org/licenses/>. > + * > + * > + * = Generic transaction API = > + * > + * The intended usage is the following: you create "prepare" functions, which > + * represents the actions. They will usually have Transaction* argument, and > + * call tran_add() to register finalization callbacks. For finalization > + * callbacks, prepare corresponding TransactionActionDrv structures. > + * > + * Than, when you need to make a transaction, create an empty Transaction by Then > + * tran_create(), call your "prepare" functions on it, and finally call > + * tran_abort() or tran_commit() to finalize the transaction by corresponding > + * finalization actions in reverse order. > + */ > + > +#ifndef QEMU_TRANSACTIONS_H > +#define QEMU_TRANSACTIONS_H > + > +#include <gmodule.h> > + > +typedef struct TransactionActionDrv { > + void (*abort)(void *opaque); > + void (*commit)(void *opaque); > + void (*clean)(void *opaque); > +} TransactionActionDrv; > + > +typedef struct Transaction Transaction; > + > +Transaction *tran_new(void); > +void tran_add(Transaction *tran, TransactionActionDrv *drv, void *opaque); > +void tran_abort(Transaction *tran); > +void tran_commit(Transaction *tran); > + > +static inline void tran_finalize(Transaction *tran, int ret) > +{ > + if (ret < 0) { > + tran_abort(tran); > + } else { > + tran_commit(tran); > + } > +} > + > +#endif /* QEMU_TRANSACTIONS_H */ > diff --git a/util/transactions.c b/util/transactions.c > new file mode 100644 > index 0000000000..d0bc9a3e73 > --- /dev/null > +++ b/util/transactions.c > @@ -0,0 +1,96 @@ > +/* > + * Simple transactions API > + * > + * Copyright (c) 2021 Virtuozzo International GmbH. > + * > + * Author: > + * Sementsov-Ogievskiy Vladimir <vsementsov@virtuozzo.com> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include "qemu/osdep.h" > + > +#include "qemu/transactions.h" > +#include "qemu/queue.h" > + > +typedef struct TransactionAction { > + TransactionActionDrv *drv; > + void *opaque; > + QSLIST_ENTRY(TransactionAction) entry; "next" is a bit more conventional as a name, but by far not as much as I thought, so no objection. With the than/then typo fixed: Reviewed-by: Kevin Wolf <kwolf@redhat.com>
diff --git a/include/qemu/transactions.h b/include/qemu/transactions.h new file mode 100644 index 0000000000..e7add9637f --- /dev/null +++ b/include/qemu/transactions.h @@ -0,0 +1,63 @@ +/* + * Simple transactions API + * + * Copyright (c) 2021 Virtuozzo International GmbH. + * + * Author: + * Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * + * = Generic transaction API = + * + * The intended usage is the following: you create "prepare" functions, which + * represents the actions. They will usually have Transaction* argument, and + * call tran_add() to register finalization callbacks. For finalization + * callbacks, prepare corresponding TransactionActionDrv structures. + * + * Than, when you need to make a transaction, create an empty Transaction by + * tran_create(), call your "prepare" functions on it, and finally call + * tran_abort() or tran_commit() to finalize the transaction by corresponding + * finalization actions in reverse order. + */ + +#ifndef QEMU_TRANSACTIONS_H +#define QEMU_TRANSACTIONS_H + +#include <gmodule.h> + +typedef struct TransactionActionDrv { + void (*abort)(void *opaque); + void (*commit)(void *opaque); + void (*clean)(void *opaque); +} TransactionActionDrv; + +typedef struct Transaction Transaction; + +Transaction *tran_new(void); +void tran_add(Transaction *tran, TransactionActionDrv *drv, void *opaque); +void tran_abort(Transaction *tran); +void tran_commit(Transaction *tran); + +static inline void tran_finalize(Transaction *tran, int ret) +{ + if (ret < 0) { + tran_abort(tran); + } else { + tran_commit(tran); + } +} + +#endif /* QEMU_TRANSACTIONS_H */ diff --git a/util/transactions.c b/util/transactions.c new file mode 100644 index 0000000000..d0bc9a3e73 --- /dev/null +++ b/util/transactions.c @@ -0,0 +1,96 @@ +/* + * Simple transactions API + * + * Copyright (c) 2021 Virtuozzo International GmbH. + * + * Author: + * Sementsov-Ogievskiy Vladimir <vsementsov@virtuozzo.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" + +#include "qemu/transactions.h" +#include "qemu/queue.h" + +typedef struct TransactionAction { + TransactionActionDrv *drv; + void *opaque; + QSLIST_ENTRY(TransactionAction) entry; +} TransactionAction; + +struct Transaction { + QSLIST_HEAD(, TransactionAction) actions; +}; + +Transaction *tran_new(void) +{ + Transaction *tran = g_new(Transaction, 1); + + QSLIST_INIT(&tran->actions); + + return tran; +} + +void tran_add(Transaction *tran, TransactionActionDrv *drv, void *opaque) +{ + TransactionAction *act; + + act = g_new(TransactionAction, 1); + *act = (TransactionAction) { + .drv = drv, + .opaque = opaque + }; + + QSLIST_INSERT_HEAD(&tran->actions, act, entry); +} + +void tran_abort(Transaction *tran) +{ + TransactionAction *act, *next; + + QSLIST_FOREACH_SAFE(act, &tran->actions, entry, next) { + if (act->drv->abort) { + act->drv->abort(act->opaque); + } + + if (act->drv->clean) { + act->drv->clean(act->opaque); + } + + g_free(act); + } + + g_free(tran); +} + +void tran_commit(Transaction *tran) +{ + TransactionAction *act, *next; + + QSLIST_FOREACH_SAFE(act, &tran->actions, entry, next) { + if (act->drv->commit) { + act->drv->commit(act->opaque); + } + + if (act->drv->clean) { + act->drv->clean(act->opaque); + } + + g_free(act); + } + + g_free(tran); +} diff --git a/MAINTAINERS b/MAINTAINERS index 5ca3c9f851..d5e6ff2224 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2514,6 +2514,12 @@ M: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> S: Maintained F: scripts/simplebench/ +Transactions helper +M: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> +S: Maintained +F: include/qemu/transactions.h +F: util/transactions.c + QAPI M: Markus Armbruster <armbru@redhat.com> M: Michael Roth <michael.roth@amd.com> diff --git a/util/meson.build b/util/meson.build index 984fba965f..3c39631bfe 100644 --- a/util/meson.build +++ b/util/meson.build @@ -41,6 +41,7 @@ util_ss.add(files('qsp.c')) util_ss.add(files('range.c')) util_ss.add(files('stats64.c')) util_ss.add(files('systemd.c')) +util_ss.add(files('transactions.c')) util_ss.add(when: 'CONFIG_POSIX', if_true: files('drm.c')) util_ss.add(files('guest-random.c'))
Add simple transaction API to use in further update of block graph operations. Supposed usage is: - "prepare" is main function of the action and it should make the main effect of the action to be visible for the following actions, keeping possibility of roll-back, saving necessary things in action state, which is prepended to the action list (to do that, prepare func should call tran_add()). So, driver struct doesn't include "prepare" field, as it is supposed to be called directly. - commit/rollback is supposed to be called for the list of action states, to commit/rollback all the actions in reverse order - When possible "commit" should not make visible effect for other actions, which make possible transparent logical interaction between actions. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> --- include/qemu/transactions.h | 63 ++++++++++++++++++++++++ util/transactions.c | 96 +++++++++++++++++++++++++++++++++++++ MAINTAINERS | 6 +++ util/meson.build | 1 + 4 files changed, 166 insertions(+) create mode 100644 include/qemu/transactions.h create mode 100644 util/transactions.c