From 25930c1a52b972fd2053cf9626f95cb60251091b Mon Sep 17 00:00:00 2001 From: John Mulligan Date: Wed, 15 May 2024 18:25:40 -0400 Subject: [PATCH] mgr/smb: add store transactions to parts of the handler Add a wrapper contextmethod that initiates a transaction on a store if said store supports transactions (otherwise the ctx manager is a no-op). Use the wrapper over certain functions in the handler where many store operations may be needed. This makes a big performance difference when using a sqlite db backed store. Signed-off-by: John Mulligan --- src/pybind/mgr/smb/handler.py | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/pybind/mgr/smb/handler.py b/src/pybind/mgr/smb/handler.py index ae776318ea5..0595138687a 100644 --- a/src/pybind/mgr/smb/handler.py +++ b/src/pybind/mgr/smb/handler.py @@ -12,6 +12,7 @@ from typing import ( cast, ) +import contextlib import logging import operator import time @@ -357,10 +358,13 @@ class ClusterConfigHandler: incoming = order_resources(inputs) for resource in incoming: staging.stage(resource) - for resource in incoming: - results.append( - self._check(resource, staging, create_only=create_only) - ) + with _store_transaction(staging.destination_store): + for resource in incoming: + results.append( + self._check( + resource, staging, create_only=create_only + ) + ) except ErrorResult as err: results.append(err) except Exception as err: @@ -372,9 +376,11 @@ class ClusterConfigHandler: 'successfully updated %s resources. syncing changes to public stores', len(list(results)), ) - results = staging.save() - _prune_linked_entries(staging) - self._sync_modified(results) + with _store_transaction(staging.destination_store): + results = staging.save() + _prune_linked_entries(staging) + with _store_transaction(staging.destination_store): + self._sync_modified(results) return results def cluster_ids(self) -> List[str]: @@ -1298,3 +1304,15 @@ def _cephx_data_entity(cluster_id: str) -> str: use for data access. """ return f'client.smb.fs.cluster.{cluster_id}' + + +@contextlib.contextmanager +def _store_transaction(store: ConfigStore) -> Iterator[None]: + transaction = getattr(store, 'transaction', None) + if not transaction: + log.debug("No transaction support for store") + yield None + return + log.debug("Using store transaction") + with transaction(): + yield None -- 2.39.5