* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+/**
+ * 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 <config.h>
#include <glib.h>
#include <glib/gstdio.h>
#include "gis-http.h"
+/**
+ * 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 *self = g_new0(GisHttp, 1);
- self->soup = soup_session_sync_new();
- self->prefix = g_strdup(prefix);
- g_object_set(self->soup, "user-agent", PACKAGE_STRING, NULL);
- return self;
+ GisHttp *http = g_new0(GisHttp, 1);
+ http->soup = soup_session_sync_new();
+ http->prefix = g_strdup(prefix);
+ g_object_set(http->soup, "user-agent", PACKAGE_STRING, NULL);
+ return http;
}
-void gis_http_free(GisHttp *self)
+/**
+ * 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", self->prefix);
- soup_session_abort(self->soup);
- g_object_unref(self->soup);
- g_free(self->prefix);
- g_free(self);
+ 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;
*/
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",
}
}
+/**
+ * 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 - %.20s... >> %s/%s mode=%d",
- uri, self->prefix, local, mode);
+ uri, http->prefix, local, mode);
gchar *path = g_build_filename(g_get_user_cache_dir(), PACKAGE,
- self->prefix, local, NULL);
+ http->prefix, local, NULL);
/* Unlink the file if we're refreshing it */
if (mode == GIS_REFRESH)
g_debug("GisHttp: do_cache - 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,
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.. */