Merge lp:~larryprice/libertine/better-db-locking into lp:libertine

Proposed by Larry Price on 2017-03-29
Status: Merged
Approved by: Christopher Townsend on 2017-03-29
Approved revision: 415
Merged at revision: 453
Proposed branch: lp:~larryprice/libertine/better-db-locking
Merge into: lp:libertine
Diff against target: 119 lines (+52/-17)
1 file modified
python/libertine/ContainersConfig.py (+52/-17)
To merge this branch: bzr merge lp:~larryprice/libertine/better-db-locking
Reviewer Review Type Date Requested Status
Christopher Townsend 2017-03-29 Approve on 2017-03-29
Libertine CI Bot continuous-integration Approve on 2017-03-29
Review via email: mp+321329@code.launchpad.net

Commit message

Reopen the database file after every failure to grab the lock.

Description of the change

Reopen the database file after every failure to grab the lock.

To post a comment you must log in.
Libertine CI Bot (libertine-ci-bot) wrote :

PASSED: Continuous integration, rev:415
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/493/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/892
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/736
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=zesty,testname=default/736
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/736
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=zesty,testname=default/736
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/902
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/893
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/893/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/893
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/893/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/893
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/893/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/893
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/893/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/493/rebuild

review: Approve (continuous-integration)
Christopher Townsend (townsend) wrote :

Nice, +1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'python/libertine/ContainersConfig.py'
2--- python/libertine/ContainersConfig.py 2017-02-23 21:08:28 +0000
3+++ python/libertine/ContainersConfig.py 2017-03-29 16:52:33 +0000
4@@ -14,42 +14,77 @@
5
6 import fcntl
7 import json
8-import libertine.utils
9 import os
10 import sys
11+import errno
12+import time
13+
14 from hashlib import md5
15-from libertine.HostInfo import HostInfo
16+from . import utils, HostInfo
17+
18+class _ContainersConfigFile(object):
19+ def __init__(self, readonly=True):
20+ self._readonly = readonly
21+
22+ if readonly:
23+ self._flags = 'r'
24+ else:
25+ self._flags = 'w'
26+
27+ self._fd = None
28+
29+ def __enter__(self):
30+ container_config_file = utils.get_libertine_database_file_path()
31+ if self._readonly and (not os.path.exists(container_config_file) or
32+ os.path.getsize(container_config_file) == 0):
33+ return None
34+
35+ retries = 0
36+ while retries < 100:
37+ try:
38+ fd = open(container_config_file, self._flags)
39+ fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
40+
41+ self._fd = fd
42+ return self._fd
43+ except IOError as e:
44+ if e.errno != errno.EAGAIN:
45+ raise
46+ else:
47+ fd.close()
48+ retries += 1
49+ time.sleep(0.05)
50+
51+ def __exit__(self, *args):
52+ if self._fd:
53+ self._fd.close()
54
55
56 def read_container_config_file():
57 container_list = {}
58- container_config_file = libertine.utils.get_libertine_database_file_path()
59-
60- if (os.path.exists(container_config_file) and
61- os.path.getsize(container_config_file) != 0):
62- with open(container_config_file, 'r') as fd:
63- fcntl.flock(fd, fcntl.LOCK_EX)
64+ with _ContainersConfigFile() as fd:
65+ if fd is not None:
66 container_list = json.load(fd)
67
68 return container_list
69
70
71 def write_container_config_file(container_list):
72- container_config_file = libertine.utils.get_libertine_database_file_path()
73+ container_config_file = utils.get_libertine_database_file_path()
74
75 # Add a warning to adventurous users advising against mucking with this file
76 if container_list is not None:
77 container_list["_warning"] = "This file is automatically generated by Libertine and should not be manually edited."
78
79- with open(container_config_file, 'w') as fd:
80- fcntl.flock(fd, fcntl.LOCK_EX)
81- json.dump(container_list, fd, sort_keys=True, indent=4)
82- fd.write('\n')
83+ with _ContainersConfigFile(False) as fd:
84+ if fd:
85+ json.dump(container_list, fd, sort_keys=True, indent=4)
86+ fd.write('\n')
87
88
89 def container_config_hash():
90 checksum = md5()
91- container_config_file = libertine.utils.get_libertine_database_file_path()
92+ container_config_file = utils.get_libertine_database_file_path()
93 if (os.path.exists(container_config_file) and os.path.getsize(container_config_file) != 0):
94 with open(container_config_file, "rb") as fd:
95 fcntl.flock(fd, fcntl.LOCK_EX)
96@@ -214,12 +249,12 @@
97
98 def check_container_id(self, container_id):
99 if container_id and not self.container_exists(container_id):
100- libertine.utils.get_logger().error("Container id \'%s\' does not exist." % container_id)
101+ utils.get_logger().error("Container id '{container_id}' does not exist.".format(container_id=container_id))
102 sys.exit(1)
103 elif not container_id:
104 container_id = self.get_default_container_id()
105 if container_id is None:
106- libertine.utils.get_logger().error("No default container available.")
107+ utils.get_logger().error("No default container available.")
108 sys.exit(1)
109
110 return container_id
111@@ -263,7 +298,7 @@
112
113 def delete_container(self, container_id):
114 if not self.container_list:
115- libertine.utils.get_logger().error("Unable to delete container. No containers defined.")
116+ utils.get_logger().error("Unable to delete container. No containers defined.")
117 sys.exit(1)
118
119 container = self._get_container_entry(container_id)

Subscribers

People subscribed via source and target branches