+ bluesky_cloudlog_stats_update(item, -1);
+
+ /* First, check to see if the journal still contains a copy of the item and
+ * if so use that. */
+ if ((item->location_flags | item->pending_write) & CLOUDLOG_JOURNAL) {
+ map = bluesky_cachefile_lookup(fs, -1, item->log_seq, TRUE);
+ if (map != NULL) {
+ location = CLOUDLOG_JOURNAL;
+ file_offset = item->log_offset;
+ file_size = item->log_size;
+ }
+ }
+
+ if (location == 0 && (item->location_flags & CLOUDLOG_CLOUD)) {
+ item->location_flags &= ~CLOUDLOG_JOURNAL;
+ map = bluesky_cachefile_lookup(fs,
+ item->location.directory,
+ item->location.sequence,
+ !range_request);
+ if (map == NULL) {
+ g_warning("Unable to remap cloud log segment!");
+ goto exit1;
+ }
+ location = CLOUDLOG_CLOUD;
+ file_offset = item->location.offset;
+ file_size = item->location.size;
+ }
+
+ /* Log segments fetched from the cloud might only be partially-fetched.
+ * Check whether the object we are interested in is available. */
+ if (location == CLOUDLOG_CLOUD) {
+ while (TRUE) {
+ const BlueSkyRangesetItem *rangeitem;
+ rangeitem = bluesky_rangeset_lookup(map->items, file_offset);
+ if (rangeitem != NULL && (rangeitem->start != file_offset
+ || rangeitem->length != file_size)) {
+ g_warning("log-%d: Item offset %zd seems to be invalid!",
+ (int)item->location.sequence, file_offset);
+ goto exit2;
+ }
+ if (rangeitem == NULL) {
+ if (bluesky_verbose) {
+ g_print("Item at offset 0x%zx not available, need to fetch.\n",
+ file_offset);
+ }
+ if (range_request) {
+ uint64_t start = file_offset, length = file_size, end;
+ if (map->prefetches != NULL)
+ bluesky_rangeset_get_extents(map->prefetches,
+ &start, &length);
+ start = MIN(start, file_offset);
+ end = MAX(start + length, file_offset + file_size);
+ length = end - start;
+ cloudlog_partial_fetch_start(map, start, length);
+ if (map->prefetches != NULL) {
+ bluesky_rangeset_free(map->prefetches);
+ map->prefetches = NULL;
+ }
+ }
+ g_cond_wait(map->cond, map->lock);
+ } else if (rangeitem->start == file_offset
+ && rangeitem->length == file_size) {
+ if (bluesky_verbose)
+ g_print("Item %zd now available.\n", file_offset);
+ break;
+ }
+ }
+ }
+
+ if (map_data) {
+ if (location == CLOUDLOG_JOURNAL)
+ file_offset += sizeof(struct log_header);
+ else
+ file_offset += sizeof(struct cloudlog_header);
+
+ file_size = item->data_size;
+ }
+ str = bluesky_cachefile_map_raw(map, file_offset, file_size);
+
+exit2: