## CamelKeyFile

CamelKeyFile

## Synopsis

    typedef             camel_block_t;
    typedef             camel_key_t;
                        CamelBlockRoot;
                        CamelBlock;
                        CamelBlockFile;
    #define             CAMEL_BLOCK_FILE_SYNC
    #define             CAMEL_BLOCK_SIZE
    #define             CAMEL_BLOCK_SIZE_BITS
    #define             CAMEL_BLOCK_DIRTY
    #define             CAMEL_BLOCK_DETACHED
    CamelBlockFile *    camel_block_file_new                (const gchar *path,
                                                             gint flags,
                                                             const gchar version[8],
                                                             gsize block_size);
    gint                camel_block_file_rename             (CamelBlockFile *bs,
                                                             const gchar *path);
    gint                camel_block_file_delete             (CamelBlockFile *kf);
    CamelBlock *        camel_block_file_new_block          (CamelBlockFile *bs);
    gint                camel_block_file_free_block         (CamelBlockFile *bs,
                                                             camel_block_t id);
    CamelBlock *        camel_block_file_get_block          (CamelBlockFile *bs,
                                                             camel_block_t id);
    void                camel_block_file_detach_block       (CamelBlockFile *bs,
                                                             CamelBlock *bl);
    void                camel_block_file_attach_block       (CamelBlockFile *bs,
                                                             CamelBlock *bl);
    void                camel_block_file_touch_block        (CamelBlockFile *bs,
                                                             CamelBlock *bl);
    void                camel_block_file_unref_block        (CamelBlockFile *bs,
                                                             CamelBlock *bl);
    gint                camel_block_file_sync_block         (CamelBlockFile *bs,
                                                             CamelBlock *bl);
    gint                camel_block_file_sync               (CamelBlockFile *bs);
                        CamelKeyFile;
    CamelKeyFile *      camel_key_file_new                  (const gchar *path,
                                                             gint flags,
                                                             const gchar version[8]);
    gint                camel_key_file_rename               (CamelKeyFile *kf,
                                                             const gchar *path);
    gint                camel_key_file_delete               (CamelKeyFile *kf);
    gint                camel_key_file_write                (CamelKeyFile *kf,
                                                             camel_block_t *parent,
                                                             gsize len,
                                                             camel_key_t *records);
    gint                camel_key_file_read                 (CamelKeyFile *kf,
                                                             camel_block_t *start,
                                                             gsize *len,
                                                             camel_key_t **records);

## Description

## Details

### camel_block_t

    typedef guint32 camel_block_t;	/* block offset, absolute, bottom BLOCK_SIZE_BITS always 0 */

### camel_key_t

    typedef guint32 camel_key_t;	/* this is a bitfield of (block offset:BLOCK_SIZE_BITS) */

### CamelBlockRoot

    typedef struct {
    	gchar version[8];	/* version number */

    	guint32 flags;		/* flags for file */
    	guint32 block_size;	/* block size of this file */
    	camel_block_t free;	/* free block list */
    	camel_block_t last;	/* pointer to end of blocks */

    	/* subclasses tack on, but no more than CAMEL_BLOCK_SIZE! */
    } CamelBlockRoot;

### CamelBlock

    typedef struct {
    	struct _CamelBlock *next;
    	struct _CamelBlock *prev;

    	camel_block_t id;
    	guint32 flags;
    	guint32 refcount;
    	guint32 align00;

    	guchar data[CAMEL_BLOCK_SIZE];
    } CamelBlock;

### CamelBlockFile

    typedef struct {
    	CamelObject parent;

    	struct _CamelBlockFilePrivate *priv;

    	gchar version[8];
    	gchar *path;
    	gint flags;

    	gint fd;
    	gsize block_size;

    	CamelBlockRoot *root;
    	CamelBlock *root_block;

    	/* make private? */
    	gint block_cache_limit;
    	gint block_cache_count;
    	CamelDList block_cache;
    	GHashTable *blocks;
    } CamelBlockFile;

### CAMEL_BLOCK_FILE_SYNC

    #define CAMEL_BLOCK_FILE_SYNC (1<<0)

### CAMEL_BLOCK_SIZE

    #define CAMEL_BLOCK_SIZE (1024)

### CAMEL_BLOCK_SIZE_BITS

    #define CAMEL_BLOCK_SIZE_BITS (10) /* # bits to contain block_size bytes */

### CAMEL_BLOCK_DIRTY

    #define CAMEL_BLOCK_DIRTY (1<<0)

### CAMEL_BLOCK_DETACHED

    #define CAMEL_BLOCK_DETACHED (1<<1)

### camel_block_file_new ()

    CamelBlockFile *    camel_block_file_new                (const gchar *path,
                                                             gint flags,
                                                             const gchar version[8],
                                                             gsize block_size);

