[libgweather] Associate the metar code cache with a specific world



commit 1800633598f1cbe1af09716d5bdbcdc6f7711665
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Mon Mar 19 22:47:58 2012 +0100

    Associate the metar code cache with a specific world
    
    GWeatherLocation are strongly associated with the world node that was
    created when the database was parsed, and they become useless when
    disconnected. This way, the API user can keep a world node alive
    and ensure that all locations are from the same parser run.

 libgweather/gweather-location.c |   23 +++++++++++------------
 libgweather/gweather-location.h |    3 ++-
 libgweather/parser.c            |    4 ++++
 libgweather/parser.h            |    1 +
 libgweather/weather-priv.h      |    1 +
 libgweather/weather.c           |   25 ++++++++++++++++++++-----
 6 files changed, 39 insertions(+), 18 deletions(-)
---
diff --git a/libgweather/gweather-location.c b/libgweather/gweather-location.c
index 5460302..b1d12e1 100644
--- a/libgweather/gweather-location.c
+++ b/libgweather/gweather-location.c
@@ -34,8 +34,6 @@
 #include "parser.h"
 #include "weather-priv.h"
 
-static GHashTable *metar_code_cache;
-
 /**
  * SECTION:gweather-location
  * @Title: GWeatherLocation
@@ -55,6 +53,7 @@ struct _GWeatherLocation {
     double latitude, longitude;
     gboolean latlon_valid;
     GWeatherTimezone **zones;
+    GHashTable *metar_code_cache;
 
     int ref_count;
 };
@@ -142,6 +141,8 @@ location_new_from_xml (GWeatherParser *parser, GWeatherLocationLevel level,
     loc->parent = parent;
     loc->level = level;
     loc->ref_count = 1;
+    if (level == GWEATHER_LOCATION_WORLD)
+	loc->metar_code_cache = g_hash_table_ref (parser->metar_code_cache);
     children = g_ptr_array_new ();
 
     if (xmlTextReaderRead (parser->xml) != 1)
@@ -252,7 +253,7 @@ location_new_from_xml (GWeatherParser *parser, GWeatherLocationLevel level,
 
     if (level == GWEATHER_LOCATION_WEATHER_STATION) {
 	/* Cache weather stations by METAR code */
-	g_hash_table_replace (metar_code_cache, loc->station_code, gweather_location_ref (loc));
+	g_hash_table_replace (parser->metar_code_cache, loc->station_code, gweather_location_ref (loc));
     }
 
     if (children->len) {
@@ -302,9 +303,6 @@ gweather_location_new_world (gboolean use_regions)
     GWeatherParser *parser;
     GWeatherLocation *world;
 
-    if (!metar_code_cache)
-	metar_code_cache = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) gweather_location_unref);
-
     parser = gweather_parser_new (use_regions);
     if (!parser)
 	return NULL;
@@ -371,6 +369,9 @@ gweather_location_unref (GWeatherLocation *loc)
 	g_free (loc->zones);
     }
 
+    if (loc->metar_code_cache)
+	g_hash_table_unref (loc->metar_code_cache);
+
     g_slice_free (GWeatherLocation, loc);
 }
 
@@ -768,10 +769,8 @@ _weather_location_from_gweather_location (GWeatherLocation *gloc, const gchar *n
 }
 
 GWeatherLocation *
-gweather_location_find_by_station_code (const gchar *station_code) {
-    if (!metar_code_cache)
-	gweather_location_unref (gweather_location_new_world (FALSE));
-
-    return g_hash_table_lookup (metar_code_cache, station_code);
+gweather_location_find_by_station_code (GWeatherLocation *world,
+					const gchar      *station_code)
+{
+    return g_hash_table_lookup (world->metar_code_cache, station_code);
 }
-
diff --git a/libgweather/gweather-location.h b/libgweather/gweather-location.h
index 89b97d9..85265b5 100644
--- a/libgweather/gweather-location.h
+++ b/libgweather/gweather-location.h
@@ -79,7 +79,8 @@ void                   gweather_location_free_timezones (GWeatherLocation  *loc,
 const char            *gweather_location_get_code       (GWeatherLocation  *loc);
 char                  *gweather_location_get_city_name  (GWeatherLocation  *loc);
 
-GWeatherLocation      *gweather_location_find_by_station_code (const gchar *code);
+GWeatherLocation      *gweather_location_find_by_station_code (GWeatherLocation *world,
+							       const gchar *code);
 
 G_END_DECLS
 
diff --git a/libgweather/parser.c b/libgweather/parser.c
index 9a5dd6f..ffefcab 100644
--- a/libgweather/parser.c
+++ b/libgweather/parser.c
@@ -247,6 +247,8 @@ gweather_parser_new (gboolean use_regions)
     tm.tm_year++;
     parser->year_end = mktime (&tm);
 
+    parser->metar_code_cache = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) gweather_location_unref);
+
     return parser;
 
 error_out:
