[Kimchi-devel] [kimchi-devel][PATCHv4 3/7] Add lock facility for storage volume upload

Aline Manera alinefm at linux.vnet.ibm.com
Mon May 4 19:40:58 UTC 2015



On 22/04/2015 05:02, lvroyce at linux.vnet.ibm.com wrote:
> From: Royce Lv <lvroyce at linux.vnet.ibm.com>
>
> This lock facility guarentees 5 concurrent volume upload
> and make sure locks are created and reclaimed when needed.
>
> Signed-off-by: Royce Lv <lvroyce at linux.vnet.ibm.com>
> ---
>   src/kimchi/i18n.py        |  1 +
>   src/kimchi/model/utils.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 47 insertions(+)
>
> diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
> index c012a62..b712c16 100644
> --- a/src/kimchi/i18n.py
> +++ b/src/kimchi/i18n.py
> @@ -216,6 +216,7 @@ messages = {
>       "KCHVOL0022E": _("Unable to access file %(url)s. Please, check it."),
>       "KCHVOL0023E": _("Unable to clone storage volume '%(name)s' in pool '%(pool)s'. Details: %(err)s"),
>       "KCHVOL0024E": _("Upload volume chunk index, size and total size must be integer"),
> +    "KCHVOL0026E": _("Inconsistent upload count"),

A more detailed message would be useful to we really know what is going 
wrong.

>       "KCHIFACE0001E": _("Interface %(name)s does not exist"),
>
> diff --git a/src/kimchi/model/utils.py b/src/kimchi/model/utils.py
> index b2739b2..b089be5 100644
> --- a/src/kimchi/model/utils.py
> +++ b/src/kimchi/model/utils.py

The code below is only related to storage volume upload feature so I 
suggest to move it to model/storagevolumes.py

The model/utils.py should be used only for generic matters.

> @@ -19,6 +19,7 @@
>
>   import libvirt
>   import socket
> +import threading
>   import urlparse
>   from lxml import etree, objectify
>   from lxml.builder import E, ElementMaker
> @@ -28,6 +29,11 @@ from kimchi.model.featuretests import FeatureTests
>
>   KIMCHI_META_URL = "https://github.com/kimchi-project/kimchi"
>   KIMCHI_NAMESPACE = "kimchi"
> +UPLOAD_THREADS = 5  # Concurrent upload volume counts at the same time
> +
> +upload_semaphore = threading.BoundedSemaphore(value=UPLOAD_THREADS)
> +upload_lock_pool = dict()
> +pool_lock = threading.Lock()
>
>
>   def get_vm_name(vm_name, t_name, name_list):
> @@ -162,3 +168,43 @@ def get_metadata_node(dom, tag, metadata_support, mode="current"):
>           if node is not None:
>               return etree.tostring(node)
>       return ""
> +
> +
> +class UpdateLock(object):
> +    def __init__(self):
> +        self.ref_cnt = 0
> +        self.lock = threading.Lock()
> +
> +    def get_lock(self):
> +        self.ref_cnt += 1
> +        return self.lock
> +
> +    def release_lock(self):
> +        delete = False
> +        self.ref_cnt -= 1
> +        if (self.ref_cnt == 0):
> +            delete = True
> +        return delete
> +
> +
> +def get_vol_update_lock(vol_path):
> +    # upload_semaphore controls the max upload count
> +    upload_semaphore.acquire()
> +
> +    # pool lock make sure lock list get/store action is atomic
> +    with pool_lock:
> +        vol_lock = upload_lock_pool.get(vol_path)
> +        if vol_lock:
> +            return vol_lock.get_lock()
> +        if len(upload_lock_pool.keys()) > (UPLOAD_THREADS - 1):
> +            raise OperationFailed("KCHVOL0026E")
> +        lock = upload_lock_pool[vol_path] = UpdateLock()
> +        return lock.get_lock()
> +
> +
> +def release_vol_update_lock(vol_path):
> +    with pool_lock:
> +        vol_lock = upload_lock_pool.get(vol_path)
> +        if vol_lock.release_lock():
> +            upload_lock_pool.pop(vol_path, None)
> +    upload_semaphore.release()




More information about the Kimchi-devel mailing list