2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-31 06:15:47 +00:00

ovsdb-idl: Break into two layers.

This change breaks the IDL into two layers: the IDL proper, whose
interface to its client is unchanged, and a low-level library called
the OVSDB "client synchronization" (CS) library.  There are two
reasons for this change.  First, the IDL is big and complicated and
I think that this change factors out some of that complication into
a simpler lower layer.  Second, the OVN northd implementation based
on DDlog can benefit from the client synchronization library even
though it would actually be made increasingly complicated by the IDL.

Signed-off-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
Ben Pfaff
2020-11-21 11:47:01 -08:00
parent a5c067a8b9
commit 1c337c43ac
4 changed files with 2432 additions and 1571 deletions

View File

@@ -17,14 +17,147 @@
#ifndef OVSDB_CS_H
#define OVSDB_CS_H 1
#include "openvswitch/compiler.h"
/* Open vSwitch Database client synchronization layer.
*
* This is a base layer for maintaining an in-memory replica of a database. It
* issues RPC requests to an OVSDB database server and passes the semantically
* meaningful parts of the stream up to a higher layer. The OVSDB IDL uses
* this as a base layer, as well as OVN's DDlog-based northd implementation.
*/
#include <stdbool.h>
#include "openvswitch/hmap.h"
#include "openvswitch/json.h"
#include "openvswitch/list.h"
#include "openvswitch/shash.h"
#include "openvswitch/uuid.h"
/* Open vSwitch Database client synchronization layer. */
struct json;
struct ovsdb_cs;
struct ovsdb_cs_ops {
/* Returns <monitor-requests> to use for the specified <schema>. The
* implementation might find ovsdb_cs_parse_table_updates() to be a useful
* helper.
*
* The caller might actually use "monitor_cond" or "monitor_cond_since",
* rather than plain "monitor". If so, this function's implementation
* doesn't need to worry about that, because the caller will add the
* conditions itself. */
struct json *(*compose_monitor_requests)(const struct json *schema,
void *aux);
};
/* An event is a happening that is worth reporting to the CS client.
*
* Currently there are three kinds of events:
*
* - "Reconnect": The connection to the database was lost and it is now
* being reconnected. This means that any transactions submitted by the
* client will never receive a reply (although it's possible that some of
* them were actually committed). This event has no associated data.
*
* - "Locked": The server granted the lock we requested.
*
* - "Update": The server sent an update to one or more monitored tables.
* The client can use the associated data to update its idea of the
* snapshot.
*
* - "Transaction reply": The server sent a reply to a transaction sent by
* the client using ovsdb_cs_send_transaction().
*/
struct ovsdb_cs_event {
struct ovs_list list_node;
enum ovsdb_cs_event_type {
OVSDB_CS_EVENT_TYPE_RECONNECT, /* Connection lost. */
OVSDB_CS_EVENT_TYPE_LOCKED, /* Got the lock we wanted. */
OVSDB_CS_EVENT_TYPE_UPDATE, /* Received update notification. */
OVSDB_CS_EVENT_TYPE_TXN_REPLY, /* Received reply to transaction. */
} type;
union {
/* Represents a <table-updates> or <table-updates2> that contains
* either the initial data in a monitor reply or a delta received in an
* update notification. The client can use this to update its database
* replica.
*
* If 'clear' is true, then the client should first clear its idea of
* what's in the replica before applying the update; otherwise, it's an
* incremental update.
*
* If 'monitor_reply' is true, then this comes from a monitor reply.
* This doesn't have real semantic meaning, but it allows the caller
* to imitate the exact behavior of previous versions of code that
* behaved differently on updates from monitor replies vs. updates.
*
* 'table-updates' is a <table-updates> if 'version' if 1, otherwise a
* <table-updates2>. The client can use ovsdb_cs_parse_table_updates()
* to parse the update.
*/
struct ovsdb_cs_update_event {
bool clear;
bool monitor_reply;
struct json *table_updates;
int version;
} update;
/* The "result" member from a transaction reply. The transaction is
* one sent by the client using ovsdb_cs_send_transaction(). The
* client can match 'txn_reply->id' against the ID in a transaction it
* sent. */
struct jsonrpc_msg *txn_reply;
};
};
void ovsdb_cs_event_destroy(struct ovsdb_cs_event *);
/* Lifecycle. */
struct ovsdb_cs *ovsdb_cs_create(const char *database, int max_version,
const struct ovsdb_cs_ops *ops,
void *ops_aux);
void ovsdb_cs_destroy(struct ovsdb_cs *);
void ovsdb_cs_run(struct ovsdb_cs *, struct ovs_list *events);
void ovsdb_cs_wait(struct ovsdb_cs *);
/* Network connection. */
void ovsdb_cs_set_remote(struct ovsdb_cs *, const char *remote, bool retry);
void ovsdb_cs_enable_reconnect(struct ovsdb_cs *);
void ovsdb_cs_force_reconnect(struct ovsdb_cs *);
void ovsdb_cs_flag_inconsistency(struct ovsdb_cs *);
bool ovsdb_cs_is_alive(const struct ovsdb_cs *);
bool ovsdb_cs_is_connected(const struct ovsdb_cs *);
int ovsdb_cs_get_last_error(const struct ovsdb_cs *);
void ovsdb_cs_set_probe_interval(const struct ovsdb_cs *, int probe_interval);
/* Conditional monitoring (specifying that only rows matching particular
* criteria should be monitored).
*
* Some database servers don't support conditional monitoring; in that case,
* the client will get all the rows. */
unsigned int ovsdb_cs_set_condition(struct ovsdb_cs *, const char *table,
const struct json *condition);
unsigned int ovsdb_cs_get_condition_seqno(const struct ovsdb_cs *);
/* Clustered servers. */
void ovsdb_cs_set_leader_only(struct ovsdb_cs *, bool leader_only);
void ovsdb_cs_set_shuffle_remotes(struct ovsdb_cs *, bool shuffle);
void ovsdb_cs_reset_min_index(struct ovsdb_cs *);
/* Database locks. */
void ovsdb_cs_set_lock(struct ovsdb_cs *, const char *lock_name);
const char *ovsdb_cs_get_lock(const struct ovsdb_cs *);
bool ovsdb_cs_has_lock(const struct ovsdb_cs *);
bool ovsdb_cs_is_lock_contended(const struct ovsdb_cs *);
/* Transactions. */
bool ovsdb_cs_may_send_transaction(const struct ovsdb_cs *);
struct json *ovsdb_cs_send_transaction(struct ovsdb_cs *, struct json *ops)
OVS_WARN_UNUSED_RESULT;
bool ovsdb_cs_forget_transaction(struct ovsdb_cs *, const struct json *);
/* Helper for partially parsing the <table-updates> or <table-updates2> that
* appear in struct ovsdb_cs_update_event. The helper leaves the data in JSON
* format, so it doesn't need to know column types. */
@@ -61,6 +194,8 @@ struct ovsdb_error *ovsdb_cs_parse_db_update(
struct ovsdb_cs_db_update **db_updatep)
OVS_WARN_UNUSED_RESULT;
void ovsdb_cs_db_update_destroy(struct ovsdb_cs_db_update *);
const struct ovsdb_cs_table_update *ovsdb_cs_db_update_find_table(
const struct ovsdb_cs_db_update *, const char *table_name);
/* Simple parsing of OVSDB schemas for use by ovsdb_cs clients. */