• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

src/xmms/collserial.c

Go to the documentation of this file.
00001 /*  XMMS2 - X Music Multiplexer System
00002  *  Copyright (C) 2003-2009 XMMS2 Team
00003  *
00004  *  PLUGINS ARE NOT CONSIDERED TO BE DERIVED WORK !!!
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Lesser General Public
00008  *  License as published by the Free Software Foundation; either
00009  *  version 2.1 of the License, or (at your option) any later version.
00010  *
00011  *  This library is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *  Lesser General Public License for more details.
00015  */
00016 
00017 
00018 /** @file
00019  *  Functions to serialize (save/restore) collections.
00020  */
00021 
00022 #include "xmmspriv/xmms_collserial.h"
00023 #include "xmmspriv/xmms_collection.h"
00024 #include "xmmspriv/xmms_medialib.h"
00025 
00026 
00027 /* Internal helper structures */
00028 
00029 typedef struct {
00030     xmms_medialib_session_t *session;
00031     guint collid;
00032     xmms_collection_namespace_id_t nsid;
00033 } coll_dbwrite_t;
00034 
00035 
00036 static xmmsv_coll_t *xmms_collection_dbread_operator (xmms_medialib_session_t *session, gint id, xmmsv_coll_type_t type);
00037 static guint xmms_collection_dbwrite_operator (xmms_medialib_session_t *session, guint collid, xmmsv_coll_t *coll);
00038 
00039 static void dbwrite_operator (void *key, void *value, void *udata);
00040 static void dbwrite_coll_attributes (const char *key, const char *value, void *udata);
00041 static void dbwrite_strip_tmpprops (void *key, void *value, void *udata);
00042 
00043 static gint value_get_dict_int (xmmsv_t *val, const gchar *key);
00044 static const gchar *value_get_dict_string (xmmsv_t *val, const gchar *key);
00045 
00046 
00047 
00048 /** Save the collection DAG in the database.
00049  *
00050  * @param dag  The collection DAG to save.
00051  */
00052 void
00053 xmms_collection_dag_save (xmms_coll_dag_t *dag)
00054 {
00055     gint i;
00056     xmms_medialib_session_t *session;
00057 
00058     session = xmms_medialib_begin_write ();
00059 
00060     /* Empty Collection* tables */
00061     xmms_medialib_select (session, "DELETE FROM CollectionAttributes", NULL);
00062     xmms_medialib_select (session, "DELETE FROM CollectionConnections", NULL);
00063     xmms_medialib_select (session, "DELETE FROM CollectionIdlists", NULL);
00064     xmms_medialib_select (session, "DELETE FROM CollectionLabels", NULL);
00065     xmms_medialib_select (session, "DELETE FROM CollectionOperators", NULL);
00066 
00067     /* Write all collections in all namespaces */
00068     coll_dbwrite_t dbinfos = { session, 1, 0 }; /* ids start at 1 */
00069     for (i = 0; i < XMMS_COLLECTION_NUM_NAMESPACES; ++i) {
00070         dbinfos.nsid = i;
00071         xmms_collection_foreach_in_namespace (dag, i, dbwrite_operator, &dbinfos);
00072     }
00073 
00074     xmms_collection_foreach_in_namespace (dag, XMMS_COLLECTION_NSID_ALL,
00075                                           dbwrite_strip_tmpprops, NULL);
00076 
00077     xmms_medialib_end (session);
00078 }
00079 
00080 /** Restore the collection DAG from the database.
00081  *
00082  * @param dag  The collection DAG to restore to.
00083  */
00084 void
00085 xmms_collection_dag_restore (xmms_coll_dag_t *dag)
00086 {
00087     xmmsv_coll_t *coll = NULL;
00088     xmms_medialib_session_t *session;
00089     xmmsv_t *cmdval;
00090     const gchar *query;
00091     GList *res;
00092     gint previd;
00093 
00094     session = xmms_medialib_begin ();
00095 
00096     /* Fetch all label-coll_operator for all namespaces, register in table */
00097     query = "SELECT op.id AS id, lbl.name AS label, "
00098             "       lbl.namespace AS nsid, op.type AS type "
00099             "FROM CollectionOperators AS op, CollectionLabels as lbl "
00100             "WHERE op.id=lbl.collid "
00101             "ORDER BY id";
00102     res = xmms_medialib_select (session, query, NULL);
00103 
00104     previd = -1;
00105 
00106     while (res) {
00107         gint id, type, nsid;
00108         const gchar *label;
00109 
00110         cmdval = (xmmsv_t*) res->data;
00111         id = value_get_dict_int (cmdval, "id");
00112         type = value_get_dict_int (cmdval, "type");
00113         nsid = value_get_dict_int (cmdval, "nsid");
00114         label = value_get_dict_string (cmdval, "label");
00115 
00116         /* Do not duplicate operator if same id */
00117         if (previd < 0 || id != previd) {
00118             coll = xmms_collection_dbread_operator (session, id, type);
00119             previd = id;
00120         }
00121         else {
00122             xmmsv_coll_ref (coll);  /* New label references the coll */
00123         }
00124 
00125         xmms_collection_dag_replace (dag, nsid, g_strdup (label), coll);
00126 
00127         xmmsv_unref (cmdval);
00128         res = g_list_delete_link (res, res);
00129     }
00130 
00131     xmms_medialib_end (session);
00132 
00133     /* FIXME: validate ? */
00134 
00135     /* Link references in collections to actual operators */
00136     xmms_collection_apply_to_all_collections (dag, bind_all_references, NULL);
00137 }
00138 
00139 /** Given a collection id, query the DB to build the corresponding
00140  *  collection DAG.
00141  *
00142  * @param session  The medialib session connected to the DB.
00143  * @param id  The id of the collection to create.
00144  * @param type  The type of the collection operator.
00145  * @return  The created collection DAG.
00146  */
00147 static xmmsv_coll_t *
00148 xmms_collection_dbread_operator (xmms_medialib_session_t *session,
00149                                  gint id, xmmsv_coll_type_t type)
00150 {
00151     xmmsv_coll_t *coll;
00152     xmmsv_coll_t *op;
00153     GList *res;
00154     GList *n;
00155     xmmsv_t *cmdval;
00156     gchar query[256];
00157 
00158     coll = xmmsv_coll_new (type);
00159 
00160     /* Retrieve the attributes */
00161     g_snprintf (query, sizeof (query),
00162                 "SELECT attr.key AS key, attr.value AS value "
00163                 "FROM CollectionOperators AS op, CollectionAttributes AS attr "
00164                 "WHERE op.id=%d AND attr.collid=op.id", id);
00165 
00166     res = xmms_medialib_select (session, query, NULL);
00167     for (n = res; n; n = n->next) {
00168         const gchar *key, *value;
00169 
00170         cmdval = (xmmsv_t*) n->data;
00171         key = value_get_dict_string (cmdval, "key");
00172         value = value_get_dict_string (cmdval, "value");
00173         xmmsv_coll_attribute_set (coll, key, value);
00174 
00175         xmmsv_unref (n->data);
00176     }
00177     g_list_free (res);
00178 
00179     /* Retrieve the idlist */
00180     g_snprintf (query, sizeof (query),
00181                 "SELECT idl.mid AS mid "
00182                 "FROM CollectionOperators AS op, CollectionIdlists AS idl "
00183                 "WHERE op.id=%d AND idl.collid=op.id "
00184                 "ORDER BY idl.position", id);
00185 
00186     res = xmms_medialib_select (session, query, NULL);
00187     for (n = res; n; n = n->next) {
00188 
00189         cmdval = (xmmsv_t *) n->data;
00190         xmmsv_coll_idlist_append (coll, value_get_dict_int (cmdval, "mid"));
00191 
00192         xmmsv_unref (cmdval);
00193     }
00194     g_list_free (res);
00195 
00196     /* Retrieve the operands */
00197     g_snprintf (query, sizeof (query),
00198                 "SELECT op.id AS id, op.type AS type "
00199                 "FROM CollectionOperators AS op, CollectionConnections AS conn "
00200                 "WHERE conn.to_id=%d AND conn.from_id=op.id", id);
00201 
00202     res = xmms_medialib_select (session, query, NULL);
00203     for (n = res; n; n = n->next) {
00204         gint id;
00205         gint type;
00206 
00207         cmdval = (xmmsv_t *) n->data;
00208         id = value_get_dict_int (cmdval, "id");
00209         type = value_get_dict_int (cmdval, "type");
00210 
00211         op = xmms_collection_dbread_operator (session, id, type);
00212         xmmsv_coll_add_operand (coll, op);
00213 
00214         xmmsv_coll_unref (op);
00215         xmmsv_unref (cmdval);
00216     }
00217     g_list_free (res);
00218 
00219     return coll;
00220 }
00221 
00222 /** Write the given operator to the database under the given id.
00223  *
00224  * @param session  The medialib session connected to the DB.
00225  * @param collid  The id under which to save the collection.
00226  * @param coll  The structure of the collection to save.
00227  * @return  The next free collection id.
00228  */
00229 static guint
00230 xmms_collection_dbwrite_operator (xmms_medialib_session_t *session,
00231                                   guint collid, xmmsv_coll_t *coll)
00232 {
00233     gchar query[128];
00234     guint *idlist;
00235     gint i;
00236     xmmsv_coll_t *op;
00237     gint newid, nextid;
00238     coll_dbwrite_t dbwrite_infos = { session, collid, 0 };
00239 
00240     /* Write operator */
00241     g_snprintf (query, sizeof (query),
00242                 "INSERT INTO CollectionOperators VALUES(%d, %d)",
00243                 collid, xmmsv_coll_get_type (coll));
00244 
00245     xmms_medialib_select (session, query, NULL);
00246 
00247     /* Write attributes */
00248     xmmsv_coll_attribute_foreach (coll, dbwrite_coll_attributes, &dbwrite_infos);
00249 
00250     /* Write idlist */
00251     idlist = xmmsv_coll_get_idlist (coll);
00252     for (i = 0; idlist[i] != 0; i++) {
00253         g_snprintf (query, sizeof (query),
00254                     "INSERT INTO CollectionIdlists VALUES(%d, %d, %d)",
00255                     collid, i, idlist[i]);
00256 
00257         xmms_medialib_select (session, query, NULL);
00258     }
00259 
00260     /* Save operands and connections (don't recurse in ref operand) */
00261     newid = collid + 1;
00262     if (xmmsv_coll_get_type (coll) != XMMS_COLLECTION_TYPE_REFERENCE) {
00263         xmmsv_coll_operand_list_save (coll);
00264         xmmsv_coll_operand_list_first (coll);
00265         while (xmmsv_coll_operand_list_entry (coll, &op)) {
00266             nextid = xmms_collection_dbwrite_operator (session, newid, op);
00267             g_snprintf (query, sizeof (query),
00268                         "INSERT INTO CollectionConnections VALUES(%d, %d)",
00269                         newid, collid);
00270             xmms_medialib_select (session, query, NULL);
00271             newid = nextid;
00272             xmmsv_coll_operand_list_next (coll);
00273         }
00274         xmmsv_coll_operand_list_restore (coll);
00275     }
00276 
00277     /* return next available id */
00278     return newid;
00279 }
00280 
00281 /* For all label-operator pairs, write the operator and all its
00282  * operands to the DB recursively. */
00283 static void
00284 dbwrite_operator (void *key, void *value, void *udata)
00285 {
00286     gchar *query;
00287     gchar *label = key;
00288     xmmsv_coll_t *coll = value;
00289     coll_dbwrite_t *dbinfos = udata;
00290     gchar *esc_label;
00291     gint serial_id;
00292 
00293     /* Only serialize each operator once, get previous id if exists */
00294     if (!xmms_collection_get_int_attr (coll, XMMS_COLLSERIAL_ATTR_ID, &serial_id)) {
00295         serial_id = dbinfos->collid;
00296         dbinfos->collid = xmms_collection_dbwrite_operator (dbinfos->session,
00297                                                             dbinfos->collid, coll);
00298         xmms_collection_set_int_attr (coll, XMMS_COLLSERIAL_ATTR_ID, serial_id);
00299     }
00300 
00301     esc_label = sqlite_prepare_string (label);
00302     query = g_strdup_printf ("INSERT INTO CollectionLabels VALUES(%d, %d, %s)",
00303                              serial_id, dbinfos->nsid, esc_label);
00304     xmms_medialib_select (dbinfos->session, query, NULL);
00305 
00306     g_free (query);
00307     g_free (esc_label);
00308 }
00309 
00310 /* Write all attributes of a collection to the DB. */
00311 static void
00312 dbwrite_coll_attributes (const char *key, const char *value, void *udata)
00313 {
00314     gchar *query;
00315     coll_dbwrite_t *dbwrite_infos = udata;
00316     gchar *esc_key;
00317     gchar *esc_val;
00318 
00319     esc_key = sqlite_prepare_string (key);
00320     esc_val = sqlite_prepare_string (value);
00321     query = g_strdup_printf ("INSERT INTO CollectionAttributes VALUES(%d, %s, %s)",
00322                              dbwrite_infos->collid, esc_key, esc_val);
00323     xmms_medialib_select (dbwrite_infos->session, query, NULL);
00324 
00325     g_free (query);
00326     g_free (esc_key);
00327     g_free (esc_val);
00328 }
00329 
00330 /* Remove all temp utility properties used to write collections to the DB. */
00331 static void
00332 dbwrite_strip_tmpprops (void *key, void *value, void *udata)
00333 {
00334     xmmsv_coll_t *coll = value;
00335     xmmsv_coll_attribute_remove (coll, XMMS_COLLSERIAL_ATTR_ID);
00336 }
00337 
00338 
00339 /* Extract the int value out of a xmmsv_t object. */
00340 static gint
00341 value_get_dict_int (xmmsv_t *val, const gchar *key)
00342 {
00343     gint i;
00344     xmmsv_dict_entry_get_int (val, key, &i);
00345     return i;
00346 }
00347 
00348 /* Extract the string value out of a xmmsv_t object. */
00349 static const gchar *
00350 value_get_dict_string (xmmsv_t *val, const gchar *key)
00351 {
00352     const gchar *s;
00353     xmmsv_dict_entry_get_string (val, key, &s);
00354     return s;
00355 }

Generated on Wed Feb 9 2011 for XMMS2 by  doxygen 1.7.1