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

Reply via email to