#include <stdint.h>
#include <glib.h>
+/* Reference-counted blocks of memory, used for passing data in and out of
+ * storage backends and in other places. */
+typedef struct {
+ gint refcount;
+ gpointer data;
+ gsize len;
+} BlueSkyRCStr;
+
+BlueSkyRCStr *bluesky_string_new(gpointer data, gsize len);
+void bluesky_string_ref(BlueSkyRCStr *string);
+void bluesky_string_unref(BlueSkyRCStr *string);
+BlueSkyRCStr *bluesky_string_dup(BlueSkyRCStr *string);
+
/* File types. The numeric values are chosen to match with those used in
* NFSv3. */
typedef enum {
/* File-specific fields */
uint64_t size;
+ GArray *blocks;
/* Directory-specific fields */
- GSequence *dirents;
+ GSequence *dirents; /* List of entries for READDIR */
+ GHashTable *dirhash; /* Hash table by name for LOOKUP */
uint64_t parent_inum; /* inode for ".."; 0 if the root directory */
} BlueSkyInode;
/* A directory entry. The name is UTF-8 and is a freshly-allocated string.
- * The name is hashed to a 64-bit value, and the directory entries are sorted
- * by hash value (the hash value can then be used as a cookie for resuming a
- * READDIR call). */
+ * Each directory entry is listed in two indices: dirents is indexed by cookie
+ * and dirhash by name. The cookie is a randomly-assigned 32-bit value, unique
+ * within the directory, that remains unchanged until the entry is deleted. It
+ * is used to provide a stable key for restarting a READDIR call. */
typedef struct {
gchar *name;
- uint64_t hash;
+ uint32_t cookie;
uint64_t inum;
-} BlueSkyDirent ;
+} BlueSkyDirent;
+
+/* File data is divided into fixed-size blocks (except the last block which may
+ * be short?). These blocks are backed by storage in a key/value store, but
+ * may also be dirty if modifications have been made in-memory that have not
+ * been committed. */
+#define BLUESKY_BLOCK_SIZE 32768ULL
+#define BLUESKY_MAX_FILE_SIZE (BLUESKY_BLOCK_SIZE << 24)
+typedef enum {
+ BLUESKY_BLOCK_ZERO = 0, /* Data is all zeroes, not explicitly stored */
+ BLUESKY_BLOCK_REF = 1, /* Reference to key/value store, not cached */
+ BLUESKY_BLOCK_CACHED = 2, /* Data is cached in memory, clean */
+ BLUESKY_BLOCK_DIRTY = 3, /* Data needs to be committed to store */
+} BlueSkyBlockType;
+
+typedef struct {
+ BlueSkyBlockType type;
+ gchar *ref; /* Name of data block in the backing store */
+ gchar *data; /* Pointer to data in memory */
+} BlueSkyBlock;
BlueSkyFS *bluesky_new_fs(gchar *name);
int64_t bluesky_get_current_time();
+void bluesky_inode_update_ctime(BlueSkyInode *inode, gboolean update_mtime);
uint64_t bluesky_fs_alloc_inode(BlueSkyFS *fs);
BlueSkyInode *bluesky_new_inode(uint64_t inum, BlueSkyFileType type);
uint64_t inum);
void bluesky_directory_dump(BlueSkyInode *dir);
+void bluesky_block_touch(BlueSkyInode *inode, uint64_t i);
+void bluesky_block_flush(BlueSkyBlock *block);
+void bluesky_file_truncate(BlueSkyInode *inode, uint64_t size);
+void bluesky_file_write(BlueSkyInode *inode, uint64_t offset,
+ const char *data, gint len);
+void bluesky_file_read(BlueSkyInode *inode, uint64_t offset,
+ char *buf, gint len);
+
#endif