Martin Betak has uploaded a new change for review.

Change subject: utils: Add @throttle decorator
......................................................................

utils: Add @throttle decorator

Added decorator for API methods that need to limit their maximum number of
concurrent operations.

The decorator can be configured for:

* Blocking operations:
  where the request waits to obtain specified semaphore, operation proceeds and
  the semaphore is released

* Non-blocking operations:
  where the request returns specified error when semaphore cannot be obtained
  without blocking and in case it is indeed obtained, it has to be released
    manually afterwareds

Needed for subsequent migration enhancements.
Wiki: http://www.ovirt.org/Features/Migration_Enhancements

Change-Id: Iab4cf387f77a9b720afb7794e27ed54efa0d3e3c
Signed-off-by: Martin Betak <[email protected]>
---
M vdsm/virt/utils.py
1 file changed, 45 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/87/47087/1

diff --git a/vdsm/virt/utils.py b/vdsm/virt/utils.py
index 55a60c6..6bd7afa 100644
--- a/vdsm/virt/utils.py
+++ b/vdsm/virt/utils.py
@@ -21,10 +21,12 @@
 """
 shared utilities and common code for the virt package
 """
+from functools import wraps
 
 import os.path
 import threading
 
+from vdsm import response
 from vdsm.utils import monotonic_time, rmFile
 
 
@@ -117,3 +119,46 @@
     if os.path.islink(sock):
         rmFile(os.path.realpath(sock))
     rmFile(sock)
+
+
+def throttle(semaphore, err, block):
+    """
+    Helper decorator for API methods that should have limited number
+    of concurrent executions.
+
+    When block=True we will wait to obtain the semaphore and
+    release it after wrapped method execution.
+
+    When block=False we won't wait to obtain the semaphore and
+    in case this fails, will return the specified error. If the execution of
+    wrapped method succeeds, it is the responsibility of called code to
+    release the semaphore (i.e. method is assumed to be async)
+
+    :param semaphore: synchronisation mechanism to use for throttling
+    :param err:       error name to return in case of full capacity
+                      (only applicable when block=False)
+    :param block:     mode of operation
+    :return:
+    """
+
+    def decorator(f):
+        @wraps(f)
+        def wrapper(*args, **kwargs):
+            acquired = semaphore.acquire(block)
+            if not acquired:
+                return response.error(err)
+
+            success = True
+            try:
+                result = f(*args, **kwargs)
+                success = not response.is_error(result)
+            except Exception:
+                success = False
+                raise
+            finally:
+                if not success or block:
+                    semaphore.release()
+
+        return wrapper
+
+    return decorator


-- 
To view, visit https://gerrit.ovirt.org/47087
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Iab4cf387f77a9b720afb7794e27ed54efa0d3e3c
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Martin Betak <[email protected]>
_______________________________________________
vdsm-patches mailing list
[email protected]
https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches

Reply via email to