~njpatel/unity-lens-applications/fix-initial-results

« back to all changes in this revision

Viewing changes to src/unity-package-search.cc

  • Committer: Mikkel Kamstrup Erlandsen
  • Date: 2010-07-21 11:08:30 UTC
  • mto: This revision was merged to the branch mainline in revision 38.
  • Revision ID: kamstrup@hardback-20100721110830-syx4k1wl84awu98x
Initial (mostly working) stab at C/Vala bindings to a C++ module talking to Xapian and AptPkg. Specifically the VAPI still needs work - and nothing is integrated into the build infrastructure yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010 Canonical Ltd
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License version 3 as
 
6
 * published by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License
 
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 * Authored by Mikkel Kamstrup Erlandsen <mikkel.kamstrup@canonical.com>
 
17
 *
 
18
 */
 
19
 
 
20
/*
 
21
 * This file contains C bindings written in C++ to hook up with the
 
22
 * Xapian indexes generated by Ubuntu Software Center and apt-xapian.
 
23
 * It also hooks up to Apt's cache via libapt-pkg to check whether or not
 
24
 * packages are installed.
 
25
 *
 
26
 * In the future we may be able to drop the depency on libapt-pkg if the Xapian
 
27
 * indexes include some installation metadata.
 
28
 */
 
29
 
 
30
using namespace std;
 
31
 
 
32
#include <apt-pkg/pkgcachegen.h>
 
33
#include <apt-pkg/cachefile.h>
 
34
#include <apt-pkg/cacheiterators.h>
 
35
#include <apt-pkg/progress.h>
 
36
#include <apt-pkg/init.h>
 
37
 
 
38
#include <xapian.h>
 
39
#include <iostream>
 
40
 
 
41
#define SOFTWARE_CENTER_INDEX "/var/cache/software-center/xapian"
 
42
#define AXI_INDEX "/var/lib/apt-xapian-index/index"
 
43
#define QUERY_PARSER_FLAGS Xapian::QueryParser::FLAG_BOOLEAN|Xapian::QueryParser::FLAG_PHRASE|Xapian::QueryParser::FLAG_LOVEHATE|Xapian::QueryParser::FLAG_WILDCARD
 
44
 
 
45
// values used in the database
 
46
#define XAPIAN_VALUE_APPNAME 170
 
47
#define XAPIAN_VALUE_PKGNAME 171
 
48
#define XAPIAN_VALUE_ICON 172
 
49
#define XAPIAN_VALUE_GETTEXT_DOMAIN 173
 
50
#define XAPIAN_VALUE_ARCHIVE_SECTION 174
 
51
#define XAPIAN_VALUE_ARCHIVE_ARCH 175
 
52
#define XAPIAN_VALUE_POPCON 176
 
53
#define XAPIAN_VALUE_SUMMARY 177
 
54
#define XAPIAN_VALUE_ARCHIVE_CHANNEL 178
 
55
#define XAPIAN_VALUE_DESKTOP_FILE 179
 
56
 
 
57
#include "xsearch.h"
 
58
 
 
59
struct _UnityPackageSearcher
 
60
{
 
61
        pkgCache *cache;
 
62
        Xapian::Database *db;
 
63
        Xapian::Enquire *enquire;
 
64
        Xapian::QueryParser *query_parser;
 
65
};
 
66
 
 
67
UnityPackageSearcher*
 
68
unity_package_searcher_new ()
 
69
{
 
70
        UnityPackageSearcher *searcher;
 
71
        
 
72
        searcher = g_new0 (UnityPackageSearcher, 1);
 
73
        
 
74
        // Xapian initialization
 
75
    try {
 
76
                // Load the Xapian database
 
77
        Xapian::Database *sc_db = new Xapian::Database (SOFTWARE_CENTER_INDEX);
 
78
        Xapian::Database *axi_db = new Xapian::Database (AXI_INDEX);
 
79
        sc_db->add_database (*axi_db);
 
80
        searcher->db = sc_db;
 
81
        delete axi_db;
 
82
        
 
83
        // Start an enquire session
 
84
        Xapian::Enquire *enquire = new Xapian::Enquire (*sc_db);
 
85
        searcher->enquire = enquire;
 
86
        
 
87
        // Create query parser
 
88
        Xapian::QueryParser *query_parser = new Xapian::QueryParser ();
 
89
        query_parser->add_prefix ("section", "AE");
 
90
        query_parser->add_prefix ("type", "AT");
 
91
        query_parser->add_prefix ("category", "AC");
 
92
        query_parser->add_prefix ("name", "AA");
 
93
        query_parser->add_prefix ("pkgname", "AP");
 
94
        query_parser->set_default_op (Xapian::Query::OP_AND);
 
95
        query_parser->set_database (*sc_db);
 
96
        searcher->query_parser = query_parser;
 
97
        } catch(const Xapian::Error &error) {
 
98
        cerr << "Error loading package indexes: "  << error.get_msg() << endl;
 
99
        return NULL;
 
100
    }
 
101
    
 
102
    // AptPkg initialization
 
103
    // FIXME: We should avoid calling the pkgInit* functions more than once
 
104
    pkgInitConfig(*_config);
 
105
        pkgInitSystem(*_config, _system);
 
106
        
 
107
        pkgSourceList list;
 
108
        list.ReadMainList();
 
109
        OpTextProgress progress;
 
110
        MMap *map;
 
111
        bool res = pkgMakeStatusCache(list, progress, &map, true);
 
112
        progress.Done ();
 
113
        pkgCache *cache = new pkgCache (map);
 
114
        searcher->cache = cache;
 
115
        
 
116
        return searcher;
 
117
}
 