Allocate a new block file, stored at `path`. `version` contains an 8 character version string which must match the head of the file, or the file will be intitialised.

`block_size` is currently ignored and is set to CAMEL_BLOCK_SIZE.

`path` : | @:
`flags` : |
`version` : |
`block_size` : |
Returns : | The new block file, or NULL if it could not be created.

### camel_block_file_rename ()

    gint                camel_block_file_rename             (CamelBlockFile *bs,
                                                             const gchar *path);

`bs` : |
`path` : |
Returns : |

### camel_block_file_delete ()

    gint                camel_block_file_delete             (CamelBlockFile *kf);

`kf` : |
Returns : |

### camel_block_file_new_block ()

    CamelBlock *        camel_block_file_new_block          (CamelBlockFile *bs);

Allocate a new block, return a pointer to it. Old blocks may be flushed to disk during this call.

`bs` : |
Returns : | The block, or NULL if an error occured.

### camel_block_file_free_block ()

    gint                camel_block_file_free_block         (CamelBlockFile *bs,
                                                             camel_block_t id);

`bs` : |
`id` : |
Returns : |

### camel_block_file_get_block ()

    CamelBlock *        camel_block_file_get_block          (CamelBlockFile *bs,
                                                             camel_block_t id);

Retreive a block `id`.

`bs` : |
`id` : |
Returns : | The block, or NULL if blockid is invalid or a file error occured.

### camel_block_file_detach_block ()

    void                camel_block_file_detach_block       (CamelBlockFile *bs,
                                                             CamelBlock *bl);

Detatch a block from the block file's cache. The block should be unref'd or attached when finished with. The block file will perform no writes of this block or flushing of it if the cache fills.

`bs` : |
`bl` : |

### camel_block_file_attach_block ()

    void                camel_block_file_attach_block       (CamelBlockFile *bs,
                                                             CamelBlock *bl);

Reattach a block that has been detached.

`bs` : |
`bl` : |

### camel_block_file_touch_block ()

    void                camel_block_file_touch_block        (CamelBlockFile *bs,
                                                             CamelBlock *bl);

Mark a block as dirty. The block will be written to disk if it ever expires from the cache.

`bs` : |
`bl` : |

### camel_block_file_unref_block ()

    void                camel_block_file_unref_block        (CamelBlockFile *bs,
                                                             CamelBlock *bl);

Mark a block as unused. If a block is used it will not be written to disk, or flushed from memory.

If a block is detatched and this is the last reference, the block will be freed.

`bs` : |
`bl` : |

### camel_block_file_sync_block ()

    gint                camel_block_file_sync_block         (CamelBlockFile *bs,
                                                             CamelBlock *bl);

Flush a block to disk immediately. The block will only be flushed to disk if it is marked as dirty (touched).

`bs` : |
`bl` : |
Returns : | -1 on io error.

### camel_block_file_sync ()

    gint                camel_block_file_sync               (CamelBlockFile *bs);

Sync all dirty blocks to disk, including the root block.

`bs` : |
Returns : | -1 on io error.

### CamelKeyFile

    typedef struct {
    	CamelObject parent;

    	struct _CamelKeyFilePrivate *priv;

    	FILE *fp;
    	gchar *path;
    	gint flags;
    	off_t last;
    } CamelKeyFile;

### camel_key_file_new ()

    CamelKeyFile *      camel_key_file_new                  (const gchar *path,
                                                             gint flags,
                                                             const gchar version[8]);

Create a new key file. A linked list of record blocks.

`path` : |
`flags` : | open flags
`version` : | Version string (header) of file. Currently written but not checked.
Returns : | A new key file, or NULL if the file could not be opened/created/initialised.

### camel_key_file_rename ()

    gint                camel_key_file_rename               (CamelKeyFile *kf,
                                                             const gchar *path);

`kf` : |
`path` : |
Returns : |

### camel_key_file_delete ()

    gint                camel_key_file_delete               (CamelKeyFile *kf);

`kf` : |
Returns : |

### camel_key_file_write ()

    gint                camel_key_file_write                (CamelKeyFile *kf,
                                                             camel_block_t *parent,
                                                             gsize len,
                                                             camel_key_t *records);

Write a new list of records to the key file.

`kf` : |
`parent` : |
`len` : |
`records` : |
Returns : | -1 on io error. The key file will remain unchanged.

### camel_key_file_read ()

    gint                camel_key_file_read                 (CamelKeyFile *kf,
                                                             camel_block_t *start,
                                                             gsize *len,
                                                             camel_key_t **records);

Read the next block of data from the key file. Returns the number of records.

`kf` : |
`start` : | The record pointer. This will be set to the next record pointer on success.
`len` : | Number of records read, if != NULL.
`records` : | Records, allocated, must be freed with g_free, if != NULL.
Returns : | -1 on io error.