summaryrefslogtreecommitdiffstats
path: root/utils/test/testapi/opnfv_testapi
diff options
context:
space:
mode:
authorSerenaFeng <feng.xiaowei@zte.com.cn>2017-06-27 19:13:32 +0800
committerSerenaFeng <feng.xiaowei@zte.com.cn>2017-06-27 19:13:32 +0800
commitfe167ee5b7cb84897c06fdc7a8b20342defff9bf (patch)
tree09e0e6612b80319cecfee10e5adcdea9daf90229 /utils/test/testapi/opnfv_testapi
parent6a9f0ce6edf92e57282ff7b69fb3d47e75234833 (diff)
bugfix: pagination crash due to memory limitation
MongoDB sorts the results in memory, and the default mem limitation is 32M, if the sort operation consumes more than that it will return an error: OperationFailure: Executor error during find command: OperationFailed Sort operation used more than the maximum 33554432 bytes of RAM. Add an index, or specify a smaller limit. To solve this problem, here we leverage aggregate() and allowDiskUse=True, it is said will not be limited by memory Change-Id: Id698ad1d02912e8b350a33a926fcccc390814fcc Signed-off-by: SerenaFeng <feng.xiaowei@zte.com.cn>
Diffstat (limited to 'utils/test/testapi/opnfv_testapi')
-rw-r--r--utils/test/testapi/opnfv_testapi/resources/handlers.py35
-rw-r--r--utils/test/testapi/opnfv_testapi/resources/result_handlers.py4
-rw-r--r--utils/test/testapi/opnfv_testapi/tests/unit/fake_pymongo.py34
3 files changed, 54 insertions, 19 deletions
diff --git a/utils/test/testapi/opnfv_testapi/resources/handlers.py b/utils/test/testapi/opnfv_testapi/resources/handlers.py
index 42372e837..0234c8a73 100644
--- a/utils/test/testapi/opnfv_testapi/resources/handlers.py
+++ b/utils/test/testapi/opnfv_testapi/resources/handlers.py
@@ -105,21 +105,36 @@ class GenericApiHandler(web.RequestHandler):
query = {}
data = []
sort = kwargs.get('sort')
- page = kwargs.get('page')
- last = kwargs.get('last')
- per_page = kwargs.get('per_page')
+ page = kwargs.get('page', 0)
+ last = kwargs.get('last', 0)
+ per_page = kwargs.get('per_page', 0)
cursor = self._eval_db(self.table, 'find', query)
+ records_count = yield cursor.count()
+ records_nr = records_count
+ if (records_count > last) and (last > 0):
+ records_nr = last
+
+ pipelines = list()
+ if query:
+ pipelines.append({'$match': query})
if sort:
- cursor = cursor.sort(sort)
- if last and last != 0:
- cursor = cursor.limit(last)
- if page:
- records_count = yield cursor.count()
- total_pages, remainder = divmod(records_count, per_page)
+ pipelines.append({'$sort': sort})
+
+ if page > 0:
+ total_pages, remainder = divmod(records_nr, per_page)
if remainder > 0:
total_pages += 1
- cursor = cursor.skip((page - 1) * per_page).limit(per_page)
+ pipelines.append({'$skip': (page - 1) * per_page})
+ pipelines.append({'$limit': per_page})
+ else:
+ pipelines.append({'$limit': records_nr})
+
+ cursor = self._eval_db(self.table,
+ 'aggregate',
+ pipelines,
+ allowDiskUse=True)
+
while (yield cursor.fetch_next):
data.append(self.format_data(cursor.next_object()))
if res_op is None:
diff --git a/utils/test/testapi/opnfv_testapi/resources/result_handlers.py b/utils/test/testapi/opnfv_testapi/resources/result_handlers.py
index 208af6da2..1773216c0 100644
--- a/utils/test/testapi/opnfv_testapi/resources/result_handlers.py
+++ b/utils/test/testapi/opnfv_testapi/resources/result_handlers.py
@@ -147,13 +147,13 @@ class ResultsCLHandler(GenericResultHandler):
@in trust_indicator: query
@required trust_indicator: False
"""
- limitations = {'sort': [('start_date', -1)]}
+ limitations = {'sort': {'start_date': -1}}
last = self.get_query_argument('last', 0)
if last is not None:
last = self.get_int('last', last)
limitations.update({'last': last})
- page = self.get_query_argument('page', 1)
+ page = self.get_query_argument('page', None)
if page is not None:
page = self.get_int('page', page)
limitations.update({'page': page,
diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/fake_pymongo.py b/utils/test/testapi/opnfv_testapi/tests/unit/fake_pymongo.py
index b2564a6de..adaf6f7c3 100644
--- a/utils/test/testapi/opnfv_testapi/tests/unit/fake_pymongo.py
+++ b/utils/test/testapi/opnfv_testapi/tests/unit/fake_pymongo.py
@@ -35,15 +35,14 @@ class MemCursor(object):
return self.collection.pop()
def sort(self, key_or_list):
- key = key_or_list[0][0]
- if key_or_list[0][1] == -1:
- reverse = True
- else:
- reverse = False
+ for k, v in key_or_list.iteritems():
+ if v == -1:
+ reverse = True
+ else:
+ reverse = False
- if key_or_list is not None:
self.collection = sorted(self.collection,
- key=itemgetter(key), reverse=reverse)
+ key=itemgetter(k), reverse=reverse)
return self
def limit(self, limit):
@@ -202,6 +201,27 @@ class MemDb(object):
def find(self, *args):
return MemCursor(self._find(*args))
+ def _aggregate(self, *args, **kwargs):
+ res = self.contents
+ print args
+ for arg in args[0]:
+ for k, v in arg.iteritems():
+ if k == '$match':
+ res = self._find(v)
+ cursor = MemCursor(res)
+ for arg in args[0]:
+ for k, v in arg.iteritems():
+ if k == '$sort':
+ cursor = cursor.sort(v)
+ elif k == '$skip':
+ cursor = cursor.skip(v)
+ elif k == '$limit':
+ cursor = cursor.limit(v)
+ return cursor
+
+ def aggregate(self, *args, **kwargs):
+ return self._aggregate(*args, **kwargs)
+
def _update(self, spec, document, check_keys=True):
updated = False