summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changes7
-rw-r--r--mmap.c217
-rw-r--r--mmap.rd2
-rw-r--r--tests/mmapt.rb17
4 files changed, 169 insertions, 74 deletions
diff --git a/Changes b/Changes
index 28e12e6..8da5335 100644
--- a/Changes
+++ b/Changes
@@ -30,3 +30,10 @@
* adapted for 1.7.2 (mm_str)
* corrected real for mm_sub_bang
* protected against old class
+
+-- 0.1.7
+
+* 1.7.2 (::allocate, #initialize)
+* added "a" for ::new
+* experimental EXP_INCR_SIZE (4096) ("increment" => 4096)
+* tests for RUNIT/Test::Unit
diff --git a/mmap.c b/mmap.c
index 6a68bcb..8b7f489 100644
--- a/mmap.c
+++ b/mmap.c
@@ -34,12 +34,14 @@
static VALUE mm_cMap;
+#define EXP_INCR_SIZE 4096
+
typedef struct {
MMAP_RETTYPE addr;
int smode, pmode, vscope;
int advice, frozen, lock;
size_t len, real;
- size_t size;
+ size_t size, incr;
off_t offset;
char *path;
} mm_mmap;
@@ -164,6 +166,79 @@ mm_to_str(obj)
extern char *ruby_strdup();
+static void
+mm_expandf(t_mm, len)
+ mm_mmap *t_mm;
+ long len;
+{
+ int fd;
+
+ if (t_mm->vscope == MAP_PRIVATE) {
+ rb_raise(rb_eTypeError, "expand for a private map");
+ }
+ if (t_mm->frozen & MM_FIXED) {
+ rb_raise(rb_eTypeError, "expand for a fixed map");
+ }
+ if (munmap(t_mm->addr, t_mm->len)) {
+ rb_raise(rb_eArgError, "munmap failed");
+ }
+ if ((fd = open(t_mm->path, t_mm->smode)) == -1) {
+ rb_raise(rb_eArgError, "Can't open %s", t_mm->path);
+ }
+ if (len > t_mm->len) {
+ if (lseek(fd, len - t_mm->len - 1, SEEK_END) == -1) {
+ rb_raise(rb_eIOError, "Can't lseek %d", len - t_mm->len - 1);
+ }
+ if (write(fd, "\000", 1) != 1) {
+ rb_raise(rb_eIOError, "Can't extend %s", t_mm->path);
+ }
+ }
+ else if (len < t_mm->len && truncate(t_mm->path, len) == -1) {
+ rb_raise(rb_eIOError, "Can't truncate %s", t_mm->path);
+ }
+ t_mm->addr = mmap(0, len, t_mm->pmode, t_mm->vscope, fd, t_mm->offset);
+ close(fd);
+ if (t_mm->addr == MAP_FAILED) {
+ rb_raise(rb_eArgError, "mmap failed");
+ }
+ if (t_mm->advice && madvise(t_mm->addr, len, t_mm->advice) == -1) {
+ rb_raise(rb_eArgError, "madvise(%d)", errno);
+ }
+ if (t_mm->lock && mlock(t_mm->addr, len) == -1) {
+ rb_raise(rb_eArgError, "mlock(%d)", errno);
+ }
+ t_mm->len = len;
+}
+
+static void
+mm_realloc(t_mm, len)
+ mm_mmap *t_mm;
+ long len;
+{
+ if (t_mm->frozen & MM_FROZEN) rb_error_frozen("mmap");
+ if (len > t_mm->len) {
+ if ((len - t_mm->len) < t_mm->incr) {
+ len = t_mm->len + t_mm->incr;
+ }
+ mm_expandf(t_mm, len);
+ }
+}
+
+static VALUE
+mm_extend(obj, a)
+ VALUE obj, a;
+{
+ mm_mmap *t_mm;
+ long len;
+
+ GetMmap(obj, t_mm, MM_MODIFY);
+ len = NUM2LONG(a);
+ if (len > 0) {
+ mm_expandf(t_mm, t_mm->len + len);
+ }
+ return INT2NUM(t_mm->len);
+}
+
static VALUE
mm_i_options(arg, obj)
VALUE arg, obj;
@@ -194,16 +269,42 @@ mm_i_options(arg, obj)
else if (strcmp(options, "advice") == 0) {
t_mm->advice = NUM2INT(value);
}
+ else if (strcmp(options, "increment") == 0) {
+ t_mm->incr = NUM2INT(value);
+ if (t_mm->incr < 0) {
+ rb_raise(rb_eArgError, "Invalid value for increment %d", t_mm->incr);
+ }
+ }
return Qnil;
}
+
+#if RUBY_VERSION_CODE >= 172
+static VALUE
+mm_s_alloc(argc, argv, obj)
+ int argc;
+ VALUE *argv, obj;
+{
+ VALUE res;
+ mm_mmap *t_mm;
+
+ res = Data_Make_Struct(obj, mm_mmap, 0, mm_free, t_mm);
+ t_mm->incr = EXP_INCR_SIZE;
+ return res;
+}
+#endif
+
static VALUE
+#if RUBY_VERSION_CODE >= 172
+mm_init(argc, argv, obj)
+#else
mm_s_new(argc, argv, obj)
+#endif
VALUE obj, *argv;
int argc;
{
struct stat st;
- int fd, smode, pmode, vscope;
+ int fd, smode, pmode, vscope, perm, init;
MMAP_RETTYPE addr;
VALUE res, fname, vmode, scope, options;
mm_mmap *t_mm;
@@ -237,7 +338,18 @@ mm_s_new(argc, argv, obj)
Check_SafeStr(fname);
path = RSTRING(fname)->ptr;
#endif
- mode = NIL_P(vmode) ? "r" : STR2CSTR(vmode);
+ perm = 0666;
+ if (NIL_P(vmode)) {
+ mode = "r";
+ }
+ else if (TYPE(vmode) == T_ARRAY && RARRAY(vmode)->len >= 2) {
+ VALUE tmp = RARRAY(vmode)->ptr[0];
+ mode = STR2CSTR(tmp);
+ perm = NUM2INT(RARRAY(vmode)->ptr[1]);
+ }
+ else {
+ mode = STR2CSTR(vmode);
+ }
if (strcmp(mode, "r") == 0) {
smode = O_RDONLY;
pmode = PROT_READ;
@@ -250,13 +362,17 @@ mm_s_new(argc, argv, obj)
smode = O_RDWR;
pmode = PROT_READ | PROT_WRITE;
}
+ else if (strcmp(mode, "a") == 0) {
+ smode = O_RDWR | O_CREAT;
+ pmode = PROT_READ | PROT_WRITE;
+ }
else {
rb_raise(rb_eArgError, "Invalid mode %s", mode);
}
vscope |= NIL_P(scope) ? MAP_SHARED : NUM2INT(scope);
size = 0;
if (path) {
- if ((fd = open(path, smode)) == -1) {
+ if ((fd = open(path, smode, perm)) == -1) {
rb_raise(rb_eArgError, "Can't open %s", path);
}
if (fstat(fd, &st) == -1) {
@@ -267,7 +383,13 @@ mm_s_new(argc, argv, obj)
else {
fd = -1;
}
+#if RUBY_VERSION_CODE >= 172
+ Data_Get_Struct(obj, mm_mmap, t_mm);
+ res = obj;
+#else
res = Data_Make_Struct(obj, mm_mmap, 0, mm_free, t_mm);
+ t_mm->incr = EXP_INCR_SIZE;
+#endif
offset = 0;
if (options != Qnil) {
rb_iterate(rb_each, options, mm_i_options, res);
@@ -278,6 +400,7 @@ mm_s_new(argc, argv, obj)
if (t_mm->size) size = t_mm->size;
offset = t_mm->offset;
}
+ init = 0;
if (!path) {
if (size <= 0) {
rb_raise(rb_eArgError, "length not specified for an anonymous map");
@@ -287,6 +410,16 @@ mm_s_new(argc, argv, obj)
offset = 0;
}
}
+ else if (size == 0 && (smode & O_RDWR)) {
+ if (lseek(fd, t_mm->incr - 1, SEEK_END) == -1) {
+ rb_raise(rb_eIOError, "Can't lseek %d", t_mm->incr - 1);
+ }
+ if (write(fd, "\000", 1) != 1) {
+ rb_raise(rb_eIOError, "Can't extend %s", path);
+ }
+ init = 1;
+ size = t_mm->incr;
+ }
addr = mmap(0, size, pmode, vscope, fd, offset);
if (fd != -1) close(fd);
if (addr == MAP_FAILED || !addr) {
@@ -296,7 +429,8 @@ mm_s_new(argc, argv, obj)
rb_raise(rb_eArgError, "madvise(%d)", errno);
}
t_mm->addr = addr;
- t_mm->real = t_mm->len = size;
+ t_mm->len = size;
+ if (!init) t_mm->real = size;
t_mm->pmode = pmode;
t_mm->vscope = vscope;
t_mm->smode = smode;
@@ -308,10 +442,13 @@ mm_s_new(argc, argv, obj)
else {
OBJ_TAINT(res);
}
+#if RUBY_VERSION_CODE < 172
rb_obj_call_init(res, argc, argv);
+#endif
return res;
}
+#if RUBY_VERSION_CODE < 171
static VALUE
mm_init(argc, argv, obj)
int argc;
@@ -319,70 +456,8 @@ mm_init(argc, argv, obj)
{
return obj;
}
+#endif
-static void
-mm_expandf(t_mm, len)
- mm_mmap *t_mm;
- long len;
-{
- int fd;
-
- if (t_mm->vscope == MAP_PRIVATE) {
- rb_raise(rb_eTypeError, "expand for a private map");
- }
- if (t_mm->frozen & MM_FIXED) {
- rb_raise(rb_eTypeError, "expand for a fixed map");
- }
- if (munmap(t_mm->addr, t_mm->len)) {
- rb_raise(rb_eArgError, "munmap failed");
- }
- if ((fd = open(t_mm->path, t_mm->smode)) == -1) {
- rb_raise(rb_eArgError, "Can't open %s", t_mm->path);
- }
- if (len > t_mm->len) {
- if (lseek(fd, len - t_mm->len - 1, SEEK_END) == -1) {
- rb_raise(rb_eIOError, "Can't lseek %d", len - t_mm->len - 1);
- }
- if (write(fd, "\000", 1) != 1) {
- rb_raise(rb_eIOError, "Can't extend %s", t_mm->path);
- }
- }
- else if (len < t_mm->len && truncate(t_mm->path, len) == -1) {
- rb_raise(rb_eIOError, "Can't truncate %s", t_mm->path);
- }
- t_mm->addr = mmap(0, len, t_mm->pmode, t_mm->vscope, fd, t_mm->offset);
- close(fd);
- if (t_mm->addr == MAP_FAILED) {
- rb_raise(rb_eArgError, "mmap failed");
- }
- if (t_mm->advice && madvise(t_mm->addr, len, t_mm->advice) == -1) {
- rb_raise(rb_eArgError, "madvise(%d)", errno);
- }
- if (t_mm->lock && mlock(t_mm->addr, len) == -1) {
- rb_raise(rb_eArgError, "mlock(%d)", errno);
- }
- t_mm->len = len;
-}
-
-static void
-mm_realloc(t_mm, len)
- mm_mmap *t_mm;
- long len;
-{
- if (t_mm->frozen & MM_FROZEN) rb_error_frozen("mmap");
- if (len > t_mm->len) mm_expandf(t_mm, len);
-}
-
-static VALUE
-mm_extend(obj, a)
- VALUE obj, a;
-{
- mm_mmap *t_mm;
-
- GetMmap(obj, t_mm, MM_MODIFY);
- mm_realloc(t_mm, t_mm->len + NUM2LONG(a));
- return INT2NUM(t_mm->len);
-}
static VALUE
mm_msync(argc, argv, obj)
@@ -717,7 +792,7 @@ mm_gsub_bang(argc, argv, obj)
if (OBJ_TAINTED(repl)) tainted = 1;
plen = END(0);
if ((t_mm->real + RSTRING(val)->len - plen) > t_mm->len) {
- mm_realloc(t_mm, RSTRING(str)->len + 2 * RSTRING(val)->len);
+ mm_realloc(t_mm, RSTRING(str)->len + RSTRING(val)->len - plen);
RSTRING(str)->ptr = t_mm->addr;
}
if (RSTRING(val)->len != plen) {
@@ -1559,7 +1634,11 @@ Init_mmap()
rb_include_module(mm_cMap, rb_mComparable);
rb_include_module(mm_cMap, rb_mEnumerable);
+#if RUBY_VERSION_CODE >= 172
+ rb_define_singleton_method(mm_cMap, "allocate", mm_s_alloc, -1);
+#else
rb_define_singleton_method(mm_cMap, "new", mm_s_new, -1);
+#endif
rb_define_singleton_method(mm_cMap, "mlockall", mm_mlockall, 1);
rb_define_singleton_method(mm_cMap, "lockall", mm_mlockall, 1);
rb_define_singleton_method(mm_cMap, "munlockall", mm_munlockall, 0);
diff --git a/mmap.rd b/mmap.rd
index ac109df..43c7f3d 100644
--- a/mmap.rd
+++ b/mmap.rd
@@ -31,7 +31,7 @@ Object
is created ((|Mmanp::MAP_ANON|))
: ((|mode|))
- Mode to open the file, it can be "r", "w" or "rw"
+ Mode to open the file, it can be "r", "w", "rw", "a"
: ((|protection|))
specify the nature of the mapping
diff --git a/tests/mmapt.rb b/tests/mmapt.rb
index 15fe5e4..a7a049c 100644
--- a/tests/mmapt.rb
+++ b/tests/mmapt.rb
@@ -2,12 +2,18 @@
$LOAD_PATH.unshift *%w{.. . tests}
require 'mmap'
require 'ftools'
-require 'runit/testcase'
-require 'runit/cui/testrunner'
+begin
+ require 'test/unit'
+ Inh = Test::Unit
+rescue LoadError
+ require 'runit/testcase'
+ require 'runit/cui/testrunner'
+ Inh = RUNIT
+end
$mmap, $str = nil, nil
-class TestMmap < RUNIT::TestCase
+class TestMmap < Inh::TestCase
def internal_init
$mmap.unmap if $mmap
file = "mmap.c"
@@ -190,4 +196,7 @@ class TestMmap < RUNIT::TestCase
end
-RUNIT::CUI::TestRunner.run(TestMmap.suite)
+if defined?(RUNIT)
+ RUNIT::CUI::TestRunner.run(TestMmap.suite)
+end
+