<commit_before>API Races - Conditional Updates
===============================

Background
----------

On Cinder API nodes we have to check that requested action can be performed by
checking request arguments and involved resources, and only if everything
matches required criteria we will proceed with the RPC call to any of the other
nodes.

Checking the conditions must be done in a non racy way to ensure that already
checked requirements don't change while we check remaining conditions.  This is
of utter importance, as Cinder uses resource status as a lock to prevent
concurrent operations on a resource.

An simple example of this would be extending a volume, where we first check the
status:

.. code:: python

   if volume['status'] != 'available':

Then update the status:

.. code:: python

       self.update(context, volume, {'status': 'extending'})

And finally make the RPC call:

.. code:: python

       self.volume_rpcapi.extend_volume(context, volume, new_size,
                                        reservations)

The problem is that that this code would allow races, as other request could
have already changed the volume status between us getting the value and
updating the DB.

There are multiple ways to fix this, such as:

- Using a Distributed Locking Mechanism
- Using DB isolation level
- Using SQL SELECT ... FOR UPDATE
- USING compare and swap mechanism in SQL query

Our tests showed that the best alternative was compare and swap and we decided
to call this mechanism "Conditional Update" as it seemed more appropriate.

Conditional Update<commit_msg>Fix typo: remove redundant 'that'<commit_after>API Races - Conditional Updates
===============================

Background
----------

On Cinder API nodes we have to check that requested action can be performed by
checking request arguments and involved resources, and only if everything
matches required criteria we will proceed with the RPC call to any of the other
nodes.

Checking the conditions must be done in a non racy way to ensure that already
checked requirements don't change while we check remaining conditions.  This is
of utter importance, as Cinder uses resource status as a lock to prevent
concurrent operations on a resource.

An simple example of this would be extending a volume, where we first check the
status:

.. code:: python

   if volume['status'] != 'available':

Then update the status:

.. code:: python

       self.update(context, volume, {'status': 'extending'})

And finally make the RPC call:

.. code:: python

       self.volume_rpcapi.extend_volume(context, volume, new_size,
                                        reservations)

The problem is that this code would allow races, as other request could
have already changed the volume status between us getting the value and
updating the DB.

There are multiple ways to fix this, such as:

- Using a Distributed Locking Mechanism
- Using DB isolation level
- Using SQL SELECT ... FOR UPDATE
- USING compare and swap mechanism in SQL query

Our tests showed that the best alternative was compare and swap and we decided
to call this mechanism "Conditional Update" as it seemed more appropriate.

Conditional Update
{'fraction_non_alphanumeric': 0.06934421085660496, 'fraction_numerical': 0.0, 'mean_word_length': 3.6882352941176473, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1552290', 'n_tokens_mistral': 754, 'n_tokens_neox': 731, 'n_words': 442}