New approach for loading of metadata 3/3
authorTomas Mlcoch <xtojaj@gmail.com>
Wed, 5 Mar 2014 22:03:11 +0000 (23:03 +0100)
committerTomas Mlcoch <xtojaj@gmail.com>
Wed, 5 Mar 2014 22:03:11 +0000 (23:03 +0100)
New bitfield in cr_Package loadingflags, that contains information
about what was loaded to the package (primary, filelists, other) and
where is the package from (parsed from rpm header, from xml, etc..)

Thanks to this field, the XML metadata parser can recognize that
a XML chunk with files (filelists.xml) or changelos (other.xml)
was already parsed for the package and skip duplicit chunks.

src/load_metadata.c
src/package.h
src/parsehdr.c

index 03f9f6c..e37f9ec 100644 (file)
@@ -139,6 +139,12 @@ cr_metadata_set_dupaction(cr_Metadata *md, cr_HashTableKeyDupAction dupaction)
 
 // Callbacks for XML parsers
 
+typedef enum {
+    PARSING_PRI,
+    PARSING_FIL,
+    PARSING_OTH,
+} cr_ParsingState;
+
 typedef struct {
     GHashTable      *ht;
     GStringChunk    *chunk;
@@ -151,6 +157,7 @@ typedef struct {
         primary.xml with metadata from filelists.xml and other.xml and
         we want the pkgId to be unique.
         Key is pkgId and value is NULL. */
+    cr_ParsingState state;
 } cr_CbData;
 
 static int
@@ -221,6 +228,8 @@ primary_pkgcb(cr_Package *pkg, void *cbdata, GError **err)
 
     if (!epkg) {
         // Store package into the hashtable
+        pkg->loadingflags |= CR_PACKAGE_FROM_XML;
+        pkg->loadingflags |= CR_PACKAGE_LOADED_PRI;
         g_hash_table_replace(cb_data->ht, pkg->pkgId, pkg);
     } else {
         // Package with the same pkgId (hash) already exists
@@ -270,9 +279,35 @@ newpkgcb(cr_Package **pkg,
 
     *pkg = g_hash_table_lookup(cb_data->ht, pkgId);
 
-    if (*pkg && cb_data->chunk) {
-        assert(!(*pkg)->chunk);
-        (*pkg)->chunk = cb_data->chunk;
+    if (*pkg) {
+        // If package with the pkgId was parsed from primary.xml, then...
+
+        if (cb_data->state == PARSING_FIL) {
+            if ((*pkg)->loadingflags & CR_PACKAGE_LOADED_FIL) {
+                // For package with this checksum, the filelist was
+                // already loaded.
+                *pkg = NULL;
+            } else {
+                // Make a note that filelist is parsed
+                (*pkg)->loadingflags |= CR_PACKAGE_LOADED_FIL;
+            }
+        }
+
+        if (cb_data->state == PARSING_OTH) {
+            if ((*pkg)->loadingflags & CR_PACKAGE_LOADED_OTH) {
+                // For package with this checksum, the other (changelogs) were
+                // already loaded.
+                *pkg = NULL;
+            } else {
+                // Make a note that other is parsed
+                (*pkg)->loadingflags |= CR_PACKAGE_LOADED_OTH;
+            }
+        }
+
+        if (*pkg && cb_data->chunk) {
+            assert(!(*pkg)->chunk);
+            (*pkg)->chunk = cb_data->chunk;
+        }
     }
 
     return CR_CB_RET_OK;
@@ -308,6 +343,7 @@ cr_load_xml_files(GHashTable *hashtable,
     assert(hashtable);
 
     // Prepare cb data
+    cb_data.state           = PARSING_PRI;
     cb_data.ht              = hashtable;
     cb_data.chunk           = chunk;
     cb_data.pkglist_ht      = pkglist_ht;
@@ -334,6 +370,8 @@ cr_load_xml_files(GHashTable *hashtable,
         return code;
     }
 
+    cb_data.state = PARSING_FIL;
+
     if (filelists_xml_path) {
         cr_xml_parse_filelists(filelists_xml_path,
                                newpkgcb,
@@ -351,6 +389,8 @@ cr_load_xml_files(GHashTable *hashtable,
         }
     }
 
+    cb_data.state = PARSING_OTH;
+
     if (other_xml_path) {
         cr_xml_parse_other(other_xml_path,
                            newpkgcb,
index bd672e8..b1749e2 100644 (file)
@@ -33,6 +33,15 @@ extern "C" {
  *  @{
  */
 
+typedef enum {
+    CR_PACKAGE_FROM_HEADER = (1<<1),    /*!< Metadata parsed from header */
+    CR_PACKAGE_FROM_XML    = (1<<2),    /*!< Metadata parsed xml */
+    /* Some values are reserved (for sqlite, solv, etc..) */
+    CR_PACKAGE_LOADED_PRI  = (1<<10),   /*!< Primary metadata was loaded */
+    CR_PACKAGE_LOADED_FIL  = (1<<11),   /*!< Filelists metadata was loaded */
+    CR_PACKAGE_LOADED_OTH  = (1<<12),   /*!< Other metadata was loaded */
+} cr_PackageLoadingFlags;
+
 /** Dependency (Provides, Conflicts, Obsoletes, Requires).
  */
 typedef struct {
@@ -107,6 +116,9 @@ typedef struct {
 
     GStringChunk *chunk;        /*!< string chunk for store all package strings
                                      on the single place */
+
+    cr_PackageLoadingFlags loadingflags; /*!<
+        Bitfield flags with information about package loading  */
 } cr_Package;
 
 /** Create new (empty) dependency structure.
index 9802d0f..8ded4c5 100644 (file)
@@ -116,6 +116,10 @@ cr_package_from_header(Header hdr, gint64 mtime, gint64 size,
     // Create new package structure
 
     pkg = cr_package_new();
+    pkg->loadingflags |= CR_PACKAGE_FROM_HEADER;
+    pkg->loadingflags |= CR_PACKAGE_LOADED_PRI;
+    pkg->loadingflags |= CR_PACKAGE_LOADED_FIL;
+    pkg->loadingflags |= CR_PACKAGE_LOADED_OTH;
 
 
     // Create rpm tag data container