na_str 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
Binary file
@@ -0,0 +1,9 @@
1
+ require "mkmf"
2
+ require "rbconfig"
3
+
4
+ sitearchdir = Config::CONFIG["sitearchdir"]
5
+
6
+ $CFLAGS += " -I #{ sitearchdir } "
7
+ $LDFLAGS += " #{ sitearchdir }/narray.so " # force a link so narray.so symbols will be resolved
8
+
9
+ create_makefile "na_str"
@@ -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
@@ -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')
@@ -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
File without changes
@@ -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
@@ -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
@@ -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*")
Binary file
@@ -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: []