[PATCH] Make the Welcome spoke wait for Geolocation lookup to finish (#975193)

Martin Kolman mkolman at redhat.com
Fri Jun 28 14:28:35 UTC 2013


The GeoIP lookup usually takes between 1 to 2 seconds to finish.
In some cases, such as when running on a live system, the welcome spoke
might show up before the lookup can finish, so the result of the lookup
can not be used to pre-set the language.

To improve this, the geoloc module top level functions now have an
optional wait parameter, that makes the function block until the
lookup is is done or a timeout is reached.

The end result is, that the Welcome spoke will wait up to 3 seconds
for the lookup to finish. Usually it would wait less than 2 seconds or
not at all (if the lookup finishes before the welcome spoke is even
initialized).

Signed-off-by: Martin Kolman <mkolman at gmail.com>
---
 pyanaconda/constants.py             |  3 ++
 pyanaconda/geoloc.py                | 62 ++++++++++++++++++++++++++++++++-----
 pyanaconda/ui/gui/spokes/welcome.py |  2 +-
 3 files changed, 59 insertions(+), 8 deletions(-)

diff --git a/pyanaconda/constants.py b/pyanaconda/constants.py
index ee9ffdb..175dc36 100644
--- a/pyanaconda/constants.py
+++ b/pyanaconda/constants.py
@@ -141,6 +141,9 @@ GEOLOC_GEOCODER_NOMINATIM = "geocoder_nominatim"
 # default providers
 GEOLOC_DEFAULT_PROVIDER = GEOLOC_PROVIDER_FEDORA_GEOIP
 GEOLOC_DEFAULT_GEOCODER = GEOLOC_GEOCODER_NOMINATIM
+# timeout (in seconds)
+GEOLOC_TIMEOUT = 3
+
 
 ANACONDA_ENVIRON = "anaconda"
 FIRSTBOOT_ENVIRON = "firstboot"
diff --git a/pyanaconda/geoloc.py b/pyanaconda/geoloc.py
index 5a6da14..bb5619f 100644
--- a/pyanaconda/geoloc.py
+++ b/pyanaconda/geoloc.py
@@ -117,6 +117,11 @@ from pyanaconda import nm
 
 location_info_instance = None
 
+# when waiting for result from geolocation,
+# how ofthen should we check if a result was returned or
+# if the timetout was reached (in seconds)
+GEOLOC_TIMEOUT_CHECK_INTERVAL = 0.2
+
 
 def init_geolocation(provider_id=constants.GEOLOC_DEFAULT_PROVIDER):
     """Prepare the geolocation module for handling geolocation queries.
@@ -143,7 +148,7 @@ def refresh():
         log.debug("Geoloc: refresh() called before init_geolocation()")
 
 
-def get_territory_code():
+def get_territory_code(wait=False):
     """This function returns the current country code
     or None, if:
     - no results were found
@@ -151,16 +156,17 @@ def get_territory_code():
     - the geolocation module was not activated (init & refresh were not called)
      - this is for example the case during image and directory installs
 
+    :param wait: wait for wait seconds for lookup in progress to finish
     :return: current country code or None if not known
     :rtype: string or None
     """
-    if location_info_instance:
+    if _get_location_info_instance(wait):
         return location_info_instance.get_territory_code()
     else:
         return None
 
 
-def get_timezone():
+def get_timezone(wait=False):
     """This function returns the current time zone
     or None, if:
     - no timezone was found
@@ -168,28 +174,29 @@ def get_timezone():
     - the geolocation module was not activated (init & refresh were not called)
      - this is for example the case during image and directory installs
 
+    :param wait: wait for wait seconds for lookup in progress to finish
     :return: current timezone or None if not known
     :rtype: string or None
     """
-    if location_info_instance:
+    if _get_location_info_instance(wait):
         return location_info_instance.get_timezone()
     else:
         return None
 
 
-def get_result():
+def get_result(wait=False):
     """Returns the current geolocation result wrapper
     or None, if:
     - no results were found
     - the refresh is still in progress
     - the geolocation module was not activated (init & refresh were not called)
-
      - this is for example the case during image and directory installs
 
+    :param wait: wait for wait seconds for lookup in progress to finish
     :return: LocationResult instance or None if location is unknown
     :rtype: LocationResult or None
     """
-    if location_info_instance:
+    if _get_location_info_instance(wait):
         return location_info_instance.get_result()
     else:
         return None
@@ -236,6 +243,47 @@ def _get_provider(provider_id):
     return provider()
 
 
+def _get_location_info_instance(wait=False):
+    """Just return instance of the location info object
+    and optionally wait for the Geolocation thread to finish
+
+    Meaning of the wait parameter:
+    - False or <=0: don't wait
+    - True : wait for default number of seconds specified by
+    the GEOLOC_TIMEOUT constant
+    - >0 - wait for a given number of seconds
+    :param wait: specifies if this function should wait
+    for the lookup to finish before returning the instance
+    :type wait: bool or integer
+
+    If there is no lookup in progress (no Geolocation refresh thread
+    is running, this function returns at once).
+    """
+
+    if wait:
+        # check if wait is boolean or a number
+        if wait is True:
+            wait = constants.GEOLOC_TIMEOUT
+        time_elapsed = 0
+        # first check if the geolocation thread is running
+        if threadMgr.get(constants.THREAD_GEOLOCATION_REFRESH):
+            while time_elapsed <= wait:
+                # refresh still in progress
+                if threadMgr.get(constants.THREAD_GEOLOCATION_REFRESH):
+                    time.sleep(GEOLOC_TIMEOUT_CHECK_INTERVAL)
+                    time_elapsed += GEOLOC_TIMEOUT_CHECK_INTERVAL
+                else:
+                    break
+            else:  # timed out
+                log.info("Waiting for Geolocation timed out after %d seconds."
+                         % wait)
+                # please note that this does not mean that the actual
+                # geolocation lookup was stopped in any way, this will
+                # just unblock the caller after the given wait period
+                # even though the lookup thread is still running
+    return location_info_instance
+
+
 class GeolocationError(Exception):
     """Exception class for geolocation related errors"""
     pass
diff --git a/pyanaconda/ui/gui/spokes/welcome.py b/pyanaconda/ui/gui/spokes/welcome.py
index 5c3a47f..fec9b68 100644
--- a/pyanaconda/ui/gui/spokes/welcome.py
+++ b/pyanaconda/ui/gui/spokes/welcome.py
@@ -156,7 +156,7 @@ class WelcomeLanguageSpoke(StandaloneSpoke):
 
         # We can use the territory from geolocation here
         # to preselect the translation, when it's available.
-        territory = geoloc.get_territory_code()
+        territory = geoloc.get_territory_code(wait=True)
         self.language = Language(LOCALE_PREFERENCES, territory=territory)
 
         # check if there is one and only one locale for the territory
-- 
1.8.1.4


More information about the anaconda-patches mailing list