On 7/2/21 12:24 PM, Mark Gray wrote:
> On 12/06/2021 03:00, Ilya Maximets wrote:
>> Current version of ovsdb relay allows to scale out read-only
>> access to the primary database. However, many clients are not
>> read-only but read-mostly. For example, ovn-controller.
>>
>> In order to scale out database access for this case ovsdb-server
>> need to process transactions that are not read-only. Relay is not
>> allowed to do that, i.e. not allowed to modify the database, but it
>> can act like a proxy and forward transactions that includes database
>> modifications to the primary server and forward replies back to a
>> client. At the same time it may serve read-only transactions and
>> monitor requests by itself greatly reducing the load on primary
>> server.
>>
>> This configuration will slightly increase transaction latency, but
>> it's not very important for read-mostly use cases.
>>
>> Implementation details:
>> With this change instead of creating a trigger to commit the
>> transaction, ovsdb-server will create a trigger for transaction
>> forwarding. Later, ovsdb_relay_run() will send all new transactions
>> to the relay source. Once transaction reply received from the
>> relay source, ovsdb-relay module will update the state of the
>> transaction forwarding with the reply. After that, trigger_run()
>> will complete the trigger and jsonrpc_server_run() will send the
>> reply back to the client. Since transaction reply from the relay
>> source will be received after all the updates, client will receive
>> all the updates before receiving the transaction reply as it is in
>> a normal scenario with other database models.
>>
>> Signed-off-by: Ilya Maximets <[email protected]>
>> ---
<snip>
>> @@ -188,7 +196,7 @@ static bool
>> ovsdb_trigger_try(struct ovsdb_trigger *t, long long int now)
>> {
>> /* Handle "initialized" state. */
>> - if (!t->reply) {
>> + if (!t->reply && !t->txn_forward) {
>> ovs_assert(!t->progress);
>>
>> struct ovsdb_txn *txn = NULL;
>> @@ -198,13 +206,14 @@ ovsdb_trigger_try(struct ovsdb_trigger *t, long long
>> int now)
>> return false;
>> }
>>
>> - bool durable;
>> + bool durable, forwarding_needed;
>>
>> struct json *result;
>> + /* Trying to compose transaction. */
>> txn = ovsdb_execute_compose(
>> t->db, t->session, t->request->params, t->read_only,
>> t->role, t->id, now - t->created, &t->timeout_msec,
>> - &durable, &result);
>> + &durable, &forwarding_needed, &result);
>> if (!txn) {
>> if (result) {
>> /* Complete. There was an error but we still represent
>> it
>> @@ -217,9 +226,20 @@ ovsdb_trigger_try(struct ovsdb_trigger *t, long long
>> int now)
>> return false;
>> }
>>
>> - /* Transition to "committing" state. */
>> - t->reply = jsonrpc_create_reply(result, t->request->id);
>> - t->progress = ovsdb_txn_propose_commit(txn, durable);
>> + if (forwarding_needed) {
>> + /* Transaction is good, but we don't need it. */
>> + ovsdb_txn_abort(txn);
>> + json_destroy(result);
>> + /* Transition to "forwarding" state. */
>> + t->txn_forward = ovsdb_txn_forward_create(t->db,
>> t->request);
>> + /* Forward will not be completed immediately. Will check
>> + * next time. */
>> + return false;
>> + } else {
>> + /* Transition to "committing" state. */
>> + t->reply = jsonrpc_create_reply(result, t->request->id);
>> + t->progress = ovsdb_txn_propose_commit(txn, durable);
>> + }
>> } else if (!strcmp(t->request->method, "convert")) {
>> /* Permission check. */
>> if (t->role && *t->role) {
>> @@ -348,6 +368,18 @@ ovsdb_trigger_try(struct ovsdb_trigger *t, long long
>> int now)
>> ovsdb_trigger_complete(t);
>> }
>>
>> + return false;
>> + } else if (t->txn_forward) {
>> + /* Handle "forwarding" state. */
>
> Should we assert that reply == NULL and progress == NULL?
Should not be necessary. We're here from the else branch of
if (t->progress), so progrees is definitely NULL.
But we can check for 'reply'. I'll add the check.
>
>> + if (!ovsdb_txn_forward_is_complete(t->txn_forward)) {
>> + return false;
>> + }
>> +
>> + /* Transition to "complete". */
But I'll add a check here, to be sure that we're not leaking
the reply.
>> + t->reply = ovsdb_txn_forward_steal_reply(t->txn_forward);
>> + ovsdb_txn_forward_destroy(t->db, t->txn_forward);
>> + t->txn_forward = NULL;
>> + ovsdb_trigger_complete(t);
>> return false;
>> }
>>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev