na_str 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Makefile +132 -0
- data/README +103 -0
- data/depends/mmap.tar.gz +0 -0
- data/depends/narray-0.5.7p2.tar.gz +0 -0
- data/extconf.rb +9 -0
- data/gemspec.rb +30 -0
- data/install.rb +210 -0
- data/lib/nmap.rb +198 -0
- data/na_str-0.1.0.gem +0 -0
- data/na_str.c +67 -0
- data/nmap.rb +198 -0
- data/samples/a.rb +18 -0
- data/samples/b.rb +47 -0
- data/samples/b.rb.data +0 -0
- data/samples/c.rb +18 -0
- metadata +59 -0
data/Makefile
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
|
2
|
+
SHELL = /bin/sh
|
3
|
+
|
4
|
+
#### Start of system configuration section. ####
|
5
|
+
|
6
|
+
srcdir = .
|
7
|
+
topdir = $(rubylibdir)/$(arch)
|
8
|
+
hdrdir = $(rubylibdir)/$(arch)
|
9
|
+
VPATH = $(srcdir)
|
10
|
+
prefix = $(DESTDIR)/dmsp/reference/ruby-1.8.1/
|
11
|
+
exec_prefix = $(prefix)
|
12
|
+
sitedir = $(prefix)/lib/ruby/site_ruby
|
13
|
+
rubylibdir = $(libdir)/ruby/$(ruby_version)
|
14
|
+
builddir = $(ac_builddir)
|
15
|
+
archdir = $(rubylibdir)/$(arch)
|
16
|
+
sbindir = $(exec_prefix)/sbin
|
17
|
+
compile_dir = $(DESTDIR)/dmsp/moby-1-1/reference/build/ruby-1.8.1
|
18
|
+
datadir = $(prefix)/share
|
19
|
+
includedir = $(prefix)/include
|
20
|
+
infodir = $(prefix)/info
|
21
|
+
top_builddir = $(ac_top_builddir)
|
22
|
+
sysconfdir = $(prefix)/etc
|
23
|
+
mandir = $(prefix)/man
|
24
|
+
libdir = $(exec_prefix)/lib
|
25
|
+
sharedstatedir = $(prefix)/com
|
26
|
+
oldincludedir = $(DESTDIR)/usr/include
|
27
|
+
sitearchdir = $(sitelibdir)/$(sitearch)
|
28
|
+
bindir = $(exec_prefix)/bin
|
29
|
+
localstatedir = $(prefix)/var
|
30
|
+
sitelibdir = $(sitedir)/$(ruby_version)
|
31
|
+
libexecdir = $(exec_prefix)/libexec
|
32
|
+
|
33
|
+
CC = gcc
|
34
|
+
LIBRUBY = $(LIBRUBY_A)
|
35
|
+
LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
|
36
|
+
LIBRUBYARG_SHARED =
|
37
|
+
LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
|
38
|
+
|
39
|
+
CFLAGS = -fPIC -g -O2 -I /dmsp/reference/ruby-1.8.1//lib/ruby/site_ruby/1.8/i686-linux
|
40
|
+
CPPFLAGS = -I. -I$(topdir) -I$(hdrdir) -I$(srcdir)
|
41
|
+
CXXFLAGS = $(CFLAGS)
|
42
|
+
DLDFLAGS = /dmsp/reference/ruby-1.8.1//lib/ruby/site_ruby/1.8/i686-linux/narray.so
|
43
|
+
LDSHARED = gcc -shared
|
44
|
+
AR = ar
|
45
|
+
EXEEXT =
|
46
|
+
|
47
|
+
RUBY_INSTALL_NAME = ruby
|
48
|
+
RUBY_SO_NAME = $(RUBY_INSTALL_NAME)
|
49
|
+
arch = i686-linux
|
50
|
+
sitearch = i686-linux
|
51
|
+
ruby_version = 1.8
|
52
|
+
RUBY = ruby
|
53
|
+
RM = $(RUBY) -run -e rm -- -f
|
54
|
+
MAKEDIRS = $(RUBY) -run -e mkdir -- -p
|
55
|
+
INSTALL_PROG = $(RUBY) -run -e install -- -vpm 0755
|
56
|
+
INSTALL_DATA = $(RUBY) -run -e install -- -vpm 0644
|
57
|
+
|
58
|
+
#### End of system configuration section. ####
|
59
|
+
|
60
|
+
|
61
|
+
LIBPATH = -L"$(libdir)"
|
62
|
+
DEFFILE =
|
63
|
+
|
64
|
+
CLEANFILES =
|
65
|
+
DISTCLEANFILES =
|
66
|
+
|
67
|
+
target_prefix =
|
68
|
+
LOCAL_LIBS =
|
69
|
+
LIBS = -ldl -lcrypt -lm -lc
|
70
|
+
OBJS = na_str.o
|
71
|
+
TARGET = na_str
|
72
|
+
DLLIB = $(TARGET).so
|
73
|
+
STATIC_LIB = $(TARGET).a
|
74
|
+
|
75
|
+
RUBYCOMMONDIR = $(sitedir)$(target_prefix)
|
76
|
+
RUBYLIBDIR = $(sitelibdir)$(target_prefix)
|
77
|
+
RUBYARCHDIR = $(sitearchdir)$(target_prefix)
|
78
|
+
|
79
|
+
CLEANLIBS = "$(TARGET).{lib,exp,il?,tds,map}" $(DLLIB)
|
80
|
+
CLEANOBJS = "*.{o,a,s[ol],pdb,bak}"
|
81
|
+
|
82
|
+
all: $(DLLIB)
|
83
|
+
static: $(STATIC_LIB)
|
84
|
+
|
85
|
+
clean:
|
86
|
+
@$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
|
87
|
+
|
88
|
+
distclean: clean
|
89
|
+
@$(RM) Makefile extconf.h conftest.* mkmf.log
|
90
|
+
@$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
|
91
|
+
|
92
|
+
realclean: distclean
|
93
|
+
install: $(RUBYARCHDIR)
|
94
|
+
install: $(RUBYARCHDIR)/$(DLLIB)
|
95
|
+
$(RUBYARCHDIR)/$(DLLIB): $(DLLIB) $(RUBYARCHDIR)
|
96
|
+
@$(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
|
97
|
+
install: $(RUBYLIBDIR)
|
98
|
+
install: $(RUBYLIBDIR)/nmap.rb
|
99
|
+
$(RUBYLIBDIR)/nmap.rb: $(srcdir)/lib/nmap.rb $(RUBYLIBDIR)
|
100
|
+
@$(INSTALL_DATA) $(srcdir)/lib/nmap.rb $(RUBYLIBDIR)
|
101
|
+
$(RUBYARCHDIR):
|
102
|
+
@$(MAKEDIRS) $(RUBYARCHDIR)
|
103
|
+
$(RUBYLIBDIR):
|
104
|
+
@$(MAKEDIRS) $(RUBYLIBDIR)
|
105
|
+
|
106
|
+
site-install: install
|
107
|
+
|
108
|
+
.SUFFIXES: .c .cc .m .cxx .cpp .C .o
|
109
|
+
|
110
|
+
.cc.o:
|
111
|
+
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
|
112
|
+
|
113
|
+
.cpp.o:
|
114
|
+
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
|
115
|
+
|
116
|
+
.cxx.o:
|
117
|
+
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
|
118
|
+
|
119
|
+
.C.o:
|
120
|
+
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
|
121
|
+
|
122
|
+
.c.o:
|
123
|
+
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
|
124
|
+
|
125
|
+
$(DLLIB): $(OBJS)
|
126
|
+
@-$(RM) $@
|
127
|
+
$(LDSHARED) $(DLDFLAGS) $(LIBPATH) -o $(DLLIB) $(OBJS) $(LOCAL_LIBS) $(LIBS)
|
128
|
+
|
129
|
+
$(STATIC_LIB): $(OBJS)
|
130
|
+
$(AR) cru $@ $(OBJS)
|
131
|
+
@-ranlib $(DLLIB) 2> /dev/null || true
|
132
|
+
|
data/README
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
NAME
|
2
|
+
|
3
|
+
na_str (c extension)
|
4
|
+
|
5
|
+
nmap (reference ruby class which combines narray and mmap)
|
6
|
+
|
7
|
+
|
8
|
+
URIS
|
9
|
+
|
10
|
+
http://codeforpeople.com/lib/ruby/na_str/
|
11
|
+
|
12
|
+
|
13
|
+
SYNOPSIS
|
14
|
+
|
15
|
+
na_str is designed to allow data sharing between narray object and other ruby
|
16
|
+
objects. the shared data is that returned by the objects to_s or to_str method
|
17
|
+
and rb_string_new4. using this technique memory mapped (using guy's mmap
|
18
|
+
extensions) data can be altered with no explicit io on the users part and
|
19
|
+
partial changed to numerical grids can occur very quickly and persistently.
|
20
|
+
|
21
|
+
the nmap.rb reference impl is a concrete example of this usage and is
|
22
|
+
included in the distribution
|
23
|
+
|
24
|
+
|
25
|
+
EXAMPLE USAGE
|
26
|
+
|
27
|
+
jib:~/eg/ruby/na_str > cat a.rb
|
28
|
+
#
|
29
|
+
# the nmap extension is installed along with na_str
|
30
|
+
#
|
31
|
+
require 'nmap'
|
32
|
+
#
|
33
|
+
# the NMap ctor interface is similar to NArray's, but a backing file must also
|
34
|
+
# be specified
|
35
|
+
#
|
36
|
+
path, x, y = 'int.data', 3, 4
|
37
|
+
nmap = NMap.int path, x, y
|
38
|
+
#
|
39
|
+
# copy the last row to the first
|
40
|
+
#
|
41
|
+
nmap.na[true, 0] = nmap.na[true, 3]
|
42
|
+
#
|
43
|
+
# set the last row to be the current time. if you run this a few times you'll
|
44
|
+
# notice that changes to the narray are automatically written to the to
|
45
|
+
# backing file via the magic of mmap
|
46
|
+
#
|
47
|
+
nmap.na[true, 3] = Time.now.to_i
|
48
|
+
#
|
49
|
+
# show the narray
|
50
|
+
#
|
51
|
+
p nmap.na
|
52
|
+
|
53
|
+
|
54
|
+
jib:~/eg/ruby/na_str > ruby a.rb
|
55
|
+
NArray(ref).int(3,4):
|
56
|
+
[ [ 0, 0, 0 ],
|
57
|
+
[ 0, 0, 0 ],
|
58
|
+
[ 0, 0, 0 ],
|
59
|
+
[ 1151439012, 1151439012, 1151439012 ] ]
|
60
|
+
|
61
|
+
jib:~/eg/ruby/na_str > ruby a.rb
|
62
|
+
NArray(ref).int(3,4):
|
63
|
+
[ [ 1151439012, 1151439012, 1151439012 ],
|
64
|
+
[ 0, 0, 0 ],
|
65
|
+
[ 0, 0, 0 ],
|
66
|
+
[ 1151439014, 1151439014, 1151439014 ] ]
|
67
|
+
|
68
|
+
|
69
|
+
SPEED
|
70
|
+
|
71
|
+
jib:~/eg/ruby/na_str > cat a.rb
|
72
|
+
#
|
73
|
+
# reference impl installed with na_str
|
74
|
+
#
|
75
|
+
require 'nmap'
|
76
|
+
#
|
77
|
+
# setup a narray grid containing 1 gb of ints
|
78
|
+
#
|
79
|
+
gb = 2 ** 30
|
80
|
+
mb = 2 ** 20
|
81
|
+
sizeof_int = [42].pack('i').size
|
82
|
+
gig_of_ints = gb / sizeof_int
|
83
|
+
nmap = NMap.int '1GB', gig_of_ints
|
84
|
+
#
|
85
|
+
# set about 1 million of the ints to 42
|
86
|
+
#
|
87
|
+
nmap.na[0 .. mb] = 42
|
88
|
+
#
|
89
|
+
# show that the data was written
|
90
|
+
#
|
91
|
+
p nmap.na[mb - 1]
|
92
|
+
|
93
|
+
|
94
|
+
jib:~/eg/ruby/na_str > time ruby a.rb
|
95
|
+
42
|
96
|
+
|
97
|
+
real 0m0.078s
|
98
|
+
user 0m0.020s
|
99
|
+
sys 0m0.020s
|
100
|
+
|
101
|
+
|
102
|
+
jib:~/eg/ruby/na_str > ls -ltar 1GB
|
103
|
+
-rw-rw-r-- 1 ahoward ahoward 1073741824 Jun 27 14:28 1GB
|
data/depends/mmap.tar.gz
ADDED
Binary file
|
Binary file
|
data/extconf.rb
ADDED
data/gemspec.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
lib, version = File::basename(File::dirname(File::expand_path(__FILE__))).split %r/-/, 2
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
|
6
|
+
Gem::Specification::new do |spec|
|
7
|
+
$VERBOSE = nil
|
8
|
+
spec.name = lib
|
9
|
+
spec.version = version
|
10
|
+
spec.platform = Gem::Platform::RUBY
|
11
|
+
spec.summary = lib
|
12
|
+
|
13
|
+
spec.files = Dir::glob "**/**"
|
14
|
+
spec.executables = Dir::glob("bin/*").map{|exe| File::basename exe}
|
15
|
+
|
16
|
+
spec.require_path = "lib"
|
17
|
+
spec.autorequire = lib
|
18
|
+
|
19
|
+
spec.has_rdoc = File::exist? "doc"
|
20
|
+
spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
|
21
|
+
|
22
|
+
spec.extensions << "extconf.rb" if File::exists? "extconf.rb"
|
23
|
+
|
24
|
+
spec.author = "Ara T. Howard"
|
25
|
+
spec.email = "ara.t.howard@noaa.gov"
|
26
|
+
spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
|
27
|
+
|
28
|
+
spec.requirements << "http://moulon.inra.fr/ruby/mmap.html"
|
29
|
+
spec.requirements << "http://narray.rubyforge.org/"
|
30
|
+
end
|
data/install.rb
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rbconfig'
|
3
|
+
require 'find'
|
4
|
+
require 'ftools'
|
5
|
+
require 'tempfile'
|
6
|
+
include Config
|
7
|
+
|
8
|
+
LIBDIR = "lib"
|
9
|
+
LIBDIR_MODE = 0644
|
10
|
+
|
11
|
+
BINDIR = "bin"
|
12
|
+
BINDIR_MODE = 0755
|
13
|
+
|
14
|
+
|
15
|
+
$srcdir = CONFIG["srcdir"]
|
16
|
+
$version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
|
17
|
+
$libdir = File.join(CONFIG["libdir"], "ruby", $version)
|
18
|
+
$archdir = File.join($libdir, CONFIG["arch"])
|
19
|
+
$site_libdir = $:.find {|x| x =~ /site_ruby$/}
|
20
|
+
$bindir = CONFIG["bindir"] || CONFIG['BINDIR']
|
21
|
+
$ruby_install_name = CONFIG['ruby_install_name'] || CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
|
22
|
+
$ruby_ext = CONFIG['EXEEXT'] || ''
|
23
|
+
$ruby = File.join($bindir, ($ruby_install_name + $ruby_ext))
|
24
|
+
|
25
|
+
if !$site_libdir
|
26
|
+
$site_libdir = File.join($libdir, "site_ruby")
|
27
|
+
elsif $site_libdir !~ %r/#{Regexp.quote($version)}/
|
28
|
+
$site_libdir = File.join($site_libdir, $version)
|
29
|
+
end
|
30
|
+
|
31
|
+
def install_rb(srcdir=nil, destdir=nil, mode=nil, bin=nil)
|
32
|
+
#{{{
|
33
|
+
path = []
|
34
|
+
dir = []
|
35
|
+
Find.find(srcdir) do |f|
|
36
|
+
next unless FileTest.file?(f)
|
37
|
+
next if (f = f[srcdir.length+1..-1]) == nil
|
38
|
+
next if (/CVS$/ =~ File.dirname(f))
|
39
|
+
next if f =~ %r/\.lnk/
|
40
|
+
path.push f
|
41
|
+
dir |= [File.dirname(f)]
|
42
|
+
end
|
43
|
+
for f in dir
|
44
|
+
next if f == "."
|
45
|
+
next if f == "CVS"
|
46
|
+
File::makedirs(File.join(destdir, f))
|
47
|
+
end
|
48
|
+
for f in path
|
49
|
+
next if (/\~$/ =~ f)
|
50
|
+
next if (/^\./ =~ File.basename(f))
|
51
|
+
unless bin
|
52
|
+
File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
|
53
|
+
else
|
54
|
+
from = File.join(srcdir, f)
|
55
|
+
to = File.join(destdir, f)
|
56
|
+
shebangify(from) do |sf|
|
57
|
+
$deferr.print from, " -> ", File::catname(from, to), "\n"
|
58
|
+
$deferr.printf "chmod %04o %s\n", mode, to
|
59
|
+
File::install(sf, to, mode, false)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
#}}}
|
64
|
+
end
|
65
|
+
def shebangify f
|
66
|
+
#{{{
|
67
|
+
open(f) do |fd|
|
68
|
+
buf = fd.read 42
|
69
|
+
if buf =~ %r/^\s*#\s*!.*ruby/o
|
70
|
+
ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
|
71
|
+
begin
|
72
|
+
fd.rewind
|
73
|
+
ftmp.puts "#!#{ $ruby }"
|
74
|
+
while((buf = fd.read(8192)))
|
75
|
+
ftmp.write buf
|
76
|
+
end
|
77
|
+
ftmp.close
|
78
|
+
yield ftmp.path
|
79
|
+
ensure
|
80
|
+
ftmp.close!
|
81
|
+
end
|
82
|
+
else
|
83
|
+
yield f
|
84
|
+
end
|
85
|
+
end
|
86
|
+
#}}}
|
87
|
+
end
|
88
|
+
def ARGV.switch
|
89
|
+
#{{{
|
90
|
+
return nil if self.empty?
|
91
|
+
arg = self.shift
|
92
|
+
return nil if arg == '--'
|
93
|
+
if arg =~ /^-(.)(.*)/
|
94
|
+
return arg if $1 == '-'
|
95
|
+
raise 'unknown switch "-"' if $2.index('-')
|
96
|
+
self.unshift "-#{$2}" if $2.size > 0
|
97
|
+
"-#{$1}"
|
98
|
+
else
|
99
|
+
self.unshift arg
|
100
|
+
nil
|
101
|
+
end
|
102
|
+
#}}}
|
103
|
+
end
|
104
|
+
def ARGV.req_arg
|
105
|
+
#{{{
|
106
|
+
self.shift || raise('missing argument')
|
107
|
+
#}}}
|
108
|
+
end
|
109
|
+
def linkify d, linked = []
|
110
|
+
#--{{{
|
111
|
+
if test ?d, d
|
112
|
+
versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
|
113
|
+
versioned.each do |v|
|
114
|
+
src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
|
115
|
+
lnk = nil
|
116
|
+
begin
|
117
|
+
if test ?l, dst
|
118
|
+
lnk = "#{ dst }.lnk"
|
119
|
+
puts "#{ dst } -> #{ lnk }"
|
120
|
+
File::rename dst, lnk
|
121
|
+
end
|
122
|
+
unless test ?e, dst
|
123
|
+
puts "#{ src } -> #{ dst }"
|
124
|
+
File::copy src, dst
|
125
|
+
linked << dst
|
126
|
+
end
|
127
|
+
ensure
|
128
|
+
if lnk
|
129
|
+
at_exit do
|
130
|
+
puts "#{ lnk } -> #{ dst }"
|
131
|
+
File::rename lnk, dst
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
linked
|
138
|
+
#--}}}
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
#
|
143
|
+
# main program
|
144
|
+
#
|
145
|
+
|
146
|
+
libdir = $site_libdir
|
147
|
+
bindir = $bindir
|
148
|
+
no_linkify = false
|
149
|
+
linked = nil
|
150
|
+
help = false
|
151
|
+
|
152
|
+
usage = <<-usage
|
153
|
+
#{ File::basename $0 }
|
154
|
+
-d, --destdir <destdir>
|
155
|
+
-l, --libdir <libdir>
|
156
|
+
-b, --bindir <bindir>
|
157
|
+
-r, --ruby <ruby>
|
158
|
+
-n, --no_linkify
|
159
|
+
-s, --sudo
|
160
|
+
-h, --help
|
161
|
+
usage
|
162
|
+
|
163
|
+
begin
|
164
|
+
while switch = ARGV.switch
|
165
|
+
case switch
|
166
|
+
when '-d', '--destdir'
|
167
|
+
libdir = ARGV.req_arg
|
168
|
+
when '-l', '--libdir'
|
169
|
+
libdir = ARGV.req_arg
|
170
|
+
when '-b', '--bindir'
|
171
|
+
bindir = ARGV.req_arg
|
172
|
+
when '-r', '--ruby'
|
173
|
+
$ruby = ARGV.req_arg
|
174
|
+
when '-n', '--no_linkify'
|
175
|
+
no_linkify = true
|
176
|
+
when '-s', '--sudo'
|
177
|
+
sudo = 'sudo'
|
178
|
+
when '-h', '--help'
|
179
|
+
help = true
|
180
|
+
else
|
181
|
+
raise "unknown switch #{switch.dump}"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
rescue
|
185
|
+
STDERR.puts $!.to_s
|
186
|
+
STDERR.puts usage
|
187
|
+
exit 1
|
188
|
+
end
|
189
|
+
|
190
|
+
if help
|
191
|
+
STDOUT.puts usage
|
192
|
+
exit
|
193
|
+
end
|
194
|
+
|
195
|
+
system "#{ sudo } #{ $ruby } pre-install.rb" if test(?s, 'pre-install.rb')
|
196
|
+
|
197
|
+
unless no_linkify
|
198
|
+
linked = linkify('lib') + linkify('bin')
|
199
|
+
end
|
200
|
+
|
201
|
+
system "#{ $ruby } extconf.rb && make && #{ sudo } make install" if test(?s, 'extconf.rb')
|
202
|
+
|
203
|
+
install_rb(LIBDIR, libdir, LIBDIR_MODE)
|
204
|
+
install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
|
205
|
+
|
206
|
+
if linked
|
207
|
+
linked.each{|path| File::rm_f path}
|
208
|
+
end
|
209
|
+
|
210
|
+
system "#{ sudo } #{ $ruby } post-install.rb" if test(?s, 'post-install.rb')
|
data/lib/nmap.rb
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
#
|
2
|
+
# built-in
|
3
|
+
#
|
4
|
+
require "yaml"
|
5
|
+
#
|
6
|
+
# rubyforge.org/raa.ruby-lang.org
|
7
|
+
#
|
8
|
+
require "mmap"
|
9
|
+
require "narray"
|
10
|
+
#
|
11
|
+
# homegrown
|
12
|
+
#
|
13
|
+
require "na_str"
|
14
|
+
#
|
15
|
+
# here we creates a little convenience class for working with memory mapped
|
16
|
+
# numerical grids
|
17
|
+
#
|
18
|
+
class NMap
|
19
|
+
module Util
|
20
|
+
def string_of obj
|
21
|
+
obj.to_str
|
22
|
+
rescue
|
23
|
+
raise ArgumentError, "cannot convert <#{ obj.inspect }> to string"
|
24
|
+
end
|
25
|
+
|
26
|
+
def int_of obj
|
27
|
+
Integer obj
|
28
|
+
rescue
|
29
|
+
raise ArgumentError, "cannot convert <#{ obj.inspect }> to int"
|
30
|
+
end
|
31
|
+
|
32
|
+
def int_list_of obj
|
33
|
+
[*obj].flatten.map{|elem| int_of elem}
|
34
|
+
rescue
|
35
|
+
raise ArgumentError, "cannot convert <#{ obj.inspect }> to int list"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Header < ::Hash
|
40
|
+
include Util
|
41
|
+
|
42
|
+
def initialize path, *argv
|
43
|
+
@path = string_of path
|
44
|
+
|
45
|
+
self.na_type = argv.shift
|
46
|
+
self.shape = argv
|
47
|
+
|
48
|
+
self.na_type = int_of na_type if na_type
|
49
|
+
self.shape = int_list_of shape if shape
|
50
|
+
|
51
|
+
init! if na_type and shape
|
52
|
+
|
53
|
+
load!
|
54
|
+
end
|
55
|
+
|
56
|
+
def init!
|
57
|
+
open(@path, "w"){|f| ::YAML::dump(({}.update self), f)}
|
58
|
+
end
|
59
|
+
|
60
|
+
def load!
|
61
|
+
self.update(open(@path){|f| ::YAML::load f})
|
62
|
+
end
|
63
|
+
|
64
|
+
def na_type
|
65
|
+
self["na_type"]
|
66
|
+
end
|
67
|
+
|
68
|
+
def na_type= val
|
69
|
+
self["na_type"] = val
|
70
|
+
end
|
71
|
+
|
72
|
+
def shape
|
73
|
+
self["shape"]
|
74
|
+
end
|
75
|
+
|
76
|
+
def shape= val
|
77
|
+
self["shape"] = val
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.init(*a, &b) new(*a, &b) end
|
81
|
+
end
|
82
|
+
|
83
|
+
include Util
|
84
|
+
|
85
|
+
attr "path"
|
86
|
+
attr "na_type"
|
87
|
+
attr "shape"
|
88
|
+
attr "lockfile"
|
89
|
+
attr "header"
|
90
|
+
attr "na"
|
91
|
+
attr "closed"
|
92
|
+
|
93
|
+
def initialize path, *argv
|
94
|
+
@path = string_of path
|
95
|
+
|
96
|
+
@na_type = argv.shift
|
97
|
+
@shape = argv
|
98
|
+
|
99
|
+
@na_type = int_of @na_type if @na_type
|
100
|
+
@shape = int_list_of @shape if @shape
|
101
|
+
|
102
|
+
@lockfile = @path + '.lock'
|
103
|
+
|
104
|
+
locked do
|
105
|
+
init! unless test ?s, @path
|
106
|
+
load_header!
|
107
|
+
load!
|
108
|
+
end
|
109
|
+
|
110
|
+
@closed = false
|
111
|
+
|
112
|
+
if block_given?
|
113
|
+
begin
|
114
|
+
yield self
|
115
|
+
ensure
|
116
|
+
close
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def init!
|
122
|
+
raise ArgumentError, "no na_type" unless @na_type
|
123
|
+
raise ArgumentError, "no shape" unless @shape
|
124
|
+
sizeof_type = NArray::new(@na_type, 1).to_s.size
|
125
|
+
size = @shape.inject(1){|product, dim| product *= dim}
|
126
|
+
pos = sizeof_type * size
|
127
|
+
File.unlink @path rescue nil
|
128
|
+
open(@path, File::CREAT|File::EXCL|File::RDWR){|f| f.truncate pos}
|
129
|
+
Header::init @path + '.nmap', @na_type, @shape
|
130
|
+
end
|
131
|
+
|
132
|
+
def load_header!
|
133
|
+
@header = Header::new @path + '.nmap'
|
134
|
+
@na_type = @header.na_type
|
135
|
+
@shape = @header.shape
|
136
|
+
end
|
137
|
+
|
138
|
+
def load!
|
139
|
+
@mmap = ::Mmap::new @path, "rw", Mmap::MAP_SHARED
|
140
|
+
@na = ::NArray::str @mmap, @na_type, *@shape
|
141
|
+
end
|
142
|
+
|
143
|
+
def locked
|
144
|
+
f = open @lockfile, 'a+'
|
145
|
+
f.flock File::LOCK_EX
|
146
|
+
yield
|
147
|
+
ensure
|
148
|
+
if f
|
149
|
+
f.flock File::LOCK_UN rescue nil
|
150
|
+
f.close rescue nil
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def sync
|
155
|
+
@mmap.msync
|
156
|
+
end
|
157
|
+
|
158
|
+
def close
|
159
|
+
return if @closed
|
160
|
+
sync
|
161
|
+
@mmap.munmap
|
162
|
+
@mmap = nil
|
163
|
+
@na = nil
|
164
|
+
@closed = true
|
165
|
+
end
|
166
|
+
|
167
|
+
class << self
|
168
|
+
def init(*a, &b) new(*a, &b) end
|
169
|
+
ctors = ::NArray.constants.select{|c| ::NArray.respond_to? c.downcase}
|
170
|
+
ctors.each do |m|
|
171
|
+
module_eval <<-code
|
172
|
+
def #{ m.downcase }(path, *argv)
|
173
|
+
new path, NArray::#{ m }, *argv
|
174
|
+
end
|
175
|
+
code
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
#
|
181
|
+
# sample usage - be sure to run more than once!!
|
182
|
+
#
|
183
|
+
if $0 == __FILE__
|
184
|
+
require 'tmpdir'
|
185
|
+
require 'yaml'
|
186
|
+
|
187
|
+
ipath = File.join Dir.tmpdir, 'i.na'
|
188
|
+
|
189
|
+
t, f = true, false
|
190
|
+
|
191
|
+
nmap = NMap.int ipath, 3,4
|
192
|
+
na = nmap.na
|
193
|
+
p na
|
194
|
+
na[t,0] = 42
|
195
|
+
na[0,t] = Time.now.to_i
|
196
|
+
p na
|
197
|
+
|
198
|
+
end
|
data/na_str-0.1.0.gem
ADDED
File without changes
|
data/na_str.c
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <version.h>
|
3
|
+
#include "narray.h"
|
4
|
+
#include "narray_config.h"
|
5
|
+
|
6
|
+
static VALUE
|
7
|
+
str_new4 (VALUE str)
|
8
|
+
{
|
9
|
+
StringValue (str);
|
10
|
+
if (FL_TEST (str, ELTS_SHARED))
|
11
|
+
{
|
12
|
+
rb_str_buf_cat2 (str, ""); /* unanchor literal string */
|
13
|
+
}
|
14
|
+
return rb_str_new4 (str);
|
15
|
+
}
|
16
|
+
|
17
|
+
static VALUE
|
18
|
+
na_s_str (int argc, VALUE * argv, VALUE klass)
|
19
|
+
{
|
20
|
+
struct NARRAY *ary;
|
21
|
+
VALUE v;
|
22
|
+
VALUE str;
|
23
|
+
int i, type, len = 1, str_len, *shape, rank = argc - 2;
|
24
|
+
|
25
|
+
if (argc < 1)
|
26
|
+
rb_raise (rb_eArgError, "String Argument required");
|
27
|
+
|
28
|
+
if (argc < 2)
|
29
|
+
rb_raise (rb_eArgError, "Type and Size Arguments required");
|
30
|
+
|
31
|
+
type = na_get_typecode (argv[1]);
|
32
|
+
str = str_new4 (argv[0]);
|
33
|
+
str_len = RSTRING (str)->len;
|
34
|
+
|
35
|
+
if (argc == 2)
|
36
|
+
{
|
37
|
+
rank = 1;
|
38
|
+
shape = ALLOCA_N (int, rank);
|
39
|
+
if (str_len % na_sizeof[type] != 0)
|
40
|
+
rb_raise (rb_eArgError, "string size mismatch");
|
41
|
+
shape[0] = str_len / na_sizeof[type];
|
42
|
+
}
|
43
|
+
else
|
44
|
+
{
|
45
|
+
shape = ALLOCA_N (int, rank);
|
46
|
+
for (i = 0; i < rank; i++)
|
47
|
+
len *= shape[i] = NUM2INT (argv[i + 2]);
|
48
|
+
len *= na_sizeof[type];
|
49
|
+
if (len != str_len)
|
50
|
+
rb_raise (rb_eArgError, "size mismatch");
|
51
|
+
}
|
52
|
+
|
53
|
+
v = na_make_object (type, rank, shape, cNArray);
|
54
|
+
GetNArray (v, ary);
|
55
|
+
ary->ptr = RSTRING (str)->ptr;
|
56
|
+
ary->ref = str;
|
57
|
+
|
58
|
+
return v;
|
59
|
+
}
|
60
|
+
|
61
|
+
void
|
62
|
+
Init_na_str ()
|
63
|
+
{
|
64
|
+
rb_require ("narray");
|
65
|
+
rb_define_singleton_method (cNArray, "str", na_s_str, -1);
|
66
|
+
rb_define_singleton_method (cNArray, "from_string", na_s_str, -1);
|
67
|
+
}
|
data/nmap.rb
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
#
|
2
|
+
# built-in
|
3
|
+
#
|
4
|
+
require "yaml"
|
5
|
+
#
|
6
|
+
# rubyforge.org/raa.ruby-lang.org
|
7
|
+
#
|
8
|
+
require "mmap"
|
9
|
+
require "narray"
|
10
|
+
#
|
11
|
+
# homegrown
|
12
|
+
#
|
13
|
+
require "na_str"
|
14
|
+
#
|
15
|
+
# here we creates a little convenience class for working with memory mapped
|
16
|
+
# numerical grids
|
17
|
+
#
|
18
|
+
class NMap
|
19
|
+
module Util
|
20
|
+
def string_of obj
|
21
|
+
obj.to_str
|
22
|
+
rescue
|
23
|
+
raise ArgumentError, "cannot convert <#{ obj.inspect }> to string"
|
24
|
+
end
|
25
|
+
|
26
|
+
def int_of obj
|
27
|
+
Integer obj
|
28
|
+
rescue
|
29
|
+
raise ArgumentError, "cannot convert <#{ obj.inspect }> to int"
|
30
|
+
end
|
31
|
+
|
32
|
+
def int_list_of obj
|
33
|
+
[*obj].flatten.map{|elem| int_of elem}
|
34
|
+
rescue
|
35
|
+
raise ArgumentError, "cannot convert <#{ obj.inspect }> to int list"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Header < ::Hash
|
40
|
+
include Util
|
41
|
+
|
42
|
+
def initialize path, *argv
|
43
|
+
@path = string_of path
|
44
|
+
|
45
|
+
self.na_type = argv.shift
|
46
|
+
self.shape = argv
|
47
|
+
|
48
|
+
self.na_type = int_of na_type if na_type
|
49
|
+
self.shape = int_list_of shape if shape
|
50
|
+
|
51
|
+
init! if na_type and shape
|
52
|
+
|
53
|
+
load!
|
54
|
+
end
|
55
|
+
|
56
|
+
def init!
|
57
|
+
open(@path, "w"){|f| ::YAML::dump(({}.update self), f)}
|
58
|
+
end
|
59
|
+
|
60
|
+
def load!
|
61
|
+
self.update(open(@path){|f| ::YAML::load f})
|
62
|
+
end
|
63
|
+
|
64
|
+
def na_type
|
65
|
+
self["na_type"]
|
66
|
+
end
|
67
|
+
|
68
|
+
def na_type= val
|
69
|
+
self["na_type"] = val
|
70
|
+
end
|
71
|
+
|
72
|
+
def shape
|
73
|
+
self["shape"]
|
74
|
+
end
|
75
|
+
|
76
|
+
def shape= val
|
77
|
+
self["shape"] = val
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.init(*a, &b) new(*a, &b) end
|
81
|
+
end
|
82
|
+
|
83
|
+
include Util
|
84
|
+
|
85
|
+
attr "path"
|
86
|
+
attr "na_type"
|
87
|
+
attr "shape"
|
88
|
+
attr "lockfile"
|
89
|
+
attr "header"
|
90
|
+
attr "na"
|
91
|
+
attr "closed"
|
92
|
+
|
93
|
+
def initialize path, *argv
|
94
|
+
@path = string_of path
|
95
|
+
|
96
|
+
@na_type = argv.shift
|
97
|
+
@shape = argv
|
98
|
+
|
99
|
+
@na_type = int_of @na_type if @na_type
|
100
|
+
@shape = int_list_of @shape if @shape
|
101
|
+
|
102
|
+
@lockfile = @path + '.lock'
|
103
|
+
|
104
|
+
locked do
|
105
|
+
init! unless test ?s, @path
|
106
|
+
load_header!
|
107
|
+
load!
|
108
|
+
end
|
109
|
+
|
110
|
+
@closed = false
|
111
|
+
|
112
|
+
if block_given?
|
113
|
+
begin
|
114
|
+
yield self
|
115
|
+
ensure
|
116
|
+
close
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def init!
|
122
|
+
raise ArgumentError, "no na_type" unless @na_type
|
123
|
+
raise ArgumentError, "no shape" unless @shape
|
124
|
+
sizeof_type = NArray::new(@na_type, 1).to_s.size
|
125
|
+
size = @shape.inject(1){|product, dim| product *= dim}
|
126
|
+
pos = sizeof_type * size
|
127
|
+
File.unlink @path rescue nil
|
128
|
+
open(@path, File::CREAT|File::EXCL|File::RDWR){|f| f.truncate pos}
|
129
|
+
Header::init @path + '.yml', @na_type, @shape
|
130
|
+
end
|
131
|
+
|
132
|
+
def load_header!
|
133
|
+
@header = Header::new @path + '.yml'
|
134
|
+
@na_type = @header.na_type
|
135
|
+
@shape = @header.shape
|
136
|
+
end
|
137
|
+
|
138
|
+
def load!
|
139
|
+
@mmap = ::Mmap::new @path, "rw", Mmap::MAP_SHARED
|
140
|
+
@na = ::NArray::str @mmap, @na_type, *@shape
|
141
|
+
end
|
142
|
+
|
143
|
+
def locked
|
144
|
+
f = open @lockfile, 'a+'
|
145
|
+
f.flock File::LOCK_EX
|
146
|
+
yield
|
147
|
+
ensure
|
148
|
+
if f
|
149
|
+
f.flock File::LOCK_UN rescue nil
|
150
|
+
f.close rescue nil
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def sync
|
155
|
+
@mmap.msync
|
156
|
+
end
|
157
|
+
|
158
|
+
def close
|
159
|
+
return if @closed
|
160
|
+
sync
|
161
|
+
@mmap.munmap
|
162
|
+
@mmap = nil
|
163
|
+
@na = nil
|
164
|
+
@closed = true
|
165
|
+
end
|
166
|
+
|
167
|
+
class << self
|
168
|
+
def init(*a, &b) new(*a, &b) end
|
169
|
+
ctors = ::NArray.constants.select{|c| ::NArray.respond_to? c.downcase}
|
170
|
+
ctors.each do |m|
|
171
|
+
module_eval <<-code
|
172
|
+
def #{ m.downcase }(path, *argv)
|
173
|
+
new path, NArray::#{ m }, *argv
|
174
|
+
end
|
175
|
+
code
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
#
|
181
|
+
# sample usage - be sure to run more than once!!
|
182
|
+
#
|
183
|
+
if $0 == __FILE__
|
184
|
+
require 'tmpdir'
|
185
|
+
require 'yaml'
|
186
|
+
|
187
|
+
ipath = File.join Dir.tmpdir, 'i.na'
|
188
|
+
|
189
|
+
t, f = true, false
|
190
|
+
|
191
|
+
nmap = NMap.int ipath, 3,4
|
192
|
+
na = nmap.na
|
193
|
+
p na
|
194
|
+
na[t,0] = 42
|
195
|
+
na[0,t] = Time.now.to_i
|
196
|
+
p na
|
197
|
+
|
198
|
+
end
|
data/samples/a.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
%w( ./lib ../lib . ..).each{|d| $:.unshift d}
|
2
|
+
require 'na_str'
|
3
|
+
|
4
|
+
#
|
5
|
+
# na_str allows you to share memory with any object that responds to to_s or
|
6
|
+
# to_str. the object whose memory is shared is frozen and cannot be modified
|
7
|
+
# and a reference to the object is kept so it is not gc'd. the object's
|
8
|
+
# memory can be modified using this 'view' of the data.
|
9
|
+
#
|
10
|
+
|
11
|
+
buf = [0,0,0,0].pack 'i*'
|
12
|
+
|
13
|
+
na = NArray::str buf, NArray::INT, 4
|
14
|
+
na[0] = 42
|
15
|
+
na[-1] = 42
|
16
|
+
|
17
|
+
p buf.unpack('i*')
|
18
|
+
p buf
|
data/samples/b.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
%w( ./lib ../lib . ..).each{|d| $:.unshift d}
|
2
|
+
require "na_str"
|
3
|
+
require "mmap"
|
4
|
+
require "yaml"
|
5
|
+
|
6
|
+
#
|
7
|
+
# setup
|
8
|
+
#
|
9
|
+
sizeof_int = [42].pack("i").size
|
10
|
+
|
11
|
+
#
|
12
|
+
# setup an empty data file big enough to hold four ints if one doesn"t already
|
13
|
+
# exist
|
14
|
+
#
|
15
|
+
data = __FILE__ + ".data"
|
16
|
+
open(data, File::CREAT|File::EXCL|File::RDWR){|f| f.write(0.chr * 4 * sizeof_int)} rescue nil
|
17
|
+
|
18
|
+
#
|
19
|
+
# show the orginal data - run the script more than once to see that the data
|
20
|
+
# persists between invocations
|
21
|
+
#
|
22
|
+
y "before" => IO::read(data).unpack("i*")
|
23
|
+
|
24
|
+
#
|
25
|
+
# mmap data in
|
26
|
+
#
|
27
|
+
m = Mmap::new data, "rw", Mmap::MAP_SHARED
|
28
|
+
|
29
|
+
#
|
30
|
+
# overlay an narray over the memory map and manipulate it. note that any
|
31
|
+
# changes to the narray changes the memory map, which in turn changes the
|
32
|
+
# file!
|
33
|
+
#
|
34
|
+
na = NArray::str m, NArray::INT, 4
|
35
|
+
na[0] = 42
|
36
|
+
na[-1] = Time.now.to_i.abs
|
37
|
+
|
38
|
+
#
|
39
|
+
# sync, and unmap the data
|
40
|
+
#
|
41
|
+
m.msync
|
42
|
+
m.munmap
|
43
|
+
|
44
|
+
#
|
45
|
+
# show that the underlying data has been transparently changed!
|
46
|
+
#
|
47
|
+
y "after" => IO::read(data).unpack("i*")
|
data/samples/b.rb.data
ADDED
Binary file
|
data/samples/c.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
%w( ./lib ../lib . ..).each{|d| $:.unshift d}
|
2
|
+
#
|
3
|
+
# be sure to run this a few times in a row - wait a second or two between runs
|
4
|
+
# - notice that the data will automagically persist between calls!
|
5
|
+
#
|
6
|
+
require 'tmpdir'
|
7
|
+
require 'nmap'
|
8
|
+
|
9
|
+
ipath = File.join Dir.tmpdir, 'i.na'
|
10
|
+
|
11
|
+
nmap = NMap.int ipath, 3,4
|
12
|
+
na = nmap.na
|
13
|
+
p na
|
14
|
+
|
15
|
+
na[0,true] = Time.now.to_i
|
16
|
+
na[2,true] = 1
|
17
|
+
na[1,1..2] = 42
|
18
|
+
p na
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: na_str
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.1.0
|
7
|
+
date: 2007-02-28 00:00:00.000000 -07:00
|
8
|
+
summary: na_str
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: ara.t.howard@noaa.gov
|
12
|
+
homepage: http://codeforpeople.com/lib/ruby/na_str/
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: na_str
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: false
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
platform: ruby
|
27
|
+
signing_key:
|
28
|
+
cert_chain:
|
29
|
+
authors:
|
30
|
+
- Ara T. Howard
|
31
|
+
files:
|
32
|
+
- depends
|
33
|
+
- extconf.rb
|
34
|
+
- install.rb
|
35
|
+
- lib
|
36
|
+
- Makefile
|
37
|
+
- na_str.c
|
38
|
+
- nmap.rb
|
39
|
+
- README
|
40
|
+
- samples
|
41
|
+
- gemspec.rb
|
42
|
+
- na_str-0.1.0.gem
|
43
|
+
- depends/mmap.tar.gz
|
44
|
+
- depends/narray-0.5.7p2.tar.gz
|
45
|
+
- lib/nmap.rb
|
46
|
+
- samples/b.rb.data
|
47
|
+
- samples/b.rb
|
48
|
+
- samples/a.rb
|
49
|
+
- samples/c.rb
|
50
|
+
test_files: []
|
51
|
+
rdoc_options: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
executables: []
|
54
|
+
extensions:
|
55
|
+
- extconf.rb
|
56
|
+
requirements:
|
57
|
+
- http://moulon.inra.fr/ruby/mmap.html
|
58
|
+
- http://narray.rubyforge.org/
|
59
|
+
dependencies: []
|