Created
February 16, 2012 14:15
-
-
Save CAFxX/1845141 to your computer and use it in GitHub Desktop.
filemap
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
#include <sys/mman.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <string.h> | |
#define CHECK(err, cond) { if (cond) return err; } | |
#define CHECK_RES(res) { int RES = res; CHECK(RES, RES != FILEMAP_OK); } | |
#define CHECK_HANDLE(m) { CHECK_RES(__filemap_check_handle(m)); } | |
#define OK() { return FILEMAP_OK; } | |
#define __(M, body) { CHECK_HANDLE(M); { body } OK(); } | |
typedef struct { | |
void *m; | |
off_t m_size; | |
int f; | |
off_t f_size; | |
} filemap; | |
typedef unsigned char byte; | |
enum filemap_errors { | |
FILEMAP_OK = 0, | |
FILEMAP_ERROR_FILE_OPEN, | |
FILEMAP_ERROR_MMAP, | |
FILEMAP_ERROR_INVALID_HANDLE, | |
FILEMAP_ERROR_MUNMAP, | |
FILEMAP_ERROR_FILE_SEEK, | |
FILEMAP_ERROR_FILE_RESIZE, | |
FILEMAP_ERROR_MSYNC | |
}; | |
static int __filemap_check_handle(filemap *m) { | |
CHECK(FILEMAP_ERROR_INVALID_HANDLE, m == NULL); | |
OK(); | |
} | |
static int __filemap_init(filemap *m) {__(m, | |
m->m = NULL; | |
m->m_size = 0; | |
m->f = -1; | |
m->f_size = 0; | |
)} | |
filemap filemap_handle() { | |
filemap m; | |
__filemap_init(&m); | |
return m; | |
} | |
int filemap_sync_ex(filemap *m, off_t offset, off_t length, int async) {__(m, | |
byte *addr = (byte*)(m->m) + offset; | |
int flags = async ? MS_ASYNC : MS_SYNC; | |
CHECK(FILEMAP_ERROR_MSYNC, msync(addr, length, flags) != 0); | |
)} | |
int filemap_sync(filemap *m) {__(m, | |
CHECK(FILEMAP_OK, m->m_size == 0); | |
return filemap_sync_ex(m, 0, m->m_size, 0); | |
)} | |
int filemap_async(filemap *m) {__(m, | |
CHECK(FILEMAP_OK, m->m_size == 0); | |
return filemap_sync_ex(m, 0, m->m_size, 1); | |
)} | |
static int __filemap_mmap(filemap *m) {__(m, | |
m->m = mmap(m->m, m->f_size, PROT_READ|PROT_WRITE, MAP_SHARED, m->f, 0); | |
CHECK(FILEMAP_ERROR_MMAP, m->m == MAP_FAILED && m->f_size > 0); | |
m->m_size = m->f_size; | |
)} | |
static int __filemap_munmap(filemap *m) {__(m, | |
CHECK(FILEMAP_OK, m->m_size == 0); | |
CHECK_RES(filemap_async(m)); | |
CHECK(FILEMAP_ERROR_MUNMAP, munmap(m->m, m->m_size)); | |
m->m_size = 0; | |
)} | |
int filemap_open(filemap *m, char *filename) {__(m, | |
CHECK_RES(__filemap_init(m)); | |
CHECK(FILEMAP_ERROR_FILE_OPEN, (m->f = open(filename, O_RDWR|O_CREAT, S_IRWXU)) < 0); | |
CHECK(FILEMAP_ERROR_FILE_SEEK, (m->f_size = lseek(m->f, 0, SEEK_END)) == (off_t)-1); | |
CHECK_RES(__filemap_mmap(m)); | |
fprintf(stderr, "%s %5d %p-%p %12ld bytes\n", "M", m->f, m->m, (byte*)(m->m)+m->m_size-1, m->f_size); | |
)} | |
int filemap_close(filemap *m) {__(m, | |
__filemap_munmap(m); | |
close(m->f); | |
)} | |
int filemap_resize(filemap *m, off_t size) {__(m, | |
CHECK(FILEMAP_OK, size == m->m_size); | |
CHECK_RES(__filemap_munmap(m)); | |
CHECK(FILEMAP_ERROR_FILE_RESIZE, ftruncate(m->f, size) != 0); | |
m->f_size = size; | |
CHECK_RES(__filemap_mmap(m)); | |
fprintf(stderr, "%s %5d %p-%p %12ld bytes\n", "R", m->f, m->m, (byte*)(m->m)+m->m_size-1, m->f_size); | |
)} | |
inline void* filemap_access(filemap *m, off_t start, off_t end) { | |
CHECK(NULL, m == NULL || end > m->m_size || start >= end); | |
return (byte*)(m->m) + start; | |
} | |
int main() { | |
int i, j=4, k; | |
filemap _m, *m = &_m; | |
CHECK_RES(filemap_open(m, "data.dat")); | |
srand(time(0)); | |
for (i=0; i<50; i++) { | |
CHECK_RES(filemap_resize(m, j+=1<<(i/2))); | |
for (k=0; k<j-sizeof(int); k++) | |
*(byte*)filemap_access(m, k, k+sizeof(int)) = rand(); | |
filemap_sync(m); | |
} | |
CHECK_RES(filemap_close(m)); | |
return 0; | |
} | |
/* | |
Filemap m("data.dat"); | |
Filemap m("data.dat", 1<<24); | |
m.resize(1<<20); | |
T* p = m.ptr<T>(offset); | |
m.sync(); | |
m.close(); | |
*/ | |
#ifdef __cplusplus | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment