Merge pull request #1009 from rags22489664/master

CLOUDSTACK-9006 - ListTemplates API returns result in inconsistent order when called concurrentlyThe order of templates returned in the response is based on a field called sortkey and by default value for the field is set to 0.

With more than 1000 templates, we tried listing the templates with different page sizes concurrently, and we noticed the results being inconsistent.

Thus we added a secondary order by clause to list templates call on tempZonePair column to make sure the results are consistent.

The addOrderby method of Filter class was also not appending , if we added more orderby clauses.

* pr/1009:
  CLOUDSTACK-9006 - ListTemplates API returns result in inconsistent order when called concurrently
  CLOUDSTACK-9006 - ListTemplates API returns result in inconsistent order when called concurrently

Signed-off-by: Remi Bergsma <github@remi.nl>
This commit is contained in:
Remi Bergsma 2015-11-04 11:48:07 +01:00
commit 5f61041550
4 changed files with 47 additions and 1 deletions

View File

@ -89,7 +89,7 @@ public class Filter {
if (_orderBy == null) {
_orderBy = order.insert(0, " ORDER BY ").toString();
} else {
_orderBy = order.insert(0, _orderBy).toString();
_orderBy = order.insert(0, _orderBy + ", ").toString();
}
}

View File

@ -0,0 +1,44 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.utils.db;
import org.junit.Assert;
import org.junit.Test;
public class FilterTest {
@Test
/*
* This test verifies that the Order By clause generated by the filter is correct and it separates each
* order by field with a comma. Using DbTestVO to assert it
*/
public void testAddOrderBy() {
Filter filter = new Filter(DbTestVO.class, "fieldString", true, 1L, 1L);
Assert.assertTrue(filter.getOrderBy().trim().toLowerCase().equals("order by test.fld_string asc"));
filter.addOrderBy(DbTestVO.class, "fieldLong", true);
Assert.assertTrue(filter.getOrderBy().contains(","));
Assert.assertTrue(filter.getOrderBy().split(",")[1].trim().toLowerCase().equals("test.fld_long asc"));
filter.addOrderBy(DbTestVO.class, "fieldInt", true);
Assert.assertTrue(filter.getOrderBy().split(",").length == 3);
Assert.assertTrue(filter.getOrderBy().split(",")[2].trim().toLowerCase().equals("test.fld_int asc"));
}
}

View File

@ -3106,6 +3106,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
Boolean isAscending = Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm"));
isAscending = (isAscending == null ? Boolean.TRUE : isAscending);
Filter searchFilter = new Filter(TemplateJoinVO.class, "sortKey", isAscending, startIndex, pageSize);
searchFilter.addOrderBy(TemplateJoinVO.class, "tempZonePair", isAscending);
SearchBuilder<TemplateJoinVO> sb = _templateJoinDao.createSearchBuilder();
sb.select(null, Func.DISTINCT, sb.entity().getTempZonePair()); // select distinct (templateId, zoneId) pair

View File

@ -383,6 +383,7 @@ public class TemplateJoinDaoImpl extends GenericDaoBase<TemplateJoinVO, Long> im
Boolean isAscending = Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm"));
isAscending = (isAscending == null ? Boolean.TRUE : isAscending);
Filter searchFilter = new Filter(TemplateJoinVO.class, "sortKey", isAscending, null, null);
searchFilter.addOrderBy(TemplateJoinVO.class, "tempZonePair", isAscending);
List<TemplateJoinVO> uvList = new ArrayList<TemplateJoinVO>();
// query details by batches
int curr_index = 0;