2
* Copyright (C) 2011 Canonical Ltd
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.
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.
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/>.
16
* Authored by Mikkel Kamstrup Erlandsen <mikkel.kamstrup@canonical.com>
20
#include "unity-ratings-db.h"
24
/* Hacky check, but we *really* need to have the same libdb version as the
25
* software-center is using to avoid a cascade of fail */
26
#if DB_VERSION_MAJOR != 4 || DB_VERSION_MINOR != 8
27
#error "unity-lens-applications only compiles and works against libdb-4.8. Please install the package libdb4.8-dev"
30
struct _UnityRatingsDatabase {
35
/* IMPLEMENTATION NOTE: It is paramount that we create our BDB environment
36
* in "concurrent" mode. This makes the database
37
* single-writer-multiple-reader safe. Hence allowing
38
* us to read the DB while S-C is updating it.
42
#define UNITY_RATINGS_DB_PATH "software-center/reviews.ubuntu.com_reviews_api_1.0_review-stats-pkgnames.p__4.8.db"
43
#define UNITY_RATINGS_DB_ENV_PATH UNITY_RATINGS_DB_PATH".dbenv"
46
unity_ratings_database_new (GError **error)
48
UnityRatingsDatabase *self;
54
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
56
/* Create a database environment in concurrent mode,
57
* enabling single-writer-multiple-reader support */
58
path = g_build_filename (g_get_user_cache_dir (),
59
UNITY_RATINGS_DB_ENV_PATH,
61
db_env_create (&env, 0);
62
error_code = env->open (env,
63
path, /* db env home dir */
64
DB_INIT_CDB | DB_INIT_MPOOL, /* use concurrent mode */
65
0600 /* access mode (user-rw only) */);
69
g_set_error (error, G_FILE_ERROR, error_code,
70
"Unable to open ratings database environment '%s': %s",
71
path, db_strerror (error_code)); // FIXME: Leak db_strerror() return?
79
/* Create a db handle in our environment */
80
path = g_build_filename (g_get_user_cache_dir (),
81
UNITY_RATINGS_DB_PATH,
83
db_create (&db, env, 0);
84
error_code = db->open (db,
85
NULL, /* transaction context */
88
DB_HASH, /* db type */
89
DB_RDONLY, /* flags - read-only */
90
0600 /* access mode (user-rw only) */);
94
g_set_error (error, G_FILE_ERROR, error_code,
95
"Unable to open ratings database '%s': %s",
96
path, db_strerror (error_code)); // FIXME: Leak db_strerror() return?
105
self = g_new0 (UnityRatingsDatabase, 1);
113
unity_ratings_database_free (UnityRatingsDatabase *self)
115
g_return_if_fail (self != NULL);
117
self->db->close (self->db, 0);
118
self->env->close (self->env, 0);
124
unity_ratings_database_query (UnityRatingsDatabase *self,
125
const gchar *pkgname,
126
UnityRatingsResult *out_result)
128
DBT key = { 0 }, data = { 0 };
132
g_return_val_if_fail (self != NULL, FALSE);
133
g_return_val_if_fail (pkgname != NULL, FALSE);
134
g_return_val_if_fail (out_result != NULL, FALSE);
136
/* Make sure the DBTs are zeroed. Otherwise libdb throws a fit */
137
key.data = (gchar*)pkgname;
138
key.size = strlen (pkgname);
142
key.flags = DB_DBT_USERMEM;
143
data.data = out_result;
145
data.ulen = sizeof (UnityRatingsResult);
148
data.flags= DB_DBT_USERMEM;
150
error_code = self->db->get (self->db,
156
/* error_code == 0 means success, everything else is bad */
157
if (error_code == DB_NOTFOUND)
163
g_warning ("Error looking up ratings for '%s': %s",
164
pkgname, db_strerror (error_code)); // FIXME : leak strerror?
168
if (data.size != 3*sizeof (gint32))
170
g_critical ("Unexpected datum size from ratings database %i bytes. "
171
"Expected %i bytes", data.size, 3*sizeof (gint32));
178
out_result->average_rating = 0;
179
out_result->total_rating = 0;
180
out_result->dampened_rating = 0;