http://storehouse.sakura.ne.jp/viewvc/viewvc.cgi/luxio/?root=svn
動くは動いたけど、ロックまわりは怪しいかも。
//#include <luxio/btree.h> #include "btree.h" #include <iostream> //#define NUM_RECORDS 1000000 #define NUM_RECORDS 100 int main(void) { Lux::IO::Btree *bt = new Lux::IO::Btree(Lux::IO::CLUSTER); //bt->open("test", Lux::DB_CREAT); bt->open("test", Lux::DB_CREAT | Lux::DB_TRUNC); char str[9]; for (int i = 0; i < NUM_RECORDS; ++i) { sprintf(str, "%08d", i); Lux::IO::data_t key = {str, strlen(str)}; Lux::IO::data_t val = {&i, sizeof(int)}; bt->put(&key, &val); // insert operation } for (int i = 0; i < NUM_RECORDS; ++i) { sprintf(str, "%08d", i); Lux::IO::data_t *val = bt->get(str, strlen(str)); std::cout << *reinterpret_cast<const int *>(val->data) << "\n"; } bt->close(); delete bt; return 0; }
flockはRubyのwin32.cを参考にした。
stdint.hは株式会社きじねこが公開しているモノ。
CodeReposに上げようかな…。
以下、パッチ。
Index: data.h =================================================================== --- data.h (revision 2369) +++ data.h (revision 2388) @@ -91,7 +91,7 @@ { // calculate each 2^i (1<=i<=32) in advance for (int i = 0; i < 32; ++i) { - pows_[i] = pow(2, i+1); + pows_[i] = pow((double) 2, i+1); } } @@ -120,7 +120,11 @@ memset(&dh, 0, sizeof(db_header_t)); if (stat_buf.st_size == 0 && oflags & DB_CREAT) { dh.num_blocks = 0; +#ifndef _WIN32 dh.block_size = (block_size_ == 0) ? stat_buf.st_blksize : block_size_; +#else + dh.block_size = WIN32_ST_BLOCKSIZE; +#endif dh.cur_block_id = 0; dh.pmode = pmode_; dh.padding = padding_; @@ -197,7 +201,11 @@ for (int i = 0; i < 32; ++i) { if (!dh_->is_pool_empty[i]) { free_pool_ptr_t pool_ptr = dh_->first_pool_ptr[i]; +#ifndef _WIN32 std::cout << "free pool size: " << pow(2, i+1) << std::endl; +#else + std::cout << "free pool size: " << pow((double) 2, i+1) << std::endl; +#endif while (1) { off_t off = calc_off(pool_ptr.id, pool_ptr.off); @@ -249,6 +257,9 @@ int fd_; db_flags_t oflags_; char *map_; +#ifdef _WIN32 + HANDLE h_map_; +#endif db_header_t *dh_; padding_mode_t pmode_; uint32_t padding_; @@ -453,7 +464,11 @@ return NULL; } } else { +#ifndef _WIN32 div_t d = div(size, dh_->block_size); +#else + div_t d = div((int) size, (int) dh_->block_size); +#endif uint32_t num_blocks = d.rem > 0 ? d.quot + 1 : d.quot; if (!extend_blocks(num_blocks)) { return NULL; } Index: win32/flock.c =================================================================== --- win32/flock.c (revision 0) +++ win32/flock.c (revision 2388) @@ -0,0 +1,25 @@ +#include <windows.h> +#include <io.h> + +#include "flock.h" + +int win32_flock(int fd, int operation) { + HANDLE h = (HANDLE) _get_osfhandle(fd); + BOOL r = 0; + + switch(operation) { + case LOCK_SH: + r = LockFileEx(h, 0, 0, ULONG_MAX, ULONG_MAX, 0); + break; + + case LOCK_EX: + r = LockFileEx(h, LOCKFILE_EXCLUSIVE_LOCK, 0, ULONG_MAX, ULONG_MAX, 0); + break; + + case LOCK_UN: + r = UnlockFileEx(h, 0, ULONG_MAX, ULONG_MAX, 0); + break; + } + + return (r != 0) ? 0 : -1; +} Index: win32/flock.h =================================================================== --- win32/flock.h (revision 0) +++ win32/flock.h (revision 2388) @@ -0,0 +1,15 @@ +#define LOCK_SH 0x01 +#define LOCK_EX 0x02 +#define LOCK_UN 0x04 + +#define flock(fd, operation) win32_flock((fd), (operation)) + +#ifdef __cplusplus +extern "C" { +#endif + +int win32_flock(int fd, int operation); + +#ifdef __cplusplus +} +#endif Index: win32/mman.c =================================================================== --- win32/mman.c (revision 0) +++ win32/mman.c (revision 2388) @@ -0,0 +1,30 @@ +#include <windows.h> +#include <stddef.h> +#include <sys/types.h> +#include <io.h> + +#include "mman.h" + +void *win32_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset, HANDLE *h) { + void *p; + DWORD flProtect = PAGE_READONLY; + DWORD dwDesiredAccess = FILE_MAP_READ; + + if (prot & PROT_WRITE) { + flProtect = PAGE_READWRITE; + dwDesiredAccess |= FILE_MAP_WRITE; + } + + *h = CreateFileMappingA((HANDLE) _get_osfhandle(fd), NULL, flProtect, 0, length, NULL); + p = MapViewOfFile(*h, dwDesiredAccess, 0, offset, 0); + + return p; +} + +int win32_munmap(void *addr, size_t length, HANDLE *h) { + return ((UnmapViewOfFile(addr) & CloseHandle(*h)) != 0) ? 0 : -1; +} + +int win32_msync(void *addr, size_t length, int flags) { + return (FlushViewOfFile(addr, length) != 0) ? 0 : -1; +} Index: win32/mman.h =================================================================== --- win32/mman.h (revision 0) +++ win32/mman.h (revision 2388) @@ -0,0 +1,25 @@ +#include <stddef.h> +#include <sys/types.h> + +#define PROT_READ 0x01 +#define PROT_WRITE 0x02 + +#define MAP_SHARED 0 +#define MAP_FAILED 0 + +#define MS_SYNC 0 + +#define munmap(addr, length) win32_munmap((addr), (length), &h_map_) +#define msync(addr, length, flags) win32_msync((addr), (length), (flags)) + +#ifdef __cplusplus +extern "C" { +#endif + +void *win32_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset, HANDLE *h); +int win32_munmap(void *addr, size_t length, HANDLE *h); +int win32_msync(void *addr, size_t length, int flags); + +#ifdef __cplusplus +} +#endif Index: util.h =================================================================== --- util.h (revision 2369) +++ util.h (revision 2388) @@ -4,11 +4,19 @@ #include "types.h" #include <sys/stat.h> #include <fcntl.h> +#ifndef _WIN32 #include <sys/mman.h> +#else +#include "mman.h" +#endif #include <errno.h> #include <string> #include <iostream> +#ifdef _WIN32 +#include <direct.h> +#endif + #ifdef DEBUG #define error_log(msg) \ std::cerr << "[error] " << msg \ @@ -40,7 +48,11 @@ } std::string dir = str_.substr(0, n); // [TODO] error handling +#ifndef _WIN32 ::mkdir(dir.c_str(), 0755); +#else + ::mkdir(dir.c_str()); +#endif } } @@ -58,6 +70,11 @@ if (flags & DB_TRUNC) { oflags |= O_TRUNC; } + +#ifdef _WIN32 + oflags |= O_BINARY; +#endif + return ::open(pathname, oflags, mode); } @@ -129,14 +146,23 @@ // [TODO] pread } +#ifndef _WIN32 void *_mmap(int fd, size_t size, int flags) +#else + void *_win32_mmap(int fd, size_t size, int flags, HANDLE *h) +#endif { int prot = PROT_READ; if (flags & DB_RDWR || flags & DB_CREAT) { prot |= PROT_WRITE; } +#ifndef _WIN32 void *p = mmap(0, size, prot, MAP_SHARED, fd, 0); +#else + void *p = win32_mmap(0, size, prot, MAP_SHARED, fd, 0, h); +#endif + if (p == MAP_FAILED) { return NULL; } @@ -145,4 +171,7 @@ } +#ifdef _WIN32 +#define _mmap(fd, size, flags) _win32_mmap((fd), (size), (flags), &h_map_) #endif +#endif Index: array.h =================================================================== --- array.h (revision 2369) +++ array.h (revision 2388) @@ -290,6 +290,9 @@ int fd_; db_flags_t oflags_; char *map_; +#ifdef _WIN32 + HANDLE h_map_; +#endif array_header_t *dh_; db_index_t index_type_; uint8_t data_size_; Index: btree.h =================================================================== --- btree.h (revision 2369) +++ btree.h (revision 2388) @@ -24,10 +24,22 @@ #include <pthread.h> #endif +#ifdef _WIN32 +#include <malloc.h> +#include "flock.h" +#endif + +#ifndef _WIN32 #define ALLOC_AND_COPY(s1, s2, size) \ char s1[size+1]; \ memcpy(s1, s2, size); \ s1[size] = '\0'; +#else +#define ALLOC_AND_COPY(s1, s2, size) \ + char *s1 = reinterpret_cast<char *>(_alloca(size+1)); \ + memcpy(s1, s2, size); \ + s1[size] = '\0'; +#endif namespace Lux { namespace IO { @@ -269,7 +281,11 @@ if (!wlock_db()) { return false; } uint32_t val_size = v->size + sizeof(uint8_t); +#ifndef _WIN32 char data[val_size]; +#else + char *data = reinterpret_cast<char *>(_alloca(val_size)); +#endif data_t val = {data, val_size}; // for size prepended uint32_t entry_size = k->size; if (dh_->index_type == CLUSTER) { @@ -535,6 +551,9 @@ int fd_; db_flags_t oflags_; char *map_; +#ifdef _WIN32 + HANDLE h_map_; +#endif btree_header_t *dh_; db_index_t index_type_; uint32_t page_size_; @@ -1079,7 +1098,11 @@ // [TODO] API should be changed ? : take data_t instead of key and key_size data_t k = {key, key_size}; +#ifndef _WIN32 char checked[node->h->num_keys]; +#else + char *checked = reinterpret_cast<char *>(_alloca(node->h->num_keys)); +#endif memset(checked, 0, node->h->num_keys); // binary search @@ -1230,7 +1253,11 @@ new_node->h->prev_id = node->h->id; // copy staying entries into the buffers +#ifndef _WIN32 char tmp_node[dh_->node_size]; +#else + char *tmp_node = reinterpret_cast<char *>(_alloca(dh_->node_size)); +#endif node_t n; node_t *np = &n; np->b = (node_body_t *) (tmp_node + sizeof(node_header_t)); Index: dbm.h =================================================================== --- dbm.h (revision 2369) +++ dbm.h (revision 2388) @@ -24,12 +24,20 @@ #include "config.h" #include "types.h" #include "util.h" +#ifndef _WIN32 #include <unistd.h> +#endif #include <stdint.h> +#ifndef _WIN32 #include <sys/file.h> +#endif #include <fcntl.h> #include <sys/stat.h> +#ifndef _WIN32 #include <sys/mman.h> +#else +#include "mman.h" +#endif #include <errno.h> #include <string.h> #include <stdlib.h> Index: config.h =================================================================== --- config.h (revision 2369) +++ config.h (revision 2388) @@ -123,3 +123,20 @@ /* Define to `unsigned' if <sys/types.h> does not define. */ /* #undef size_t */ + +#ifdef _WIN32 +#include <windows.h> +#include <io.h> +#include <sys/stat.h> + +typedef SSIZE_T ssize_t; +typedef int mode_t; + +#define getpagesize() (4096) +#define ftruncate(fd, length) chsize((fd), (length)) +#define S_ISREG(m) (((m) & (_S_IFMT)) == (_S_IFREG)) + +#define WIN32_ST_BLOCKSIZE (512) + +#undef small +#endif