diff options
author | Alex Wang <alexw@nicira.com> | 2015-08-04 09:52:26 -0700 |
---|---|---|
committer | Alex Wang <alexw@nicira.com> | 2015-08-08 09:49:39 -0700 |
commit | a548a764b89ac6421c9c8bbb5c683aff0d5ddd88 (patch) | |
tree | 707898cbdbc200d4672910d089c56c6219a67564 /lib | |
parent | bf4afb5a1582076bc822b8260213291c9ea39e94 (diff) | |
download | openvswitch-a548a764b89ac6421c9c8bbb5c683aff0d5ddd88.tar.gz |
idl-loop: Move idl-loop into ovsdb-idl library.
idl-loop is needed in implementing other controller (i.e., vtep controller).
So, this commit moves the logic into ovsdb-idl library module.
Signed-off-by: Alex Wang <alexw@nicira.com>
Acked-by: Russell Bryant <rbryant@redhat.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ovsdb-idl.c | 72 | ||||
-rw-r--r-- | lib/ovsdb-idl.h | 19 |
2 files changed, 91 insertions, 0 deletions
diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c index 4ec703240..f0d5d9ca0 100644 --- a/lib/ovsdb-idl.c +++ b/lib/ovsdb-idl.c @@ -2632,3 +2632,75 @@ ovsdb_idl_parse_lock_notify(struct ovsdb_idl *idl, } } } + +void +ovsdb_idl_loop_destroy(struct ovsdb_idl_loop *loop) +{ + if (loop) { + ovsdb_idl_destroy(loop->idl); + } +} + +struct ovsdb_idl_txn * +ovsdb_idl_loop_run(struct ovsdb_idl_loop *loop) +{ + ovsdb_idl_run(loop->idl); + loop->open_txn = (loop->committing_txn + || ovsdb_idl_get_seqno(loop->idl) == loop->skip_seqno + ? NULL + : ovsdb_idl_txn_create(loop->idl)); + return loop->open_txn; +} + +void +ovsdb_idl_loop_commit_and_wait(struct ovsdb_idl_loop *loop) +{ + if (loop->open_txn) { + loop->committing_txn = loop->open_txn; + loop->open_txn = NULL; + + loop->precommit_seqno = ovsdb_idl_get_seqno(loop->idl); + } + + struct ovsdb_idl_txn *txn = loop->committing_txn; + if (txn) { + enum ovsdb_idl_txn_status status = ovsdb_idl_txn_commit(txn); + if (status != TXN_INCOMPLETE) { + switch (status) { + case TXN_TRY_AGAIN: + /* We want to re-evaluate the database when it's changed from + * the contents that it had when we started the commit. (That + * might have already happened.) */ + loop->skip_seqno = loop->precommit_seqno; + if (ovsdb_idl_get_seqno(loop->idl) != loop->skip_seqno) { + poll_immediate_wake(); + } + break; + + case TXN_SUCCESS: + /* If the database has already changed since we started the + * commit, re-evaluate it immediately to avoid missing a change + * for a while. */ + if (ovsdb_idl_get_seqno(loop->idl) != loop->precommit_seqno) { + poll_immediate_wake(); + } + break; + + case TXN_UNCHANGED: + case TXN_ABORTED: + case TXN_NOT_LOCKED: + case TXN_ERROR: + break; + + case TXN_UNCOMMITTED: + case TXN_INCOMPLETE: + OVS_NOT_REACHED(); + + } + ovsdb_idl_txn_destroy(txn); + loop->committing_txn = NULL; + } + } + + ovsdb_idl_wait(loop->idl); +} diff --git a/lib/ovsdb-idl.h b/lib/ovsdb-idl.h index a49f84fb6..519412231 100644 --- a/lib/ovsdb-idl.h +++ b/lib/ovsdb-idl.h @@ -222,5 +222,24 @@ const struct ovsdb_idl_row *ovsdb_idl_txn_insert( const struct uuid *); struct ovsdb_idl *ovsdb_idl_txn_get_idl (struct ovsdb_idl_txn *); + + +/* ovsdb_idl_loop provides an easy way to manage the transactions related + * to 'idl' and to cope with different status during transaction. */ +struct ovsdb_idl_loop { + struct ovsdb_idl *idl; + unsigned int skip_seqno; + + struct ovsdb_idl_txn *committing_txn; + unsigned int precommit_seqno; + + struct ovsdb_idl_txn *open_txn; +}; + +#define OVSDB_IDL_LOOP_INITIALIZER(IDL) { .idl = (IDL) } + +void ovsdb_idl_loop_destroy(struct ovsdb_idl_loop *); +struct ovsdb_idl_txn *ovsdb_idl_loop_run(struct ovsdb_idl_loop *); +void ovsdb_idl_loop_commit_and_wait(struct ovsdb_idl_loop *); #endif /* ovsdb-idl.h */ |