Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
406 lines (353 sloc) 14.5 KB
#pragma once
#ifndef IWFSMFILE_H
#define IWFSMFILE_H
/**************************************************************************************************
* IOWOW library
*
* MIT License
*
* Copyright (c) 2012-2019 Softmotions Ltd <info@softmotions.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*************************************************************************************************/
/** @file
* @brief Auto-expandable file with support of reader/writer address space
locking and free space block management using bitmaps.
* @author Anton Adamansky (adamansky@softmotions.com)
*
* @note Before using API of this module you should call
* `iw_init(void)` iowow module initialization routine.
*
* <strong>Features:</strong>
*
* - Address blocks allocation and deallocation using bitmaps.
* - Read/write file address space locking.
* - Tunable file expansion policies.
* - Read/write methods locking option in multithreaded environment.
* - File shrinking/truncation support.
* - A number mmaped regions can be registered in the file's address space.
* These regions used in read/write operation and automatically maintained
* during file resize operations.
*
* File operations implemented as function pointers contained
* in `IWFS_FSM` `C` structure.
* The `iwfs_fsmfile_open(IWFS_FSM *f, const IWFS_FSM_OPTS *opts)` opens file
* and initializes a given `IWFS_FSM` structure.
*
* <strong>File format:</strong>
* @verbatim
[FSM_CTL_MAGICK u32][block pow u8]
[bmoffset u64][bmlength u64]
[crzsum u64][crznum u32][crszvar u64][reserved u256]
[custom header size u32][custom header data...]
[fsm data...] @endverbatim
*
* <strong>where:</strong>
*
* - <b>FSM_CTL_MAGICK:</b> Free-space file magic number (32 bit)
* - <b>block pow:</b> Block size as power of `2` Eg: `6` means `64` bit block
size. (8 bit)
* - <b>bmoffset:</b> Free space bitmap area offset in bytes (64 bit)
* - <b>bmlength:</b> Free space bitmap area length. (64 bit)
* - <b>crzsum:</b> Number of allocated blocks. (64 bit)
* - <b>crznum:</b> Number of all allocated continuous areas. (32 bit)
* - <b>crszvar</b> Allocated areas length standard variance (deviation^2 * N) (64 bit)
* - <b>reserved:</b> Reserved space.
* - <b>custom header size:</b> Length of custom header area. See
`IWFS_FSM::writehdr` and `IWFS_FSM::readhdr`
*/
#include "iwexfile.h"
#include <stdbool.h>
#include <math.h>
IW_EXTERN_C_START
/** Free space allocation flags
* @see IWFS_FSM::allocate
*/
typedef uint8_t iwfs_fsm_aflags;
/** Use default allocation settings */
#define IWFSM_ALLOC_DEFAULTS ((iwfs_fsm_aflags) 0x00U)
/** Do not @em overallocate a requested free space in order to reduce fragmentation */
#define IWFSM_ALLOC_NO_OVERALLOCATE ((iwfs_fsm_aflags) 0x01U)
/** Do not extend the file and its bitmap free space mapping in the case if
* file size expansion is required.
* In this case the `IWFS_ERROR_NO_FREE_SPACE` error will be raised.*/
#define IWFSM_ALLOC_NO_EXTEND ((iwfs_fsm_aflags) 0x02U)
/** Force offset of an allocated space to be page aligned. */
#define IWFSM_ALLOC_PAGE_ALIGNED ((iwfs_fsm_aflags) 0x04U)
/** Do not collect internal allocation stats for this allocation. */
#define IWFSM_ALLOC_NO_STATS ((iwfs_fsm_aflags) 0x08U)
/** Force all of the allocated address space backed by real file address space. */
#define IWFSM_SOLID_ALLOCATED_SPACE ((iwfs_fsm_aflags) 0x10U)
/** Do msync of bitmap allocation index. */
#define IWFSM_SYNC_BMAP ((iwfs_fsm_aflags) 0x20U)
#define IWFSM_MAGICK 0x19cc7cc
#define IWFSM_CUSTOM_HDR_DATA_OFFSET \
(4 /*magic*/ + 1 /*block pow*/ + 8 /*fsm bitmap block offset */ + 8 /*fsm bitmap block length*/ + \
8 /*all allocated block length sum */ + 4 /*number of all allocated areas */ + \
8 /* allocated areas length standard variance (deviation^2 * N) */ + 32 /*reserved*/ + \
4 /*custom hdr size*/)
/** File cleanup flags used in `IWFS_FSM::clear` */
typedef uint8_t iwfs_fsm_clrfalgs;
/** Perform file size trimming after cleanup */
#define IWFSM_CLEAR_TRIM ((iwfs_fsm_clrfalgs) 0x01U)
/** `IWFS_FSM` file open modes used in `IWFS_FSM_OPTS` */
typedef uint8_t iwfs_fsm_openflags;
/** Do not use threading locks */
#define IWFSM_NOLOCKS ((iwfs_fsm_openflags) 0x01U)
/** Strict block checking for alloc/dealloc operations. 10-15% performance overhead. */
#define IWFSM_STRICT ((iwfs_fsm_openflags) 0x02U)
/**
* @brief Error codes specific to `IWFS_FSM`.
*/
typedef enum {
_IWFS_FSM_ERROR_START = (IW_ERROR_START + 4000UL),
IWFS_ERROR_NO_FREE_SPACE, /**< No free space. */
IWFS_ERROR_INVALID_BLOCK_SIZE, /**< Invalid block size specified */
IWFS_ERROR_RANGE_NOT_ALIGNED, /**< Specified range/offset is not aligned with
page/block */
IWFS_ERROR_FSM_SEGMENTATION, /**< Free-space map segmentation error */
IWFS_ERROR_INVALID_FILEMETA, /**< Invalid file-metadata */
IWFS_ERROR_PLATFORM_PAGE, /**< Platform page size incopatibility, data
migration required. */
IWFS_ERROR_RESIZE_FAIL, /**< Failed to resize file */
_IWFS_FSM_ERROR_END
} iwfs_fsm_ecode;
/**
* @brief `IWFS_FSM` file options.
* @see iwfs_fsmfile_open(IWFS_FSM *f, const IWFS_FSM_OPTS *opts)
*/
typedef struct IWFS_FSM_OPTS {
IWFS_EXT_OPTS exfile;
size_t bmlen; /**< Initial size of free-space bitmap */
uint32_t hdrlen; /**< Length of custom file header.*/
iwfs_fsm_openflags oflags; /**< Operation mode flags */
iwfs_ext_mmap_opts_t mmap_opts; /**< Defaul mmap options used in `add_mmap` */
uint8_t bpow; /**< Block size power for 2 */
bool mmap_all; /**< Mmap all file data */
} IWFS_FSM_OPTS;
/**
* @brief `IWFS_FSM` file state container.
* @see IWFS_FSM::state
*/
typedef struct IWFS_FSM_STATE {
IWFS_EXT_STATE exfile; /**< File pool state */
size_t block_size; /**< Size of data block in bytes. */
iwfs_fsm_openflags oflags; /**< Operation mode flags. */
uint32_t hdrlen; /**< Length of custom file header length in bytes */
uint64_t blocks_num; /**< Number of available data blocks. */
uint64_t free_segments_num; /**< Number of free (deallocated) continuous data
segments. */
double_t avg_alloc_size; /**< Average allocation number of blocks */
double_t alloc_dispersion; /**< Average allocation blocks dispersion */
} IWFS_FSM_STATE;
typedef struct IWFS_FSMDBG_STATE {
IWFS_FSM_STATE state;
uint64_t bmoff;
uint64_t bmlen;
uint64_t lfbklen;
uint64_t lfbkoff;
} IWFS_FSMDBG_STATE;
/**
* @brief Auto-expandable file with support of reader/writer address space
* locking
* and free space blocks management using bitmaps.
*/
typedef struct IWFS_FSM {
struct IWFS_FSM_IMPL *impl;
/**
* @brief Allocate a continuous address space within a file
* with length greater or equal to the desired @a len bytes.
*
* `Offset` and `length` allocated area will be block size aligned.
*
* @param f `IWFS_FSM` file.
* @param len Desired length of an allocated area in bytes.
* @param [in,out] oaddr Placeholder for the address of an allocated area.
* Value of @a oaddr passed to this function used as
* `hint` in order
* to allocate area located closely to the specified @a
* oaddr value.
* @param [out] olen Actual length of an allocated area in bytes.
* @param opts Allocation options bitmask flag @ref iwfs_fsm_aflags
* @return `0` on success or error code.
*/
iwrc(*allocate)(struct IWFS_FSM *f, off_t len, off_t *oaddr, off_t *olen,
iwfs_fsm_aflags opts);
/**
* @brief Reallocate and adjust a size of an allocated block.
*
* If the given @a nlen value lesser than actual length of segment @a olen in
* that case
* segment will be truncated.
*
* @param f `IWFS_FSM` file.
* @param nlen Desired length of segment in bytes.
* @param oaddr [in,out] Address of an allocated segment. Placeholder for new
* address of reallocated segment.
* @param olen [in,out] Length of an allocated segment. Placeholder for length
* of reallocated segment.
* @param opts Allocation options bitmask flag @ref iwfs_fsm_aflags
* @return `0` on success or error code.
*/
iwrc(*reallocate)(struct IWFS_FSM *f, off_t nlen, off_t *oaddr, off_t *olen,
iwfs_fsm_aflags opts);
/**
* @brief Free a previously allocated area.
* @param addr Address space offset in bytes <em>it must be block size
* aligned</em>.
* @param len Length of area to release.
* @return `0` on success or error code.
*/
iwrc(*deallocate)(struct IWFS_FSM *f, off_t addr, off_t len);
/**
* @brief Check allocation status of region specified by @a addr and @a len
* @return `0` on success or error code.
*/
iwrc(*check_allocation_status)(struct IWFS_FSM *f, off_t addr, off_t len, bool allocated);
/**
* @brief Write a data to the custom file header.
*
* A custom file header size specified in IWFS_FSM_OPTS::hdrlen options on
* file creation.
*
* @param off Offset position relative to custom header start offset.
* @param buf Data buffer to write
* @param siz Number of bytes of @a buf to write into header.
* @return `0` on success or error code.
*/
iwrc(*writehdr)(struct IWFS_FSM *f, off_t off, const void *buf, off_t siz);
/**
* @brief Read a data from the custom file header.
*
* A custom file header size specified in IWFS_FSM_OPTS::hdrlen options on
* file creation.
*
* @param off Offset position relative to custom header start offset.
* @param [out] buf Data buffer to read into
* @param Number of bytes to read
*/
iwrc(*readhdr)(struct IWFS_FSM *f, off_t off, void *buf, off_t siz);
/**
* @brief Cleanup all allocated data blocks and reset the file to the initial
* empty state.
*
* @param clrflags
* @return `0` on success or error code.
*/
iwrc(*clear)(struct IWFS_FSM *f, iwfs_fsm_clrfalgs clrflags);
/* See iwexfile.h */
/** @see IWFS_EXT::ensure_size */
iwrc(*ensure_size)(struct IWFS_FSM *f, off_t size);
/** @see IWFS_EXT::add_mmap */
iwrc(*add_mmap)(struct IWFS_FSM *f, off_t off, size_t maxlen, iwfs_ext_mmap_opts_t opts);
/** @see IWFS_EXT::remap_all */
iwrc(*remap_all)(struct IWFS_FSM *f);
/**
* @brief Get a pointer to the registered mmap area starting at `off`.
*
* WARNING: Internal read lock will be acquired and
* must be released by subsequent `release_mmap()` call
* after all activity with mmaped region has finished.
*
* @see IWFS_FSM::add_mmap
* @see IWFS_EXT::acquire_mmap
*/
iwrc(*acquire_mmap)(struct IWFS_FSM *f, off_t off, uint8_t **mm, size_t *sp);
/**
* @brief Retrieve mmaped region by its offset @a off
*/
iwrc(*probe_mmap)(struct IWFS_FSM *f, off_t off, uint8_t **mm, size_t *sp);
/**
* @brief Release the lock acquired by successfull call of `acquire_mmap()`
*/
iwrc(*release_mmap)(struct IWFS_FSM *f);
/** @see IWFS_EXT::remove_mmap */
iwrc(*remove_mmap)(struct IWFS_FSM *f, off_t off);
/** @see IWFS_EXT::sync_mmap */
iwrc(*sync_mmap)(struct IWFS_FSM *f, off_t off, iwfs_sync_flags flags);
/* See iwfile.h */
/** @see IWFS_FILE::write */
iwrc(*write)(struct IWFS_FSM *f, off_t off, const void *buf, size_t siz,
size_t *sp);
/** @see IWFS_FILE::read */
iwrc(*read)(struct IWFS_FSM *f, off_t off, void *buf, size_t siz,
size_t *sp);
/** @see IWFS_FILE::close */
iwrc(*close)(struct IWFS_FSM *f);
/** @see IWFS_FILE::sync */
iwrc(*sync)(struct IWFS_FSM *f, iwfs_sync_flags flags);
/** @see IWFS_FILE::state */
iwrc(*state)(struct IWFS_FSM *f, IWFS_FSM_STATE *state);
/** get access to the underlying iwextfile instance */
iwrc(*extfile)(struct IWFS_FSM *f, IWFS_EXT **ext);
} IWFS_FSM;
/**
* @brief Open `IWFS_FSM` file.
*
* <strong>Example:</strong>
*
* Open a buffer pool file for multithreaded env with fibonacci file resize
* policy with block size of 64 bytes and custom file header of 255 bytes
* length.
*
* @code {.c}
* IWFS_FSM_OPTS opts = {
* .exfile = {
* .file = {
* .path = "myfile.dat",
* .omode = IWFS_OWRITE | IWFS_OCREATE,
* .lock_mode = IWP_WLOCK
* },
* .rspolicy = iw_exfile_szpolicy_fibo
* },
* .bpow = 6, // 2^6 bytes block size
* .hdrlen = 255, // Size of custom file header
* .oflags = IWFSM_STRICT // Use verbose free-space bitmap checking for
* // allocations (10-15% overhead)
* };
*
* IWFS_FSM f;
* size_t sp;
* off_t space_len, space_addr = 0;
*
* iwrc rc = iwfs_fsmfile_open(&f, &opts);
*
* //Allocate 2 blocks of file space
* rc = f.allocate(&f, 128, &space_addr, &space_len, 0);
* if (!rc) {
* int data = 33;
* // Write some data to the allocated block with writer lock acquired on
* // `[space_addr, sizeof(data))`
* rc = f.lwrite(&f, space_addr, &data, sizeof(data), &sp);
* ...
* }
* ...
* @endcode
*
* @param f File handle
* @param opts File open options
* @relatesalso IWFS_FSM
*/
IW_EXPORT WUR iwrc iwfs_fsmfile_open(IWFS_FSM *f, const IWFS_FSM_OPTS *opts);
/**
* @brief Init `iwfsmfile` submodule.
*/
IW_EXPORT WUR iwrc iwfs_fsmfile_init(void);
IW_EXTERN_C_END
#endif
You can’t perform that action at this time.