Fix leaking sockets after v2 list operation

This fixes the same problem with leaking file descriptors after the port
to requests I16a7b02f2b10e506e91719712cf34ef0aea1afc0 does, but for the
v2 api client.

The paginate function in the list method has been refactored from a
recursive generator to a non-recursive generator, which avoids issues
with garbage collection holding the socket open.

Change-Id: Iaa7a421e8c1acafb7b23bb3f55e50b9d2a9d030a
Closes-Bug: #1428797
This commit is contained in:
Louis Taylor
2015-03-05 18:53:54 +00:00
parent 59eec058bc
commit 0ab5a78d78

View File

@@ -54,40 +54,40 @@ class Controller(object):
page_size = kwargs.get('page_size') or DEFAULT_PAGE_SIZE
def paginate(url, page_size, limit=None):
next_url = url
if limit and page_size > limit:
# NOTE(flaper87): Avoid requesting 2000 images when limit is 1
url = url.replace("limit=%s" % page_size,
"limit=%s" % limit)
while True:
if limit and page_size > limit:
# NOTE(flaper87): Avoid requesting 2000 images when limit
# is 1
next_url = next_url.replace("limit=%s" % page_size,
"limit=%s" % limit)
resp, body = self.http_client.get(url)
for image in body['images']:
# NOTE(bcwaldon): remove 'self' for now until we have
# an elegant way to pass it into the model constructor
# without conflict.
image.pop('self', None)
yield self.model(**image)
# NOTE(zhiyan): In order to resolve the performance issue
# of JSON schema validation for image listing case, we
# don't validate each image entry but do it only on first
# image entry for each page.
self.model.validate = empty_fun
resp, body = self.http_client.get(next_url)
for image in body['images']:
# NOTE(bcwaldon): remove 'self' for now until we have
# an elegant way to pass it into the model constructor
# without conflict.
image.pop('self', None)
yield self.model(**image)
# NOTE(zhiyan): In order to resolve the performance issue
# of JSON schema validation for image listing case, we
# don't validate each image entry but do it only on first
# image entry for each page.
self.model.validate = empty_fun
if limit:
limit -= 1
if limit <= 0:
raise StopIteration
if limit:
limit -= 1
if limit <= 0:
raise StopIteration
# NOTE(zhiyan); Reset validation function.
self.model.validate = ori_validate_fun
# NOTE(zhiyan); Reset validation function.
self.model.validate = ori_validate_fun
try:
next_url = body['next']
except KeyError:
return
else:
for image in paginate(next_url, page_size, limit):
yield image
try:
next_url = body['next']
except KeyError:
return
filters = kwargs.get('filters', {})
# NOTE(flaper87): We paginate in the client, hence we use