g_mutex_unlock(log->fs->lock);
}
-struct cloudlog_header {
- char magic[4];
- uint8_t type;
- BlueSkyCloudID id;
- uint32_t size1, size2, size3;
-} __attribute__((packed));
+/* Look up the cloud log entry for the given ID. If create is TRUE and the
+ * item does not exist, create a special pending entry that can later be filled
+ * in when the real item is loaded. The returned item has a reference held.
+ * As a special case, if a null ID is provided then NULL is returned. */
+BlueSkyCloudLog *bluesky_cloudlog_get(BlueSkyFS *fs, BlueSkyCloudID id)
+{
+ static BlueSkyCloudID id0 = {{0}};
-#define CLOUDLOG_MAGIC "AgI-"
+ if (memcmp(&id, &id0, sizeof(BlueSkyCloudID)) == 0)
+ return NULL;
+
+ g_mutex_lock(fs->lock);
+ BlueSkyCloudLog *item;
+ item = g_hash_table_lookup(fs->locations, &id);
+ if (item == NULL) {
+ item = bluesky_cloudlog_new(fs, &id);
+ g_hash_table_insert(fs->locations, &id, item);
+ } else {
+ bluesky_cloudlog_ref(item);
+ }
+ g_mutex_unlock(fs->lock);
+ return item;
+}
/* Ensure that a cloud log item is loaded in memory, and if not read it in.
* TODO: Make asynchronous, and make this also fetch from the cloud. Right now
if (log->data != NULL)
return;
+ int offset;
+
if ((log->location_flags | log->pending_write) & CLOUDLOG_JOURNAL) {
bluesky_cloudlog_stats_update(log, -1);
+ offset = log->log_offset + sizeof(struct log_header);
log->data = bluesky_log_map_object(log->fs, -1, log->log_seq,
- log->log_offset, log->log_size);
+ offset, log->data_size);
bluesky_cloudlog_stats_update(log, 1);
}
if (log->data == NULL && (log->location_flags & CLOUDLOG_CLOUD)) {
log->location_flags &= ~CLOUDLOG_JOURNAL;
bluesky_cloudlog_stats_update(log, -1);
+ offset = log->location.offset + sizeof(struct cloudlog_header);
log->data = bluesky_log_map_object(log->fs, log->location.directory,
log->location.sequence,
- log->location.offset,
- log->location.size);
+ offset, log->data_size);
bluesky_cloudlog_stats_update(log, 1);
}
/* TODO: Right now offset/size are set to the raw data, but we should add
* header parsing to the code which loads objects back in. */
log->location = state->location;
- log->location.offset = state->data->len + sizeof(struct cloudlog_header);
- log->location.size = data1->len;
+ log->location.offset = state->data->len;
+ log->data_size = data1->len;
struct cloudlog_header header;
memcpy(header.magic, CLOUDLOG_MAGIC, 4);
g_string_append_len(state->data, data2->str, data2->len);
g_string_append_len(state->data, data3->str, data3->len);
+ log->location.size = state->data->len - log->location.offset;
+
/* If the object we flushed was an inode, update the inode map. */
if (log->type == LOGTYPE_INODE) {
g_mutex_lock(fs->lock);