X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/6a4a29aa76af1b8ed8695cf8ed16c186b571d9e1..01709fe4e9fa57f256a22a4f87124ba0fb03dcfa:/src/download.c diff --git a/src/download.c b/src/download.c index e973ab8c..1c7711b9 100644 --- a/src/download.c +++ b/src/download.c @@ -27,8 +27,12 @@ #include #include #include +#ifdef HAVE_SYS_TYPES_H #include +#endif +#ifdef HAVE_UTIME_H #include +#endif #include #include #include @@ -37,6 +41,8 @@ #include "download.h" #include "curl_download.h" +#include "preferences.h" +#include "globals.h" static gboolean check_file_first_line(FILE* f, gchar *patterns[]) { @@ -93,7 +99,49 @@ gboolean a_check_kml_file(FILE* f) return check_file_first_line(f, kml_str); } -static int download( const char *hostname, const char *uri, const char *fn, DownloadOptions *options, gboolean ftp) +static GList *file_list = NULL; +static GMutex *file_list_mutex = NULL; + +/* spin button scales */ +VikLayerParamScale params_scales[] = { + {1, 10000, 10, 0}, +}; + +static VikLayerParam prefs[] = { + { VIKING_PREFERENCES_NAMESPACE "download_tile_age", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Tile age (s):"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 0, NULL }, +}; + +void a_download_init (void) +{ + VikLayerParamData tmp; + tmp.u = VIK_CONFIG_DEFAULT_TILE_AGE; + a_preferences_register(prefs, tmp, VIKING_PREFERENCES_GROUP_KEY); + + file_list_mutex = g_mutex_new(); +} + +static gboolean lock_file(const char *fn) +{ + gboolean locked = FALSE; + g_mutex_lock(file_list_mutex); + if (g_list_find(file_list, fn) == NULL) + { + // The filename is not yet locked + file_list = g_list_append(file_list, (gpointer)fn), + locked = TRUE; + } + g_mutex_unlock(file_list_mutex); + return locked; +} + +static void unlock_file(const char *fn) +{ + g_mutex_lock(file_list_mutex); + file_list = g_list_remove(file_list, (gconstpointer)fn); + g_mutex_unlock(file_list_mutex); +} + +static int download( const char *hostname, const char *uri, const char *fn, DownloadOptions *options, gboolean ftp, void *handle) { FILE *f; int ret; @@ -105,10 +153,14 @@ static int download( const char *hostname, const char *uri, const char *fn, Down if ( g_file_test ( fn, G_FILE_TEST_EXISTS ) == TRUE ) { if (options != NULL && options->check_file_server_time) { + time_t tile_age = a_preferences_get(VIKING_PREFERENCES_NAMESPACE "download_tile_age")->u; /* Get the modified time of this file */ struct stat buf; g_stat ( fn, &buf ); time_condition = buf.st_mtime; + if ( (time(NULL) - time_condition) < tile_age ) + /* File cache is too recent, so return */ + return -3; } else { /* Nothing to do as file already exists, so return */ return -3; @@ -120,16 +172,21 @@ static int download( const char *hostname, const char *uri, const char *fn, Down } tmpfilename = g_strdup_printf("%s.tmp", fn); - f = g_fopen ( tmpfilename, "w+bx" ); /* truncate file and open it in exclusive mode */ + if (!lock_file ( tmpfilename ) ) + { + g_debug("%s: Couldn't take lock on temporary file \"%s\"\n", __FUNCTION__, tmpfilename); + g_free ( tmpfilename ); + return -4; + } + f = g_fopen ( tmpfilename, "w+b" ); /* truncate file and open it */ if ( ! f ) { - if (errno == EEXIST) - g_debug("%s: Couldn't take lock on temporary file \"%s\"\n", __FUNCTION__, tmpfilename); + g_warning("Couldn't open temporary file \"%s\": %s", tmpfilename, g_strerror(errno)); g_free ( tmpfilename ); return -4; } /* Call the backend function */ - ret = curl_download_get_url ( hostname, uri, f, options, ftp, time_condition ); + ret = curl_download_get_url ( hostname, uri, f, options, ftp, time_condition, handle ); if (ret != DOWNLOAD_NO_ERROR && ret != DOWNLOAD_NO_NEWER_FILE) { g_debug("%s: download failed: curl_download_get_url=%d", __FUNCTION__, ret); @@ -141,36 +198,53 @@ static int download( const char *hostname, const char *uri, const char *fn, Down failure = TRUE; } + fclose ( f ); + f = NULL; + if (failure) { g_warning(_("Download error: %s"), fn); g_remove ( tmpfilename ); + unlock_file ( tmpfilename ); g_free ( tmpfilename ); - fclose ( f ); - f = NULL; g_remove ( fn ); /* couldn't create temporary. delete 0-byte file. */ return -1; } - if (ret == DOWNLOAD_NO_NEWER_FILE) + if (ret == DOWNLOAD_NO_NEWER_FILE) { g_remove ( tmpfilename ); - else +#if GLIB_CHECK_VERSION(2,18,0) + g_utime ( fn, NULL ); /* update mtime of local copy */ +#else + utimes ( fn, NULL ); /* update mtime of local copy */ +#endif + } else g_rename ( tmpfilename, fn ); /* move completely-downloaded file to permanent location */ + unlock_file ( tmpfilename ); g_free ( tmpfilename ); - fclose ( f ); - f = NULL; + return 0; } /* success = 0, -1 = couldn't connect, -2 HTTP error, -3 file exists, -4 couldn't write to file... */ /* uri: like "/uri.html?whatever" */ /* only reason for the "wrapper" is so we can do redirects. */ -int a_http_download_get_url ( const char *hostname, const char *uri, const char *fn, DownloadOptions *opt ) +int a_http_download_get_url ( const char *hostname, const char *uri, const char *fn, DownloadOptions *opt, void *handle ) +{ + return download ( hostname, uri, fn, opt, FALSE, handle ); +} + +int a_ftp_download_get_url ( const char *hostname, const char *uri, const char *fn, DownloadOptions *opt, void *handle ) +{ + return download ( hostname, uri, fn, opt, TRUE, handle ); +} + +void * a_download_handle_init () { - return download ( hostname, uri, fn, opt, FALSE ); + return curl_download_handle_init (); } -int a_ftp_download_get_url ( const char *hostname, const char *uri, const char *fn, DownloadOptions *opt ) +void a_download_handle_cleanup ( void *handle ) { - return download ( hostname, uri, fn, opt, TRUE ); + curl_download_handle_cleanup ( handle ); }