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

Proposed by Larry Price
Status: Merged
Approved by: Christopher Townsend
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 Approve
Libertine CI Bot continuous-integration Approve
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.
Revision history for this message
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)
Revision history for this message
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
=== modified file 'python/libertine/ContainersConfig.py'
--- python/libertine/ContainersConfig.py 2017-02-23 21:08:28 +0000
+++ python/libertine/ContainersConfig.py 2017-03-29 16:52:33 +0000
@@ -14,42 +14,77 @@
1414
15import fcntl15import fcntl
16import json16import json
17import libertine.utils
18import os17import os
19import sys18import sys
19import errno
20import time
21
20from hashlib import md522from hashlib import md5
21from libertine.HostInfo import HostInfo23from . import utils, HostInfo
24
25class _ContainersConfigFile(object):
26 def __init__(self, readonly=True):
27 self._readonly = readonly
28
29 if readonly:
30 self._flags = 'r'
31 else:
32 self._flags = 'w'
33
34 self._fd = None
35
36 def __enter__(self):
37 container_config_file = utils.get_libertine_database_file_path()
38 if self._readonly and (not os.path.exists(container_config_file) or
39 os.path.getsize(container_config_file) == 0):
40 return None
41
42 retries = 0
43 while retries < 100:
44 try:
45 fd = open(container_config_file, self._flags)
46 fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
47
48 self._fd = fd
49 return self._fd
50 except IOError as e:
51 if e.errno != errno.EAGAIN:
52 raise
53 else:
54 fd.close()
55 retries += 1
56 time.sleep(0.05)
57
58 def __exit__(self, *args):
59 if self._fd:
60 self._fd.close()
2261
2362
24def read_container_config_file():63def read_container_config_file():
25 container_list = {}64 container_list = {}
26 container_config_file = libertine.utils.get_libertine_database_file_path()65 with _ContainersConfigFile() as fd:
2766 if fd is not None:
28 if (os.path.exists(container_config_file) and
29 os.path.getsize(container_config_file) != 0):
30 with open(container_config_file, 'r') as fd:
31 fcntl.flock(fd, fcntl.LOCK_EX)
32 container_list = json.load(fd)67 container_list = json.load(fd)
3368
34 return container_list69 return container_list
3570
3671
37def write_container_config_file(container_list):72def write_container_config_file(container_list):
38 container_config_file = libertine.utils.get_libertine_database_file_path()73 container_config_file = utils.get_libertine_database_file_path()
3974
40 # Add a warning to adventurous users advising against mucking with this file75 # Add a warning to adventurous users advising against mucking with this file
41 if container_list is not None:76 if container_list is not None:
42 container_list["_warning"] = "This file is automatically generated by Libertine and should not be manually edited."77 container_list["_warning"] = "This file is automatically generated by Libertine and should not be manually edited."
4378
44 with open(container_config_file, 'w') as fd:79 with _ContainersConfigFile(False) as fd:
45 fcntl.flock(fd, fcntl.LOCK_EX)80 if fd:
46 json.dump(container_list, fd, sort_keys=True, indent=4)81 json.dump(container_list, fd, sort_keys=True, indent=4)
47 fd.write('\n')82 fd.write('\n')
4883
4984
50def container_config_hash():85def container_config_hash():
51 checksum = md5()86 checksum = md5()
52 container_config_file = libertine.utils.get_libertine_database_file_path()87 container_config_file = utils.get_libertine_database_file_path()
53 if (os.path.exists(container_config_file) and os.path.getsize(container_config_file) != 0):88 if (os.path.exists(container_config_file) and os.path.getsize(container_config_file) != 0):
54 with open(container_config_file, "rb") as fd:89 with open(container_config_file, "rb") as fd:
55 fcntl.flock(fd, fcntl.LOCK_EX)90 fcntl.flock(fd, fcntl.LOCK_EX)
@@ -214,12 +249,12 @@
214249
215 def check_container_id(self, container_id):250 def check_container_id(self, container_id):
216 if container_id and not self.container_exists(container_id):251 if container_id and not self.container_exists(container_id):
217 libertine.utils.get_logger().error("Container id \'%s\' does not exist." % container_id)252 utils.get_logger().error("Container id '{container_id}' does not exist.".format(container_id=container_id))
218 sys.exit(1)253 sys.exit(1)
219 elif not container_id:254 elif not container_id:
220 container_id = self.get_default_container_id()255 container_id = self.get_default_container_id()
221 if container_id is None:256 if container_id is None:
222 libertine.utils.get_logger().error("No default container available.")257 utils.get_logger().error("No default container available.")
223 sys.exit(1)258 sys.exit(1)
224259
225 return container_id260 return container_id
@@ -263,7 +298,7 @@
263298
264 def delete_container(self, container_id):299 def delete_container(self, container_id):
265 if not self.container_list:300 if not self.container_list:
266 libertine.utils.get_logger().error("Unable to delete container. No containers defined.")301 utils.get_logger().error("Unable to delete container. No containers defined.")
267 sys.exit(1)302 sys.exit(1)
268303
269 container = self._get_container_entry(container_id)304 container = self._get_container_entry(container_id)

Subscribers

People subscribed via source and target branches