Cache::FastMmap::WithWin32

Win32でCatalystを触っていた人にはおそらく待望のCache::FastMmapのWin32対応版。なんで素直にC::FMの名前で出なかったかというのはFastMmap.pmに書いてある通りですね。移植が済んでから半年近くも待たされた挙げ句、新しい版(1.15〜1.16)には移植版を含めてくれなかったってんですからブチ切れたくなる気持ちもよくわかるというものです。

This module is a fork of Cache::FastMmap by Rob Mueller to include the Win32
port by Ash Berlin, cos i got fed up waiting for Rob to release it.

で、さっそく手元の5.8.7で試したところ、VC6ではコンパイルエラー、gccではコンパイルこそ通るものの、途中ひとつテストがこけるという状態だったのですが、メールしておいたらさっそく対処してくれました。この追記を書いている21日6:30時点ではまだリリースされていませんが、次の版では問題なく通るはずです。

というわけで、以下は記録として残しておきますが、すでに過去の話です。


まずはVC6でコンパイルを通すためのパッチをば。

diff -ur Cache-FastMmap-WithWin32-1.16.1/Cache-FastMmap-CImpl/CImpl.xs Cache-FastMmap-WithWin32-1.16.1-patched/Cache-FastMmap-CImpl/CImpl.xs
--- Cache-FastMmap-WithWin32-1.16.1/Cache-FastMmap-CImpl/CImpl.xs	2007-05-20 06:34:13.000000000 +0900
+++ Cache-FastMmap-WithWin32-1.16.1-patched/Cache-FastMmap-CImpl/CImpl.xs	2007-05-21 01:52:10.694875000 +0900
@@ -55,12 +55,12 @@
     if (!strcmp(param, "share_file")) {
       RETVAL = newSVpv( (char*)mmc_get_param(cache, param), 0);
     } else {
-      RETVAL = mmc_get_param(cache, param);
+      RETVAL = (SV*)mmc_get_param(cache, param); // VC complains due to type mismatch
     }
   OUTPUT:
     RETVAL
   POSTCALL:
-    if (RETVAL == -1) {
+    if ((int)RETVAL == -1) {   // VC complains due to type mismatch
       croak(mmc_error(cache));
     }
 
@@ -422,6 +422,7 @@
     int wb;
     int len;
   INIT:
+    SV * val;
     mmap_cache * cache;
     MU32 new_num_slots = 0, ** to_expunge = 0;
     int num_expunge, item;
@@ -467,7 +468,6 @@
             flags ^= FC_UTF8KEY;
           }
 
-          SV * val;
           if (flags & FC_UNDEF) {
             val = newSV(0);
             flags ^= FC_UNDEF;
diff -ur Cache-FastMmap-WithWin32-1.16.1/Cache-FastMmap-CImpl/mmap_cache.c Cache-FastMmap-WithWin32-1.16.1-patched/Cache-FastMmap-CImpl/mmap_cache.c
--- Cache-FastMmap-WithWin32-1.16.1/Cache-FastMmap-CImpl/mmap_cache.c	2007-05-20 06:16:18.000000000 +0900
+++ Cache-FastMmap-WithWin32-1.16.1-patched/Cache-FastMmap-CImpl/mmap_cache.c	2007-05-21 01:42:45.179250000 +0900
@@ -24,7 +24,12 @@
 #include <errno.h>
 #include <stdarg.h>
 #include <time.h>
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include <io.h>
+#include <process.h>
+#endif
 #include "mmap_cache.h"
 #include "mmap_cache_internals.h"
 
diff -ur Cache-FastMmap-WithWin32-1.16.1/Cache-FastMmap-CImpl/win32.c Cache-FastMmap-WithWin32-1.16.1-patched/Cache-FastMmap-CImpl/win32.c
--- Cache-FastMmap-WithWin32-1.16.1/Cache-FastMmap-CImpl/win32.c	2007-05-07 23:43:09.000000000 +0900
+++ Cache-FastMmap-WithWin32-1.16.1-patched/Cache-FastMmap-CImpl/win32.c	2007-05-21 01:49:43.476125000 +0900
@@ -198,6 +198,8 @@
     
     /* Set to bad value while page not locked */
     cache->p_cur = ~0; /* ~0 = -1, but unsigned */
+
+    return 0; // needs to return value
 }
 

このパッチをあてても、うちの環境ではかなり高い確率でVC版、gcc版ともt/11.tがこける(「Truncate of existing share file c:\tmp\sharefile-****-********** failed: プロセスはファイルにアクセスできません。別のプロセスが使用中です」というエラーが出る)んですが、なぜかこんな風に途中でウェイトをかましてやるとすんなり通る。

diff -ur Cache-FastMmap-WithWin32-1.16.1/t/11.t Cache-FastMmap-WithWin32-1.16.1-patched/t/11.t
--- Cache-FastMmap-WithWin32-1.16.1/t/11.t	2007-05-08 16:18:10.000000000 +0900
+++ Cache-FastMmap-WithWin32-1.16.1-patched/t/11.t	2007-05-21 02:08:39.726125000 +0900
@@ -23,6 +23,7 @@
   write_action => 'write_back',
   @_
 );
+sleep 1;
 return $FC;
 }
 
@@ -43,4 +44,3 @@
 $V = eval { $FC->get("foo"); };
 ok(!$@, "recurse success 1");
 is($V, "bar", "recurse success 2");
-

いや、なぜかというほどのことはなく、このテスト、たまたまUnixではファイルを開きっぱなしでもtruncateしたりできるから通っちゃうだけで、期待通りの動作をしていないからそんなことになっているんですが(秒が変わるとsharefileも変わるのでWin環境でも正しく動作しているように見えてしまう、と)、中身をきちんと追いかける余裕はないのでとりあえず放置。コールバックまわりを直して $FC = undef; したときにきちんとデストラクタが呼ばれるようにすればいいだけの話(のはず)なんですけれどね。

上のパッチについてはあとでRTの方に投げておきます(どうもいまうまくつながらないので)。