Lux IO msvc9移植版

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;
}

flockRubyの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