X-Git-Url: http://pileus.org/git/?p=grits;a=blobdiff_plain;f=src%2Fdata%2Fgis-http.c;h=739792a57a33669f180257aaf6cab4d511b412a2;hp=ad21baf5ea03d0436894fefd3e021ad55982dd7a;hb=e995e7c95773c0adfa8dfd40b9ee5d099485afd3;hpb=50fd58d421d4b632d0980a5a22ed3506776f00ab diff --git a/src/data/gis-http.c b/src/data/gis-http.c index ad21baf..739792a 100644 --- a/src/data/gis-http.c +++ b/src/data/gis-http.c @@ -15,6 +15,16 @@ * along with this program. If not, see . */ +/** + * SECTION:gis-http + * @short_description: Hyper Text Transfer Protocol + * + * #GisHttp is a small wrapper around libsoup to provide data access using the + * Hyper Text Transfer Protocol. Each #GisHttp should be associated with a + * particular server or dataset, all the files downloaded for this dataset will + * be cached together in $HOME.cache/libgis/ + */ + #include #include #include @@ -22,17 +32,48 @@ #include "gis-http.h" +gchar *_get_cache_path(GisHttp *http, const gchar *local) +{ + return g_build_filename(g_get_user_cache_dir(), PACKAGE, + http->prefix, local, NULL); +} + +/** + * gis_http_new: + * @prefix: The prefix in the cache to store the downloaded files. + * For example: * "/nexrad/level2/". + * + * Create a new #GisHttp for the given prefix + * + * Returns: the new #GisHttp + */ GisHttp *gis_http_new(const gchar *prefix) { + g_debug("GisHttp: new - %s", prefix); GisHttp *http = g_new0(GisHttp, 1); - http->prefix = g_strdup(prefix); http->soup = soup_session_sync_new(); + http->prefix = g_strdup(prefix); g_object_set(http->soup, "user-agent", PACKAGE_STRING, NULL); return http; } +/** + * gis_http_free: + * @http: the #GisHttp to free + * + * Frees resources used by @http and cancels any pending requests. + */ +void gis_http_free(GisHttp *http) +{ + g_debug("GisHttp: free - %s", http->prefix); + soup_session_abort(http->soup); + g_object_unref(http->soup); + g_free(http->prefix); + g_free(http); +} + /* For passing data to the chunck callback */ -struct _cache_info { +struct _CacheInfo { FILE *fp; gchar *path; GisChunkCallback callback; @@ -44,7 +85,7 @@ struct _cache_info { */ static void _chunk_cb(SoupMessage *message, SoupBuffer *chunk, gpointer _info) { - struct _cache_info *info = _info; + struct _CacheInfo *info = _info; if (!SOUP_STATUS_IS_SUCCESSFUL(message->status_code)) { g_warning("GisHttp: _chunk_cb - soup failed with %d", @@ -64,14 +105,28 @@ static void _chunk_cb(SoupMessage *message, SoupBuffer *chunk, gpointer _info) } } +/** + * gis_http_fetch: + * @http: the #GisHttp connection to use + * @uri: the URI to fetch + * @local: the local name to give to the file + * @mode: the update type to use when fetching data + * @callback: callback to call when a chunk of data is received + * @user_data: user data to pass to the callback + * + * Fetch a file from the cache. Whether the file is actually loaded from the + * remote server depends on the value of @mode. + * + * Returns: The local path to the complete file + */ /* TODO: use .part extentions and continue even when using GIS_ONCE */ -gchar *gis_http_fetch(GisHttp *self, const gchar *uri, const char *local, +gchar *gis_http_fetch(GisHttp *http, const gchar *uri, const char *local, GisCacheType mode, GisChunkCallback callback, gpointer user_data) { - g_debug("GisHttp: fetch - %s >> %s mode=%d", uri, self->prefix, mode); + g_debug("GisHttp: fetch - %s... >> %s/%s mode=%d", + uri, http->prefix, local, mode); - gchar *path = g_build_filename(g_get_user_cache_dir(), PACKAGE, - self->prefix, local, NULL); + gchar *path = _get_cache_path(http, local); /* Unlink the file if we're refreshing it */ if (mode == GIS_REFRESH) @@ -80,13 +135,16 @@ gchar *gis_http_fetch(GisHttp *self, const gchar *uri, const char *local, /* Do the cache if necessasairy */ if (!(mode == GIS_ONCE && g_file_test(path, G_FILE_TEST_EXISTS)) && mode != GIS_LOCAL) { - g_debug("GisHttp: do_cache - Caching file %s", local); + g_debug("GisHttp: fetch - Caching file %s", local); /* Open the file for writting */ - FILE *fp = fopen_p(path, "a"); + gchar *part = path; + if (!g_file_test(path, G_FILE_TEST_EXISTS)) + part = g_strdup_printf("%s.part", path); + FILE *fp = fopen_p(part, "a"); /* Make temp data */ - struct _cache_info info = { + struct _CacheInfo info = { .fp = fp, .path = path, .callback = callback, @@ -99,16 +157,25 @@ gchar *gis_http_fetch(GisHttp *self, const gchar *uri, const char *local, g_error("message is null, cannot parse uri"); g_signal_connect(message, "got-chunk", G_CALLBACK(_chunk_cb), &info); soup_message_headers_set_range(message->request_headers, ftell(fp), -1); - soup_session_send_message(self->soup, message); + soup_session_send_message(http->soup, message); + + /* Close file */ + fclose(fp); + if (path != part && SOUP_STATUS_IS_SUCCESSFUL(message->status_code)) { + g_rename(part, path); + g_free(part); + } /* Finished */ if (message->status_code == 416) { /* Range unsatisfiable, file already complete */ - } else if (!SOUP_STATUS_IS_SUCCESSFUL(message->status_code)) + } else if (!SOUP_STATUS_IS_SUCCESSFUL(message->status_code)) { g_warning("GisHttp: done_cb - error copying file, status=%d\n" "\tsrc=%s\n" "\tdst=%s", message->status_code, uri, path); + return NULL; + } } /* TODO: free everything.. */