+ g_mutex_lock(item->lock);
+ g_mutex_unlock(item->lock);
+ bluesky_cloudlog_unref(item);
+}
+
+void bluesky_cloudlog_background_fetch(BlueSkyCloudLog *item)
+{
+ bluesky_cloudlog_ref(item);
+ g_thread_pool_push(fetch_pool, item, NULL);
+}
+
+/* Attempt to prefetch a cloud log item. This does not guarantee that it will
+ * be made available, but does make it more likely that a future call to
+ * bluesky_cloudlog_fetch will complete quickly. Item must be locked? */
+void bluesky_cloudlog_prefetch(BlueSkyCloudLog *item)
+{
+ if (item->data != NULL)
+ return;
+
+ /* When operating in a non log-structured mode, simply start a background
+ * fetch immediately when asked to prefetch. */
+ if (bluesky_options.disable_aggregation
+ || bluesky_options.disable_read_aggregation) {
+ bluesky_cloudlog_background_fetch(item);
+ return;
+ }
+
+ /* TODO: Some of the code here is duplicated with bluesky_log_map_object.
+ * Refactor to fix that. */
+ BlueSkyFS *fs = item->fs;
+ BlueSkyCacheFile *map = NULL;
+
+ /* First, check to see if the journal still contains a copy of the item and
+ * if so update the atime on the journal so it is likely to be kept around
+ * until we need it. */
+ if ((item->location_flags | item->pending_write) & CLOUDLOG_JOURNAL) {
+ map = bluesky_cachefile_lookup(fs, -1, item->log_seq, TRUE);
+ if (map != NULL) {
+ map->atime = bluesky_get_current_time();
+ bluesky_cachefile_unref(map);
+ g_mutex_unlock(map->lock);
+ return;
+ }
+ }
+
+ item->location_flags &= ~CLOUDLOG_JOURNAL;
+ if (!(item->location_flags & CLOUDLOG_CLOUD))
+ return;
+
+ map = bluesky_cachefile_lookup(fs,
+ item->location.directory,
+ item->location.sequence,
+ FALSE);
+ if (map == NULL)
+ return;
+
+ /* At this point, we have information about the log segment containing the
+ * item we need. If our item is already fetched, we have nothing to do
+ * except update the atime. If not, queue up a fetch of our object. */
+ const BlueSkyRangesetItem *rangeitem;
+ rangeitem = bluesky_rangeset_lookup(map->items,
+ item->location.offset);
+ if (rangeitem == NULL) {
+ if (map->prefetches == NULL)
+ map->prefetches = bluesky_rangeset_new();
+
+ gchar *id = bluesky_cloudlog_id_to_string(item->id);
+ if (bluesky_verbose)
+ g_print("Need to prefetch %s\n", id);
+ g_free(id);
+
+ bluesky_rangeset_insert(map->prefetches,
+ item->location.offset,
+ item->location.size, NULL);
+
+ uint64_t start, length;
+ bluesky_rangeset_get_extents(map->prefetches, &start, &length);
+ if (bluesky_verbose)
+ g_print("Range to prefetch: %"PRIu64" + %"PRIu64"\n",
+ start, length);
+ }
+
+ bluesky_cachefile_unref(map);
+ g_mutex_unlock(map->lock);
+}