@@ -259,5 +261,7 @@ gweather_parser_free (GWeatherParser *parser)
 {
     if (parser->xml)
 	xmlFreeTextReader (parser->xml);
+    g_hash_table_unref (parser->metar_code_cache);
+
     g_slice_free (GWeatherParser, parser);
 }
diff --git a/libgweather/parser.h b/libgweather/parser.h
index 1d3d134..6b1c807 100644
--- a/libgweather/parser.h
+++ b/libgweather/parser.h
@@ -29,6 +29,7 @@ typedef struct {
     const char * const *locales;
     gboolean use_regions;
     time_t year_start, year_end;
+    GHashTable *metar_code_cache;
 } GWeatherParser;
 
 GWeatherParser *gweather_parser_new                 (gboolean        use_regions);
diff --git a/libgweather/weather-priv.h b/libgweather/weather-priv.h
index 8a910f7..01782b1 100644
--- a/libgweather/weather-priv.h
+++ b/libgweather/weather-priv.h
@@ -103,6 +103,7 @@ struct _GWeatherInfoPrivate {
     gboolean moonValid;
     gboolean tempMinMaxValid;
     WeatherLocation *location;
+    GWeatherLocation *world;
     GWeatherLocation *glocation;
     GWeatherUpdate update;
     GWeatherSky sky;
diff --git a/libgweather/weather.c b/libgweather/weather.c
index 12e0b88..91738e8 100644
--- a/libgweather/weather.c
+++ b/libgweather/weather.c
@@ -63,6 +63,7 @@ static void _weather_internal_check (void);
 
 enum {
     PROP_0,
+    PROP_WORLD,
     PROP_LOCATION,
     PROP_TYPE,
     PROP_LAST
@@ -544,10 +545,11 @@ gweather_info_finalize (GObject *object)
     _weather_location_free (priv->location);
     priv->location = NULL;
 
-    if (priv->glocation) {
+    if (priv->glocation)
 	gweather_location_unref (priv->glocation);
-	priv->glocation = NULL;
-    }
+
+    if (priv->world)
+	gweather_location_unref (priv->world);
 
     g_free (priv->forecast);
     priv->forecast = NULL;
@@ -1535,7 +1537,7 @@ gweather_info_get_value_apparent (GWeatherInfo *info, GWeatherTemperatureUnit un
 /**
  * gweather_info_get_value_update:
  * @info: a #GWeatherInfo
- * @value: (out) (type gulong): the time @info was last updated
+ * @value: (out) (type glong): the time @info was last updated
  *
  * Returns: TRUE is @value is valid, FALSE otherwise.
  */
@@ -1744,6 +1746,9 @@ gweather_info_set_location_internal (GWeatherInfo     *info,
     if (priv->location)
 	_weather_location_free (priv->location);
 
+    if (!priv->world)
+	priv->world = gweather_location_new_world (FALSE);
+
     priv->glocation = location;
     if (priv->glocation) {
 	gweather_location_ref (location);
@@ -1756,7 +1761,7 @@ gweather_info_set_location_internal (GWeatherInfo     *info,
 	if (strcmp(name, "") == 0)
 	    name = NULL;
 
-	priv->glocation = gweather_location_find_by_station_code (station_code);
+	priv->glocation = gweather_location_find_by_station_code (priv->world, station_code);
     }
 
     priv->location = _weather_location_from_gweather_location (priv->glocation, name);
@@ -1797,6 +1802,9 @@ gweather_info_set_property (GObject *object,
     GWeatherInfoPrivate *priv = self->priv;
 
     switch (property_id) {
+    case PROP_WORLD:
+	priv->world = g_value_dup_boxed (value);
+	break;
     case PROP_LOCATION:
 	gweather_info_set_location_internal (self, (GWeatherLocation*) g_value_get_boxed (value));
 	break;
@@ -1819,6 +1827,13 @@ gweather_info_class_init (GWeatherInfoClass *klass)
     gobject_class->finalize = gweather_info_finalize;
     gobject_class->set_property = gweather_info_set_property;
 
+    pspec = g_param_spec_boxed ("world",
+				"World",
+				"The hierarchy of locations containing the desired location",
+				GWEATHER_TYPE_LOCATION,
+				G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
+    g_object_class_install_property (gobject_class, PROP_WORLD, pspec);
+
     pspec = g_param_spec_boxed ("location",
 				"Location",
 				"The location this info represents",



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]