118
 
 
119
void
 
120
unity_package_searcher_free (UnityPackageSearcher *searcher)
 
121
{
 
122
        g_return_if_fail (searcher != NULL);
 
123
        
 
124
        delete searcher->db;
 
125
        delete searcher->enquire;
 
126
        delete searcher->query_parser;
 
127
        delete searcher->cache;
 
128
        g_free (searcher);
 
129
}
 
130
 
 
131
UnityPackageSearchResult*
 
132
unity_package_searcher_search (UnityPackageSearcher *searcher,
 
133
                               const gchar          *search_string)
 
134
{
 
135
        UnityPackageSearchResult* result;
 
136
        
 
137
        g_return_val_if_fail (searcher != NULL, NULL);
 
138
        g_return_val_if_fail (search_string != NULL, NULL);
 
139
        
 
140
        string _search_string (search_string);
 
141
        Xapian::Query query = searcher->query_parser->parse_query (_search_string, QUERY_PARSER_FLAGS);
 
142
    cout << "Performing query `" << query.get_description() << "'" << endl;
 
143
        
 
144
        // Perform search
 
145
    searcher->enquire->set_query(query);
 
146
    Xapian::MSet matches =
 
147
        searcher->enquire->get_mset(0, searcher->db->get_doccount ());  
 
148
 
 
149
    // Retrieve the results, note that we build the result->results
 
150
    // list in reverse order and then reverse it before we return it
 
151
    result = g_slice_new0 (UnityPackageSearchResult);
 
152
    result->num_hits = matches.get_matches_estimated ();
 
153
    for (Xapian::MSetIterator i = matches.begin();
 
154
         i != matches.end();
 
155
         ++i)
 
156
        {
 
157
                UnityPackageInfo *pkginfo = g_slice_new0 (UnityPackageInfo);
 
158
        Xapian::Document doc = i.get_document();
 
159
            
 
160
        string pkgname = doc.get_value (XAPIAN_VALUE_PKGNAME);
 
161
        pkginfo->package_name = g_strdup (pkgname.c_str ());
 
162
        if (pkgname != "")
 
163
                        {
 
164
                                pkgCache::PkgIterator pkg = searcher->cache->FindPkg(pkgname);
 
165
                                
 
166
                                if (!pkg.end() && pkg->CurrentState == pkgCache::State::Installed)
 
167
                                        pkginfo->installed = TRUE;
 
168
                                else
 
169
                                        pkginfo->installed = FALSE;
 
170
                        }
 
171
                else
 
172
                        pkginfo->installed = FALSE;
 
173
                
 
174
                string appname = doc.get_value (XAPIAN_VALUE_APPNAME);
 
175
        pkginfo->application_name = g_strdup (appname.c_str ());
 
176
                
 
177
                string desktop_file = doc.get_value (XAPIAN_VALUE_DESKTOP_FILE);
 
178
        pkginfo->desktop_file = g_strdup (desktop_file.c_str ());
 
179
                                
 
180
                result->results = g_slist_prepend (result->results, pkginfo);
 
181
    }
 
182
        
 
183
        result->results = g_slist_reverse (result->results);
 
184
        return result;
 
185
}
 
186
 
 
187
// extern "C"
 
188
static void _free_package_info (gpointer pkg, gpointer data)
 
189
{
 
190
  UnityPackageInfo pkginfo = (UnityPackageInfo*) pkg;
 
191
  
 
192
  g_free (pkginfo->package_name);
 
193
  g_free (pkginfo->application_name);
 
194
  g_free (pkginfo->desktop_file);
 
195
  
 
196
        g_slice_free (UnityPackageInfo, pkg);
 
197
}
 
198
 
 
199
void
 
200
unity_package_search_result_free (UnityPackageSearchResult *result)
 
201
{
 
202
        g_return_if_fail (result != NULL);
 
203
        
 
204
        g_slist_foreach (result->results, _free_package_info, NULL);
 
205
        g_slist_free (result->results);
 
206
        g_slice_free (UnityPackageSearchResult, result);
 
207
}
 
208