localmemcache 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +1 -0
- data/COPYING +21 -0
- data/LICENSE +3 -0
- data/Makefile.in +18 -0
- data/README +83 -0
- data/Rakefile +78 -0
- data/VERSION +1 -0
- data/aclocal.m4 +3 -0
- data/configure +5254 -0
- data/configure.in +42 -0
- data/site/index.html +70 -0
- data/site/style.css +37 -0
- data/src/Makefile.in +53 -0
- data/src/lmc_config.h.in +4 -0
- data/src/lmc_error.c +18 -0
- data/src/lmc_error.h +19 -0
- data/src/lmc_hashtable.c +104 -0
- data/src/lmc_hashtable.h +33 -0
- data/src/lmc_lock.c +65 -0
- data/src/lmc_lock.h +22 -0
- data/src/lmc_shm.c +92 -0
- data/src/lmc_shm.h +22 -0
- data/src/lmc_valloc.c +324 -0
- data/src/lmc_valloc.h +31 -0
- data/src/localmemcache.c +130 -0
- data/src/localmemcache.h +33 -0
- data/src/ruby-binding/extconf.rb +14 -0
- data/src/ruby-binding/localmemcache.rb +32 -0
- data/src/ruby-binding/rblocalmemcache.c +119 -0
- data/src/tests/alloc +11 -0
- data/src/tests/alloc.rb +61 -0
- data/src/tests/bacon.rb +301 -0
- data/src/tests/bench +11 -0
- data/src/tests/bench.rb +46 -0
- data/src/tests/extconf.rb +14 -0
- data/src/tests/lmc +11 -0
- data/src/tests/lmc.rb +85 -0
- data/src/tests/lmctestapi.c +162 -0
- data/src/tests/runtest.sh +9 -0
- data/src/tests/shm +11 -0
- data/src/tests/shm.rb +20 -0
- data/src/tests/torture.rb +56 -0
- data/src/tests/ttalloc +11 -0
- data/src/tests/ttalloc.rb +47 -0
- data/src/tests/ttlmc +11 -0
- data/src/tests/ttlmc.rb +21 -0
- metadata +99 -0
data/src/tests/alloc.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
$DIR=File.dirname(__FILE__)
|
2
|
+
['.', '..'].each {|p| $:.unshift File.join($DIR, p) }
|
3
|
+
|
4
|
+
require 'bacon'
|
5
|
+
require 'lmctestapi'
|
6
|
+
$a = Alloc.new(1000)
|
7
|
+
|
8
|
+
Bacon.summary_on_exit
|
9
|
+
|
10
|
+
describe 'Alloc' do
|
11
|
+
|
12
|
+
it 'should support basic allocation and freeing of memory' do
|
13
|
+
$a.dispose($a.get(100))
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should merge free chunks' do
|
17
|
+
free = $a.free_mem
|
18
|
+
v1 = $a.get(100)
|
19
|
+
$a.free_mem.should.equal(free - 108)
|
20
|
+
v2 = $a.get(100)
|
21
|
+
$a.free_mem.should.equal(free - 216)
|
22
|
+
$a.free_chunks.should.equal 1
|
23
|
+
$a.dispose(v1)
|
24
|
+
$a.free_mem.should.equal(free - 108)
|
25
|
+
$a.free_chunks.should.equal 2
|
26
|
+
$a.dispose(v2)
|
27
|
+
$a.free_mem.should.equal free
|
28
|
+
$a.free_chunks.should.equal 1
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should handle memory exhaustion' do
|
32
|
+
v1 = $a.get($a.free_mem)
|
33
|
+
$a.free_mem.should.equal 0
|
34
|
+
$a.free_mem.should.equal 0
|
35
|
+
$a.free_mem.should.equal 0
|
36
|
+
should.raise(OutOfMemoryError) { $a.get(1) }
|
37
|
+
$a.dispose(v1)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should manage free memory only if there is enough mem left to hold the struct ' do
|
41
|
+
$a.free_chunks.should.equal 1
|
42
|
+
v1 = $a.get($a.free_mem - 100)
|
43
|
+
$a.free_chunks.should.equal 1
|
44
|
+
v2 = $a.get(90)
|
45
|
+
$a.dump
|
46
|
+
$a.free_chunks.should.equal 0
|
47
|
+
$a.dispose(v1)
|
48
|
+
$a.dispose(v2)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should deal with calling free for already freed items' do
|
52
|
+
v = $a.get(90)
|
53
|
+
$a.dispose(v)
|
54
|
+
$a.dispose(v)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should deal with calling free with nasty parameters' do
|
58
|
+
$a.dispose(0)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
data/src/tests/bacon.rb
ADDED
@@ -0,0 +1,301 @@
|
|
1
|
+
# Bacon -- small RSpec clone.
|
2
|
+
#
|
3
|
+
# "Truth will sooner come out from error than from confusion." ---Francis Bacon
|
4
|
+
|
5
|
+
# Copyright (C) 2007, 2008 Christian Neukirchen <purl.org/net/chneukirchen>
|
6
|
+
#
|
7
|
+
# Bacon is freely distributable under the terms of an MIT-style license.
|
8
|
+
# See COPYING or http://www.opensource.org/licenses/mit-license.php.
|
9
|
+
|
10
|
+
module Bacon
|
11
|
+
VERSION = "0.9"
|
12
|
+
|
13
|
+
Counter = Hash.new(0)
|
14
|
+
ErrorLog = ""
|
15
|
+
Shared = Hash.new { |_, name|
|
16
|
+
raise NameError, "no such context: #{name.inspect}"
|
17
|
+
}
|
18
|
+
|
19
|
+
RestrictName = // unless defined? RestrictName
|
20
|
+
RestrictContext = // unless defined? RestrictContext
|
21
|
+
|
22
|
+
def self.summary_on_exit
|
23
|
+
return if Counter[:installed_summary] > 0
|
24
|
+
at_exit {
|
25
|
+
handle_summary
|
26
|
+
if $!
|
27
|
+
raise $!
|
28
|
+
elsif Counter[:errors] + Counter[:failed] > 0
|
29
|
+
exit 1
|
30
|
+
end
|
31
|
+
}
|
32
|
+
Counter[:installed_summary] += 1
|
33
|
+
end
|
34
|
+
|
35
|
+
module SpecDoxOutput
|
36
|
+
def handle_specification(name)
|
37
|
+
puts name
|
38
|
+
yield
|
39
|
+
puts
|
40
|
+
end
|
41
|
+
|
42
|
+
def handle_requirement(description)
|
43
|
+
print "- #{description}"
|
44
|
+
error = yield
|
45
|
+
puts error.empty? ? "" : " [#{error}]"
|
46
|
+
end
|
47
|
+
|
48
|
+
def handle_summary
|
49
|
+
print ErrorLog
|
50
|
+
puts "%d specifications (%d requirements), %d failures, %d errors" %
|
51
|
+
Counter.values_at(:specifications, :requirements, :failed, :errors)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module TestUnitOutput
|
56
|
+
def handle_specification(name) yield end
|
57
|
+
|
58
|
+
def handle_requirement(description)
|
59
|
+
error = yield
|
60
|
+
if error.empty?
|
61
|
+
print "."
|
62
|
+
else
|
63
|
+
print error[0..0]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def handle_summary
|
68
|
+
puts "", ErrorLog
|
69
|
+
puts "%d tests, %d assertions, %d failures, %d errors" %
|
70
|
+
Counter.values_at(:specifications, :requirements, :failed, :errors)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
module TapOutput
|
75
|
+
def handle_specification(name) yield end
|
76
|
+
|
77
|
+
def handle_requirement(description)
|
78
|
+
ErrorLog.replace ""
|
79
|
+
error = yield
|
80
|
+
if error.empty?
|
81
|
+
printf "ok %-3d - %s\n" % [Counter[:specifications], description]
|
82
|
+
else
|
83
|
+
printf "not ok %d - %s: %s\n" %
|
84
|
+
[Counter[:specifications], description, error]
|
85
|
+
puts ErrorLog.strip.gsub(/^/, '# ')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def handle_summary
|
90
|
+
puts "1..#{Counter[:specifications]}"
|
91
|
+
puts "# %d tests, %d assertions, %d failures, %d errors" %
|
92
|
+
Counter.values_at(:specifications, :requirements, :failed, :errors)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
extend SpecDoxOutput # default
|
97
|
+
|
98
|
+
class Error < RuntimeError
|
99
|
+
attr_accessor :count_as
|
100
|
+
|
101
|
+
def initialize(count_as, message)
|
102
|
+
@count_as = count_as
|
103
|
+
super message
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class Context
|
108
|
+
def initialize(name, &block)
|
109
|
+
@name = name
|
110
|
+
@before, @after = [], []
|
111
|
+
|
112
|
+
return unless name =~ RestrictContext
|
113
|
+
Bacon.handle_specification(name) { instance_eval(&block) }
|
114
|
+
end
|
115
|
+
|
116
|
+
def before(&block); @before << block; end
|
117
|
+
def after(&block); @after << block; end
|
118
|
+
|
119
|
+
def behaves_like(*names)
|
120
|
+
names.each { |name| instance_eval(&Shared[name]) }
|
121
|
+
end
|
122
|
+
|
123
|
+
def it(description, &block)
|
124
|
+
return unless description =~ RestrictName
|
125
|
+
Counter[:specifications] += 1
|
126
|
+
run_requirement description, block
|
127
|
+
end
|
128
|
+
|
129
|
+
def run_requirement(description, spec)
|
130
|
+
Bacon.handle_requirement description do
|
131
|
+
begin
|
132
|
+
Counter[:depth] += 1
|
133
|
+
@before.each { |block| instance_eval(&block) }
|
134
|
+
instance_eval(&spec)
|
135
|
+
rescue Object => e
|
136
|
+
ErrorLog << "#{e.class}: #{e.message}\n"
|
137
|
+
e.backtrace.find_all { |line| line !~ /bin\/bacon|\/bacon\.rb:\d+/ }.
|
138
|
+
each_with_index { |line, i|
|
139
|
+
ErrorLog << "\t#{line}#{i==0 ? ": #@name - #{description}" : ""}\n"
|
140
|
+
}
|
141
|
+
ErrorLog << "\n"
|
142
|
+
|
143
|
+
if e.kind_of? Error
|
144
|
+
Counter[e.count_as] += 1
|
145
|
+
e.count_as.to_s.upcase
|
146
|
+
else
|
147
|
+
Counter[:errors] += 1
|
148
|
+
"ERROR: #{e.class}"
|
149
|
+
end
|
150
|
+
else
|
151
|
+
""
|
152
|
+
ensure
|
153
|
+
begin
|
154
|
+
@after.each { |block| instance_eval(&block) }
|
155
|
+
rescue
|
156
|
+
end
|
157
|
+
Counter[:depth] -= 1
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def raise?(*args, &block); block.raise?(*args); end
|
163
|
+
def throw?(*args, &block); block.throw?(*args); end
|
164
|
+
def change?(*args, &block); block.change?(*args); end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
class Object
|
170
|
+
def true?; false; end
|
171
|
+
def false?; false; end
|
172
|
+
end
|
173
|
+
|
174
|
+
class TrueClass
|
175
|
+
def true?; true; end
|
176
|
+
end
|
177
|
+
|
178
|
+
class FalseClass
|
179
|
+
def false?; true; end
|
180
|
+
end
|
181
|
+
|
182
|
+
class Proc
|
183
|
+
def raise?(*exceptions)
|
184
|
+
exceptions << RuntimeError if exceptions.empty?
|
185
|
+
call
|
186
|
+
|
187
|
+
# Only to work in 1.9.0, rescue with splat doesn't work there right now
|
188
|
+
rescue Object => e
|
189
|
+
case e
|
190
|
+
when *exceptions
|
191
|
+
e
|
192
|
+
else
|
193
|
+
raise e
|
194
|
+
end
|
195
|
+
else
|
196
|
+
false
|
197
|
+
end
|
198
|
+
|
199
|
+
def throw?(sym)
|
200
|
+
catch(sym) {
|
201
|
+
call
|
202
|
+
return false
|
203
|
+
}
|
204
|
+
return true
|
205
|
+
end
|
206
|
+
|
207
|
+
def change?
|
208
|
+
pre_result = yield
|
209
|
+
called = call
|
210
|
+
post_result = yield
|
211
|
+
pre_result != post_result
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
class Numeric
|
216
|
+
def close?(to, delta)
|
217
|
+
(to.to_f - self).abs <= delta.to_f rescue false
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
|
222
|
+
class Object
|
223
|
+
def should(*args, &block) Should.new(self).be(*args, &block) end
|
224
|
+
end
|
225
|
+
|
226
|
+
module Kernel
|
227
|
+
private
|
228
|
+
|
229
|
+
def describe(name, &block) Bacon::Context.new(name, &block) end
|
230
|
+
def shared(name, &block) Bacon::Shared[name] = block end
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
class Should
|
235
|
+
# Kills ==, ===, =~, eql?, equal?, frozen?, instance_of?, is_a?,
|
236
|
+
# kind_of?, nil?, respond_to?, tainted?
|
237
|
+
instance_methods.each { |method|
|
238
|
+
undef_method method if method =~ /\?|^\W+$/
|
239
|
+
}
|
240
|
+
|
241
|
+
def initialize(object)
|
242
|
+
@object = object
|
243
|
+
@negated = false
|
244
|
+
end
|
245
|
+
|
246
|
+
def not(*args, &block)
|
247
|
+
@negated = !@negated
|
248
|
+
|
249
|
+
if args.empty?
|
250
|
+
self
|
251
|
+
else
|
252
|
+
be(*args, &block)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
def be(*args, &block)
|
257
|
+
if args.empty?
|
258
|
+
self
|
259
|
+
else
|
260
|
+
block = args.shift unless block_given?
|
261
|
+
satisfy(*args, &block)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
alias a be
|
266
|
+
alias an be
|
267
|
+
|
268
|
+
def satisfy(*args, &block)
|
269
|
+
if args.size == 1 && String === args.first
|
270
|
+
description = args.shift
|
271
|
+
else
|
272
|
+
description = ""
|
273
|
+
end
|
274
|
+
|
275
|
+
r = yield(@object, *args)
|
276
|
+
if Bacon::Counter[:depth] > 0
|
277
|
+
raise Bacon::Error.new(:failed, description) unless @negated ^ r
|
278
|
+
Bacon::Counter[:requirements] += 1
|
279
|
+
end
|
280
|
+
@negated ^ r ? r : false
|
281
|
+
end
|
282
|
+
|
283
|
+
def method_missing(name, *args, &block)
|
284
|
+
name = "#{name}?" if name.to_s =~ /\w[^?]\z/
|
285
|
+
|
286
|
+
desc = @negated ? "not " : ""
|
287
|
+
desc << @object.inspect << "." << name.to_s
|
288
|
+
desc << "(" << args.map{|x|x.inspect}.join(", ") << ") failed"
|
289
|
+
|
290
|
+
satisfy(desc) { |x| x.__send__(name, *args, &block) }
|
291
|
+
end
|
292
|
+
|
293
|
+
def equal(value) self == value end
|
294
|
+
def match(value) self =~ value end
|
295
|
+
def identical_to(value) self.equal? value end
|
296
|
+
alias same_as identical_to
|
297
|
+
|
298
|
+
def flunk(reason="Flunked")
|
299
|
+
raise Bacon::Error.new(:failed, reason)
|
300
|
+
end
|
301
|
+
end
|
data/src/tests/bench
ADDED
data/src/tests/bench.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
$DIR=File.dirname(__FILE__)
|
2
|
+
['.', '..', '../ruby-binding/'].each {|p| $:.unshift File.join($DIR, p) }
|
3
|
+
|
4
|
+
require 'bacon'
|
5
|
+
require 'localmemcache'
|
6
|
+
|
7
|
+
Bacon.summary_on_exit
|
8
|
+
|
9
|
+
LocalMemCache.clear_namespace("speed-comparison");
|
10
|
+
$lm2 = LocalMemCache.new :namespace=>"speed-comparison"
|
11
|
+
|
12
|
+
def compare_speed(n)
|
13
|
+
|
14
|
+
puts "LocalMemCache"
|
15
|
+
measure_time(n) {
|
16
|
+
r = rand(10000).to_s
|
17
|
+
$lm2.set(r, r)
|
18
|
+
$lm2.get(r)
|
19
|
+
}
|
20
|
+
|
21
|
+
puts "builtin"
|
22
|
+
$hh = {}
|
23
|
+
measure_time(n) {
|
24
|
+
r = rand(10000).to_s
|
25
|
+
$hh[r] = r
|
26
|
+
$hh[r]
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def measure_time(c, &block)
|
31
|
+
_then = Time.now
|
32
|
+
c.times { block.call }
|
33
|
+
now = Time.now
|
34
|
+
puts "#{(now - _then)*1000} ms"
|
35
|
+
end
|
36
|
+
|
37
|
+
compare_speed(2_000_000)
|
38
|
+
|
39
|
+
#$stdout.write "ht shm setting x 20000: "
|
40
|
+
#tmeasure (2_000_000) {
|
41
|
+
# v = $lm2.get("f").to_i + 1
|
42
|
+
# #puts "v:#{v}"
|
43
|
+
# $lm2.set("f", v)
|
44
|
+
#}
|
45
|
+
#puts "foo: #{$lm2.get("f")}"
|
46
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
dir = File.dirname(__FILE__)
|
4
|
+
|
5
|
+
$defs << "-DRUBY_VERSION_CODE=#{RUBY_VERSION.gsub(/\D/, '')}"
|
6
|
+
|
7
|
+
$srcs = ['lmctestapi.c']
|
8
|
+
$objs = ['lmctestapi.o']
|
9
|
+
|
10
|
+
$CFLAGS << " -D_REENTRANT -g -I .."
|
11
|
+
$LDFLAGS << " ../liblmc.a -lpthread -lrt"
|
12
|
+
|
13
|
+
dir_config('lmctestapi')
|
14
|
+
create_makefile('lmctestapi')
|
data/src/tests/lmc
ADDED
data/src/tests/lmc.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
$DIR=File.dirname(__FILE__)
|
2
|
+
['.', '..', '../ruby-binding/'].each {|p| $:.unshift File.join($DIR, p) }
|
3
|
+
|
4
|
+
require 'bacon'
|
5
|
+
require 'localmemcache'
|
6
|
+
|
7
|
+
Bacon.summary_on_exit
|
8
|
+
|
9
|
+
$lm = LocalMemCache.new :namespace=>"testing"
|
10
|
+
|
11
|
+
describe 'LocalMemCache' do
|
12
|
+
|
13
|
+
it 'should allow to set and query keys' do
|
14
|
+
$lm.get("non-existant").should.be.nil
|
15
|
+
$lm.set("foo", "1")
|
16
|
+
$lm.get("foo").should.equal "1"
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should support the [] and []= operators' do
|
20
|
+
$lm["boo"] = "2"
|
21
|
+
$lm["boo"].should.equal "2"
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should allow deletion of keys' do
|
25
|
+
$lm["deleteme"] = "blah"
|
26
|
+
$lm["deleteme"].should.not.be.nil
|
27
|
+
$lm.delete("deleteme")
|
28
|
+
$lm["deleteme"].should.be.nil
|
29
|
+
$lm.delete("non-existant")
|
30
|
+
end
|
31
|
+
|
32
|
+
#it 'should support iteration' do
|
33
|
+
# puts "TBD"
|
34
|
+
#end
|
35
|
+
|
36
|
+
it 'should support clearing of namespaces' do
|
37
|
+
LocalMemCache.clear_namespace("testing");
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
def tmeasure(c, &block)
|
43
|
+
_then = Time.now
|
44
|
+
c.times { block.call }
|
45
|
+
now = Time.now
|
46
|
+
puts "#{(now - _then)*1000} ms"
|
47
|
+
end
|
48
|
+
|
49
|
+
$lm2 = LocalMemCache.new :namespace=>"speed-comparison"
|
50
|
+
|
51
|
+
def compare_speed(n)
|
52
|
+
|
53
|
+
puts "LocalMemCache"
|
54
|
+
tmeasure(n) {
|
55
|
+
r = rand(10000).to_s
|
56
|
+
# $lm2.get(r)
|
57
|
+
$lm2.set(r, r)
|
58
|
+
# nr = $lm2.get(r)
|
59
|
+
# if nr != r
|
60
|
+
# $stderr.puts "FAILED: #{nr.inspect} != #{r.inspect}"
|
61
|
+
# end
|
62
|
+
}
|
63
|
+
|
64
|
+
puts "builtin"
|
65
|
+
$hh = {}
|
66
|
+
tmeasure(n) {
|
67
|
+
r = rand(10000).to_s
|
68
|
+
# $hh[r]
|
69
|
+
$hh[r] = r
|
70
|
+
# if $hh[r] != r
|
71
|
+
# $stderr.puts "FAILED!"
|
72
|
+
# end
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
compare_speed(2_000_000)
|
77
|
+
|
78
|
+
#$stdout.write "ht shm setting x 20000: "
|
79
|
+
#tmeasure (2_000_000) {
|
80
|
+
# v = $lm2.get("f").to_i + 1
|
81
|
+
# #puts "v:#{v}"
|
82
|
+
# $lm2.set("f", v)
|
83
|
+
#}
|
84
|
+
#puts "foo: #{$lm2.get("f")}"
|
85
|
+
|
@@ -0,0 +1,162 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) 2009, Sven C. Koehler
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include <ruby.h>
|
6
|
+
#include "lmc_shm.h"
|
7
|
+
#include "lmc_hashtable.h"
|
8
|
+
#include "lmc_valloc.h"
|
9
|
+
|
10
|
+
void *memp = NULL;
|
11
|
+
static VALUE OutOfMemoryError;
|
12
|
+
|
13
|
+
long long_value(VALUE i) { return NUM2LONG(rb_Integer(i)); }
|
14
|
+
VALUE num2string(long i) { return rb_big2str(rb_int2big(i), 10); }
|
15
|
+
char *rstring_ptr(VALUE s) {
|
16
|
+
char* r = NIL_P(s) ? "nil" : RSTRING_PTR(rb_String(s));
|
17
|
+
return r ? r : "nil";
|
18
|
+
}
|
19
|
+
static VALUE ruby_string(char *s) { return s ? rb_str_new2(s) : Qnil; }
|
20
|
+
|
21
|
+
static VALUE Alloc__new(VALUE klass, VALUE size) {
|
22
|
+
size_t s = long_value(size);
|
23
|
+
memp = malloc(s);
|
24
|
+
#ifdef DEBUG_ALLOC
|
25
|
+
printf("memp: %0x, end: %0x\n", memp, memp+s);
|
26
|
+
memset(memp, 0xF0, s);
|
27
|
+
#endif
|
28
|
+
lmc_init_memory(memp, s);
|
29
|
+
return rb_class_new_instance(0, NULL, klass);
|
30
|
+
}
|
31
|
+
|
32
|
+
static VALUE Alloc__get(VALUE obj, VALUE size) {
|
33
|
+
size_t va = lmc_valloc(memp, long_value(size));
|
34
|
+
if (!va) { rb_raise(OutOfMemoryError, "Out of memory"); }
|
35
|
+
size_t v = long_value(size);
|
36
|
+
#ifdef DEBUG_ALLOC
|
37
|
+
memset(memp + va, va, v);
|
38
|
+
#endif
|
39
|
+
return rb_int2big(va);
|
40
|
+
}
|
41
|
+
|
42
|
+
static VALUE Alloc__dispose(VALUE obj, VALUE adr) {
|
43
|
+
lmc_free(memp, long_value(adr));
|
44
|
+
return Qnil;
|
45
|
+
}
|
46
|
+
|
47
|
+
static VALUE Alloc__dump(VALUE obj) {
|
48
|
+
lmc_dump(memp);
|
49
|
+
return Qnil;
|
50
|
+
}
|
51
|
+
|
52
|
+
static VALUE Alloc__free_mem(VALUE obj) {
|
53
|
+
return rb_int2inum(lmc_status(memp, "f").free_mem);
|
54
|
+
}
|
55
|
+
|
56
|
+
static VALUE Alloc__largest_chunk(VALUE obj) {
|
57
|
+
return rb_int2inum(lmc_status(memp, "lc").largest_chunk);
|
58
|
+
}
|
59
|
+
|
60
|
+
static VALUE Alloc__free_chunks(VALUE obj) {
|
61
|
+
return rb_int2inum(lmc_status(memp, "fc").free_chunks);
|
62
|
+
}
|
63
|
+
|
64
|
+
static VALUE SHMError;
|
65
|
+
|
66
|
+
static lmc_shm_t* get_Shm(VALUE obj) {
|
67
|
+
lmc_shm_t *ls;
|
68
|
+
Data_Get_Struct(obj, lmc_shm_t, ls);
|
69
|
+
if (ls == NULL) { rb_raise(SHMError, "Not active"); }
|
70
|
+
return ls;
|
71
|
+
}
|
72
|
+
|
73
|
+
static VALUE SHM__new(VALUE klass, VALUE namespace) {
|
74
|
+
Check_Type(namespace, T_STRING);
|
75
|
+
lmc_shm_t *ls = lmc_shm_create("test2", 2000000, 0, 0);
|
76
|
+
return Data_Wrap_Struct(klass, NULL, lmc_shm_destroy, ls);
|
77
|
+
}
|
78
|
+
|
79
|
+
static VALUE SHM__close(VALUE obj) {
|
80
|
+
lmc_shm_destroy(get_Shm(obj), 0);
|
81
|
+
DATA_PTR(obj) = NULL;
|
82
|
+
return Qnil;
|
83
|
+
}
|
84
|
+
|
85
|
+
static VALUE SHM__get(VALUE obj, VALUE id) {
|
86
|
+
return num2string(((int *)get_Shm(obj)->base)[long_value(id)]);
|
87
|
+
}
|
88
|
+
|
89
|
+
static VALUE SHM__set(VALUE obj, VALUE id, VALUE value) {
|
90
|
+
((int *)get_Shm(obj)->base)[long_value(id)] = long_value(value);
|
91
|
+
return Qnil;
|
92
|
+
}
|
93
|
+
|
94
|
+
//typedef struct {
|
95
|
+
// va_ht_hash_t va;
|
96
|
+
// mem_cache_t *mc;
|
97
|
+
// lmc_lock_t *ll;
|
98
|
+
//} ht_desc_t;
|
99
|
+
//
|
100
|
+
//static VALUE Hashtable__new(VALUE klass) {
|
101
|
+
// lmc_lock_obtain("Hashtable__new");
|
102
|
+
// size_t s = 20401094656;
|
103
|
+
// lmc_lock_t *ll = lmc_lock_init("test11");
|
104
|
+
// mem_cache_t *mc = local_mem_cache_create(s); // namespace?
|
105
|
+
// lmc_init_memory(mc->shm, s);
|
106
|
+
// va_ht_hash_t va_ht = ht_hash_create(mc->shm);
|
107
|
+
// ht_desc_t* ht = malloc(sizeof(ht_desc_t));
|
108
|
+
// ht->va = va_ht;
|
109
|
+
// ht->mc = mc;
|
110
|
+
// ht->ll = ll;
|
111
|
+
// lmc_lock_release("Hashtable__new");
|
112
|
+
// return Data_Wrap_Struct(klass, NULL, NULL, ht);
|
113
|
+
//}
|
114
|
+
//
|
115
|
+
//ht_desc_t *get_Hashtable(VALUE obj) {
|
116
|
+
// ht_desc_t *ht;
|
117
|
+
// Data_Get_Struct(obj, ht_desc_t, ht);
|
118
|
+
// return ht;
|
119
|
+
//}
|
120
|
+
//
|
121
|
+
//static VALUE Hashtable__get(VALUE obj, VALUE key) {
|
122
|
+
// ht_desc_t *ht = get_Hashtable(obj);
|
123
|
+
// return ruby_string(ht_get(ht->mc->shm, ht->va, rstring_ptr(key)));
|
124
|
+
//}
|
125
|
+
//
|
126
|
+
//static VALUE Hashtable__set(VALUE obj, VALUE key, VALUE value) {
|
127
|
+
// ht_desc_t *ht = get_Hashtable(obj);
|
128
|
+
// ht_set(ht->mc->shm, ht->va, rstring_ptr(key), rstring_ptr(value));
|
129
|
+
// return Qnil;
|
130
|
+
//}
|
131
|
+
|
132
|
+
static VALUE Alloc;
|
133
|
+
static VALUE SHM;
|
134
|
+
//static VALUE Hashtable;
|
135
|
+
|
136
|
+
#include <stdio.h>
|
137
|
+
#include <fcntl.h>
|
138
|
+
#include <sys/stat.h>
|
139
|
+
#include <sys/mman.h>
|
140
|
+
|
141
|
+
void Init_lmctestapi() {
|
142
|
+
OutOfMemoryError = rb_define_class("OutOfMemoryError", rb_eStandardError);
|
143
|
+
Alloc = rb_define_class("Alloc", rb_cObject);
|
144
|
+
rb_define_singleton_method(Alloc, "new", Alloc__new, 1);
|
145
|
+
rb_define_method(Alloc, "get", Alloc__get, 1);
|
146
|
+
rb_define_method(Alloc, "dispose", Alloc__dispose, 1);
|
147
|
+
rb_define_method(Alloc, "dump", Alloc__dump, 0);
|
148
|
+
rb_define_method(Alloc, "free_mem", Alloc__free_mem, 0);
|
149
|
+
rb_define_method(Alloc, "largest_chunk", Alloc__largest_chunk, 0);
|
150
|
+
rb_define_method(Alloc, "free_chunks", Alloc__free_chunks, 0);
|
151
|
+
|
152
|
+
SHM = rb_define_class("SHM", rb_cObject);
|
153
|
+
rb_define_singleton_method(SHM, "new", SHM__new, 1);
|
154
|
+
rb_define_method(SHM, "get", SHM__get, 1);
|
155
|
+
rb_define_method(SHM, "set", SHM__set, 2);
|
156
|
+
rb_define_method(SHM, "close", SHM__close, 0);
|
157
|
+
|
158
|
+
//Hashtable = rb_define_class("Hashtable", rb_cObject);
|
159
|
+
//rb_define_singleton_method(Hashtable, "new", Hashtable__new, 0);
|
160
|
+
//rb_define_method(Hashtable, "get", Hashtable__get, 1);
|
161
|
+
//rb_define_method(Hashtable, "set", Hashtable__set, 2);
|
162
|
+
}
|