Bug 1099097 - packages.search APIs returning only one match per package name
Summary: packages.search APIs returning only one match per package name
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: Spacewalk
Classification: Community
Component: API
Version: 2.2
Hardware: All
OS: All
urgent
medium
Target Milestone: ---
Assignee: Stephen Herr
QA Contact: Red Hat Satellite QA List
URL:
Whiteboard:
Depends On: 1074083
Blocks: space22
TreeView+ depends on / blocked
 
Reported: 2014-05-19 13:36 UTC by Stephen Herr
Modified: 2014-07-17 08:41 UTC (History)
10 users (show)

Fixed In Version: spacewalk-java-2.2.59-1
Doc Type: Bug Fix
Doc Text:
Clone Of: 1074083
Environment:
Last Closed: 2014-07-17 08:41:32 UTC
Embargoed:


Attachments (Terms of Use)

Description Stephen Herr 2014-05-19 13:36:24 UTC
+++ This bug was initially created as a clone of Bug #1074083 +++

Description of problem:

packages.search.name and similar APIs return only one match per package name.


Version-Release number of selected component (if applicable):

spacewalk-java-2.0.2-62.el6sat.noarch

How reproducible:

100%

Steps to Reproduce:
1.) Create an API script to list all packages matching a given name, e.g.,

----
#!/usr/bin/python

import sys
import os
import xmlrpclib


URL  = "http://localhost/rpc/api"
USER = "XXXX"
PASS = "XXXX"

server = xmlrpclib.Server(URL)
session = server.auth.login(USER, PASS)

pkgs = server.packages.search.name(session, 'redhat-release')
for pkg in pkgs:
   print pkg

server.auth.logout(session)
----

2.) With spacewalk-java-2.0.2-58.el6sat.noarch installed, run the script and see multiple matches, one for each package matching the string 'redhat-release':

# rpm -q spacewalk-java
spacewalk-java-2.0.2-58.el6sat.noarch
# /root/package-search-01048907.py |wc -l
75

3.) Upgrade to spacewalk-java-2.0.2-62.el6sat.noarch, and re-run the script. This time, only one package is returned for each unique package name that matches the string:

# rpm -q spacewalk-java
spacewalk-java-2.0.2-62.el6sat.noarch

# /root/package-search-01048907.py |wc -l
3

# /root/package-search-01048907.py
{'description': 'Red Hat Enterprise Linux release notes files.', 'summary': 'Red Hat Enterprise Linux release notes files', 'epoch': '', 'version': '5Server', 'provider': 'Red Hat Inc.', 'release': '46', 'arch': 'i386', 'id': 54699, 'name': 'redhat-release-notes'}
{'description': 'Red Hat Enterprise Linux release files', 'summary': 'Red Hat Enterprise Linux release file', 'epoch': '', 'version': '5Server', 'provider': 'Red Hat Inc.', 'release': '5.10.0.4', 'arch': 'i386', 'id': 65135, 'name': 'redhat-release'}
{'description': 'Red Hat Enterprise Linux Server release files', 'summary': 'Red Hat Enterprise Linux Server release file', 'epoch': '', 'version': '6Server', 'provider': 'Red Hat Inc.', 'release': '6.2.0.3.el6', 'arch': 'x86_64', 'id': 5952, 'name': 'redhat-release-server'}


Actual results:

packages.search APIs return only one package match per package name.

Expected results:

All matching packages should be returned.

Additional info:

The regression appears to have been introduced in https://bugzilla.redhat.com/show_bug.cgi?id=1035429 . Specifically:

./java/code/src/com/redhat/rhn/frontend/action/channel/PackageSearchHelper.java:

****
[...]
        Map<String, PackageOverview> nameToPackageMap =
                new HashMap<String, PackageOverview>();
[...]
        for (PackageOverview po : unsorted) {
            nameToPackageMap.put(po.getPackageName(), po);
        }
[...]
        // Iterate through in the order that the search server returned, add packages
        // to the return list in the order they appear in the search results.
        for (Object resultObject : results) {
            Map result = (Map) resultObject;
            String name = (String) result.get("name");
            if (!alreadyAddedNames.contains(name) &&
                    nameToPackageMap.keySet().contains(name)) {
                ordered.add(nameToPackageMap.get(name));
                alreadyAddedNames.add(name);
            }
        }
****

Because nameToPackageMap is a HashMap with a key equal to the package name, only one PackageOverview object will end up associated with that key. All others are ignored.

I've tested out a patch (attached), which maps package id to PackageOverview object instead. Also, I'm not sure why some of the package queries in Package_queries.xml were only returning max(p.id) instead of all package ids, so I've modified those to return all distinct matching package ids.

--- Additional comment from Stephen Herr on 2014-03-21 17:48:45 EDT ---

Hi Tasos,

It appears I was a bit too zealous in my performance improving. Thanks for the patch. I've partially accepted it.

The queries that you changed in Package_queries.xml were fine the way they were. The WebUI package search only needs one result per name returned. You'll notice the API always performs the searchById query, which does not group by name. To make the other queries return every id again would be to hobble the WebUI package search unnecessarily.

Your changes to PackageSearchHelper were right on the mark though.
Committing to Spacewalk master:
9f9b9753b5bf7e6fb3afcf13856c1a768bc0df3c
48c7a83a58bb245d36b29e88c90456755cdfc333

--- Additional comment from Stephen Herr on 2014-05-06 10:12:00 EDT ---

The API search is also only returning results that have providers. A package provider is not a required field for packages, so we should also be able to return packages that do not have providers.

Committing to Spacewalk master:
b757cbd09a0c6cca11665521e5469218ca3aaf0f

Comment 1 Milan Zázrivec 2014-07-17 08:41:32 UTC
Spacewalk 2.2 has been released:

    https://fedorahosted.org/spacewalk/wiki/ReleaseNotes22


Note You need to log in before you can comment on or make changes to this bug.