summaryrefslogtreecommitdiffstats
path: root/trunk/bitbake-data/src/backend-sqlite3.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/bitbake-data/src/backend-sqlite3.c')
-rw-r--r--trunk/bitbake-data/src/backend-sqlite3.c372
1 files changed, 372 insertions, 0 deletions
diff --git a/trunk/bitbake-data/src/backend-sqlite3.c b/trunk/bitbake-data/src/backend-sqlite3.c
new file mode 100644
index 000000000..80d2d9e44
--- /dev/null
+++ b/trunk/bitbake-data/src/backend-sqlite3.c
@@ -0,0 +1,372 @@
+/* vi:ts=8:sw=4:sts=4:et
+ *
+ * Copyright (C) 2004, 2005 Chris Larson <kergoth@handhelds.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h> /* for printf */
+#include <stdlib.h> /* for strtol */
+#include <glib.h>
+#include <sqlite3.h>
+#include <bitbake-data.h>
+#include <bitbake-data/private.h>
+
+#include "config.h"
+
+/**
+ * Static structure to hold process wide information associated with
+ * our bitbake data. In this case, this holds our pointer to our open
+ * sqlite3 database, its path, and so on. Protected by a GStaticMutex.
+ */
+static struct {
+ int initialized;
+ GStaticMutex mutex;
+ unsigned char *datapath;
+ sqlite3 *db;
+ guint users;
+} bbdata_setup = {
+ .initialized = FALSE,
+ .mutex = G_STATIC_MUTEX_INIT,
+};
+
+
+static inline int add_tables()
+{
+ char **results;
+ int nrow, ncol;
+ int sret;
+
+ sqlite3_get_table(bbdata_setup.db, "select name from sqlite_master where type = 'table' and name = 'recipes'",
+ &results, &nrow, &ncol, NULL);
+ sqlite3_free_table(results);
+ if (nrow < 1) {
+ sret = sqlite3_exec(bbdata_setup.db, "create table recipes(key integer primary key, recipe text not null)",
+ NULL, 0, NULL);
+ if (sret != SQLITE_OK)
+ return FALSE;
+ }
+
+ sqlite3_get_table(bbdata_setup.db, "select name from sqlite_master where type = 'table' and name = 'scopes'",
+ &results, &nrow, &ncol, NULL);
+ sqlite3_free_table(results);
+ if (nrow < 1) {
+ sret = sqlite3_exec(bbdata_setup.db,
+ "create table scopes(key integer primary key, priority integer, scope integer, recipe integer)",
+ NULL, 0, NULL);
+ if (sret != SQLITE_OK)
+ return FALSE;
+ }
+
+ sqlite3_get_table(bbdata_setup.db, "select name from sqlite_master where type = 'table' and name = 'vars'",
+ &results, &nrow, &ncol, NULL);
+ sqlite3_free_table(results);
+ if (nrow < 1) {
+ sret = sqlite3_exec(bbdata_setup.db,
+ "create table vars(key integer primary key, var text not null, val text, recipe integer)",
+ NULL, 0, NULL);
+ if (sret != SQLITE_OK)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/**
+ * Process wide initialization
+ */
+static int __bb_data_init(void)
+{
+ int ret = TRUE;
+ const gchar *datapath = g_getenv("BBDATAPATH");
+ unsigned char *fpath = NULL;
+ guint sret;
+
+ if (datapath)
+ bbdata_setup.datapath = g_filename_to_utf8(datapath, -1, NULL, NULL, NULL);
+
+ if (!bbdata_setup.datapath)
+ bbdata_setup.datapath = g_build_path(LOCALSTATEDIR, "lib", "bitbake-data", NULL);
+
+ fpath = g_build_filename(bbdata_setup.datapath, "data");
+
+ sret = sqlite3_open(fpath, &bbdata_setup.db);
+ if (sret)
+ goto out_fail;
+
+ ret = add_tables();
+ if (!ret)
+ goto out_fail;
+
+ g_free(fpath);
+
+ bbdata_setup.initialized = TRUE;
+ return ret;
+
+out_fail:
+ sqlite3_close(bbdata_setup.db);
+ g_free(bbdata_setup.datapath);
+ g_free(fpath);
+ return FALSE;
+}
+
+/**
+ * Process wide shutdown
+ */
+static void __bb_data_shutdown(void)
+{
+ bbdata_setup.initialized = FALSE;
+ sqlite3_close(bbdata_setup.db);
+ g_free(bbdata_setup.datapath);
+}
+
+/**
+ * Wrapper that initializes when necessary
+ */
+static inline int bb_data_init(void)
+{
+ if (!bbdata_setup.initialized)
+ return __bb_data_init();
+ else
+ return TRUE;
+}
+
+/**
+ * Wrapper that shuts down when necessary
+ */
+static inline void bb_data_shutdown(void)
+{
+ if (bbdata_setup.initialized) {
+ bbdata_setup.users -= 1;
+
+ if (bbdata_setup.users < 1)
+ __bb_data_shutdown();
+ }
+}
+
+
+static inline int add_recipe_to_db(const char *recipe)
+{
+ char **results;
+ char *query;
+ int nrow, ncol;
+
+ query = sqlite3_mprintf("select key from recipes where recipe = '%q'", recipe);
+ sqlite3_get_table(bbdata_setup.db, query, &results, &nrow, &ncol, NULL);
+ sqlite3_free_table(results);
+ sqlite3_free(query);
+ if (nrow < 1) {
+ int sret;
+ char *insert = sqlite3_mprintf("insert into recipes values(NULL, '%q')", recipe);
+ sret = sqlite3_exec(bbdata_setup.db, insert, NULL, 0, NULL);
+ sqlite3_free(insert);
+ if (sret != SQLITE_OK)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void *bb_data_new(const unsigned char *recipe)
+{
+ void *ret = NULL;
+ struct bb_data *data;
+ int sret;
+
+ g_static_mutex_lock(&bbdata_setup.mutex);
+ if (!bb_data_init()) {
+ g_static_mutex_unlock(&bbdata_setup.mutex);
+ return ret;
+ }
+
+ bbdata_setup.users += 1;
+ g_static_mutex_unlock(&bbdata_setup.mutex);
+
+ ret = g_malloc0(sizeof(struct bb_data));
+ data = (struct bb_data *)ret;
+ data->recipe = g_strdup(recipe);
+
+ sret = sqlite3_exec(bbdata_setup.db, "begin", NULL, 0, NULL);
+ if (sret != SQLITE_OK)
+ goto sqliteerror;
+
+ if (!add_recipe_to_db(recipe))
+ goto sqliteerror;
+
+ sret = sqlite3_exec(bbdata_setup.db, "commit", NULL, 0, NULL);
+ if (sret != SQLITE_OK)
+ goto sqliteerror;
+ return ret;
+sqliteerror:
+ sqlite3_exec(bbdata_setup.db, "rollback", NULL, 0, NULL);
+ g_static_mutex_lock(&bbdata_setup.mutex);
+ bbdata_setup.users -= 1;
+ bb_data_shutdown();
+ g_static_mutex_unlock(&bbdata_setup.mutex);
+ g_free(ret);
+ return NULL;
+}
+
+void bb_data_destroy(void *data, int flush)
+{
+ struct bb_data *d = (struct bb_data *)data;
+ if (flush) {
+ char *str;
+#if 0
+ str = sqlite3_mprintf("drop table '%q'", d->recipe);
+ sqlite3_exec(bbdata_setup.db, str, NULL, 0, NULL);
+ sqlite3_free(str);
+#endif
+ str = sqlite3_mprintf("delete from recipes where recipe = '%q'", d->recipe);
+ sqlite3_exec(bbdata_setup.db, str, NULL, 0, NULL);
+ sqlite3_free(str);
+ }
+
+ g_free(data);
+
+ g_static_mutex_lock(&bbdata_setup.mutex);
+
+ if (bbdata_setup.initialized) {
+ bbdata_setup.users -= 1;
+
+ if (bbdata_setup.users < 1) {
+ bb_data_shutdown();
+ }
+ }
+
+ g_static_mutex_unlock(&bbdata_setup.mutex);
+}
+
+unsigned char *bb_data_lookup(const void *data, const unsigned char *var)
+{
+ struct bb_data *d = (struct bb_data *)data;
+ char **results;
+ char *query;
+ int nrow, ncol;
+ unsigned char *ret = NULL;
+
+ query = sqlite3_mprintf("select val from vars join scopes on vars.recipe = scopes.scope join recipes on recipes.key = scopes.recipe where var = '%q' and recipes.recipe = '%q' order by scopes.priority desc limit 1", var, d->recipe);
+ sqlite3_get_table(bbdata_setup.db, query, &results, &nrow, &ncol, NULL);
+ sqlite3_free(query);
+ printf("nrow is %d\n", nrow);
+ if (nrow > 0)
+ if (results && results[1])
+ ret = g_strdup(results[1]);
+ sqlite3_free_table(results);
+ return ret;
+}
+
+long __get_recipe_num(void *data)
+{
+ struct bb_data *d = (struct bb_data *)data;
+ char *query;
+ char **results;
+ int nrow, ncol;
+ long recipenum = 0;
+
+ query = sqlite3_mprintf("select key from recipes where recipe = '%q'", d->recipe);
+ sqlite3_get_table(bbdata_setup.db, query, &results, &nrow, &ncol, NULL);
+ sqlite3_free(query);
+ printf("nrow is %d", nrow);
+ if (nrow > 0)
+ if (results && results[1]) {
+ recipenum = strtol(results[1], NULL, 10);
+ printf("recipenum is %ld\n", recipenum);
+ }
+ sqlite3_free_table(results);
+ return recipenum;
+}
+
+int bb_data_insert(void *data, const unsigned char *var, const unsigned char *val)
+{
+ char *query;
+ int sret;
+ long recipenum = __get_recipe_num(data);
+
+ query = sqlite3_mprintf("insert into vars values(NULL, '%q', '%q', %d)", var, val, recipenum);
+ sret = sqlite3_exec(bbdata_setup.db, query, NULL, 0, NULL);
+ sqlite3_free(query);
+ if (sret != SQLITE_OK)
+ return FALSE;
+ return TRUE;
+}
+
+int bb_data_remove(void *data, const unsigned char *var)
+{
+ struct bb_data *d = (struct bb_data *)data;
+ char *query;
+ int sret;
+ long recipenum = __get_recipe_num(data);
+
+ query = sqlite3_mprintf("delete from vars where var = '%q' and recipe = %d", d->recipe, var, recipenum);
+ sret = sqlite3_exec(bbdata_setup.db, query, NULL, 0, NULL);
+ sqlite3_free(query);
+ if (sret != SQLITE_OK)
+ return FALSE;
+ return TRUE;
+}
+
+unsigned char *bb_data_lookup_attr(const void *data, const unsigned char *var, const unsigned char *attr)
+{
+ struct bb_data *d = (struct bb_data *)data;
+ char **results;
+ char *query;
+ int nrow, ncol;
+ unsigned char *ret = NULL;
+
+ query = sqlite3_mprintf("select attr from '%q' where var = '%q' and attr not null and val = '%q'", d->recipe, var, attr);
+ sqlite3_get_table(bbdata_setup.db, query, &results, &nrow, &ncol, NULL);
+ sqlite3_free(query);
+ if (nrow > 0)
+ if (results && results[1])
+ ret = g_strdup(results[1]);
+ sqlite3_free_table(results);
+ return ret;
+}
+
+int bb_data_insert_attr(void *data, const unsigned char *var, const unsigned char *attr, const unsigned char *val)
+{
+ struct bb_data *d = (struct bb_data *)data;
+ char *query;
+ int sret;
+
+ query = sqlite3_mprintf("delete from '%q' where var = '%q' and attr not null and val = '%q'", d->recipe, var, attr);
+ sret = sqlite3_exec(bbdata_setup.db, query, NULL, 0, NULL);
+ sqlite3_free(query);
+
+ query = sqlite3_mprintf("insert into '%q' values(NULL, '%q', '%q', '%q')", d->recipe, var, attr, val);
+ sret = sqlite3_exec(bbdata_setup.db, query, NULL, 0, NULL);
+ sqlite3_free(query);
+ if (sret != SQLITE_OK)
+ return FALSE;
+ return TRUE;
+}
+
+int bb_data_remove_attr(void *data, const unsigned char *var, const unsigned char *attr)
+{
+ struct bb_data *d = (struct bb_data *)data;
+ char *query;
+ int sret;
+
+ query = sqlite3_mprintf("delete from '%q' where var = '%q' and val = '%q' and attr not null", d->recipe, var, attr);
+ sret = sqlite3_exec(bbdata_setup.db, query, NULL, 0, NULL);
+ sqlite3_free(query);
+ if (sret != SQLITE_OK)
+ return FALSE;
+ return TRUE;
+}