rubyhaze 0.0.1-jruby
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.rdoc +67 -0
- data/Rakefile +55 -0
- data/VERSION +1 -0
- data/bin/rh_console +7 -0
- data/lib/rubyhaze/base_mixin.rb +40 -0
- data/lib/rubyhaze/client.rb +12 -0
- data/lib/rubyhaze/core_ext.rb +76 -0
- data/lib/rubyhaze/list.rb +12 -0
- data/lib/rubyhaze/lock.rb +12 -0
- data/lib/rubyhaze/map.rb +96 -0
- data/lib/rubyhaze/multi_map.rb +12 -0
- data/lib/rubyhaze/node.rb +12 -0
- data/lib/rubyhaze/queue.rb +12 -0
- data/lib/rubyhaze/set.rb +12 -0
- data/lib/rubyhaze/stored.rb +184 -0
- data/lib/rubyhaze/stores/fake_store.rb +25 -0
- data/lib/rubyhaze/topic.rb +21 -0
- data/lib/rubyhaze.rb +52 -0
- data/test/test_stored.rb +85 -0
- metadata +93 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Adrian Madrid
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
= rubyhaze-0.0.1
|
2
|
+
|
3
|
+
JRuby convenience library to connect with {Hazelcast}[http://hazelcast.com]. According to the website:
|
4
|
+
|
5
|
+
Hazelcast is an open source clustering and highly scalable data distribution platform for Java, which is:
|
6
|
+
|
7
|
+
* Lightning-fast; thousands of operations/sec.
|
8
|
+
* Fail-safe; no losing data after crashes.
|
9
|
+
* Dynamically scales as new servers added.
|
10
|
+
* Super-easy to use; include a single jar.
|
11
|
+
|
12
|
+
== Getting started
|
13
|
+
|
14
|
+
Let's get the gem installed and test out the interactive console.
|
15
|
+
|
16
|
+
rvm jruby
|
17
|
+
gem install rubyhaze
|
18
|
+
export HAZELCAST_JAR_PATH=/my/own/path/hazelcast-1.8.5.jar
|
19
|
+
rh_console
|
20
|
+
|
21
|
+
hash = RH::Hash[:test]
|
22
|
+
hash[:a] = 1
|
23
|
+
hash[:b] = 2
|
24
|
+
|
25
|
+
Let's open another console to check how this distributed hash works:
|
26
|
+
|
27
|
+
rh_console
|
28
|
+
|
29
|
+
hash = RH::Hash[:test]
|
30
|
+
hash[:a]
|
31
|
+
|
32
|
+
>> 1
|
33
|
+
|
34
|
+
== Distributed Objects
|
35
|
+
|
36
|
+
Now let's share our own objects:
|
37
|
+
|
38
|
+
rh_console
|
39
|
+
|
40
|
+
class Foo
|
41
|
+
include RubyHaze::Stored
|
42
|
+
field :name, :string
|
43
|
+
field :age, :int
|
44
|
+
end
|
45
|
+
|
46
|
+
a = Foo.create :name => "Leonardo", :age => 65
|
47
|
+
b = Foo.create :name => "Michelangelo", :age => 45
|
48
|
+
c = Foo.create :name => "Raffaello", :age => 32
|
49
|
+
|
50
|
+
found = Foo.find 'age BETWEEN 40 AND 50'
|
51
|
+
found.first.name
|
52
|
+
|
53
|
+
>> "Michelangelo"
|
54
|
+
|
55
|
+
== Note on Patches/Pull Requests
|
56
|
+
|
57
|
+
* Fork the project.
|
58
|
+
* Make your feature addition or bug fix.
|
59
|
+
* Add tests for it. This is important so I don't break it in a
|
60
|
+
future version unintentionally.
|
61
|
+
* Commit, do not mess with rakefile, version, or history.
|
62
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
63
|
+
* Send me a pull request. Bonus points for topic branches.
|
64
|
+
|
65
|
+
== Copyright
|
66
|
+
|
67
|
+
Copyright (c) 2010 Adrian Madrid. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |gem|
|
9
|
+
gem.name = "rubyhaze"
|
10
|
+
gem.summary = %Q{JRuby convenience library to connect with Hazelcast}
|
11
|
+
gem.description = %Q{JRuby convenience library to connect with Hazelcast}
|
12
|
+
gem.email = "aemadrid@gmail.com"
|
13
|
+
gem.homepage = "http://github.com/aemadrid/rubyhaze"
|
14
|
+
gem.authors = ["Adrian Madrid"]
|
15
|
+
gem.files = FileList['bin/*', 'lib/**/*.rb', 'test/**/*.rb', '[A-Z]*'].to_a
|
16
|
+
gem.test_files = Dir["test/test*.rb"]
|
17
|
+
gem.platform = "jruby"
|
18
|
+
gem.add_dependency "bitescript"
|
19
|
+
end
|
20
|
+
Jeweler::GemcutterTasks.new
|
21
|
+
rescue LoadError
|
22
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
23
|
+
end
|
24
|
+
|
25
|
+
Rake::TestTask.new :test do |t|
|
26
|
+
t.libs << "lib"
|
27
|
+
t.test_files = FileList["test/**/test*.rb"]
|
28
|
+
end
|
29
|
+
|
30
|
+
task :test => :check_dependencies
|
31
|
+
|
32
|
+
task :default => :test
|
33
|
+
|
34
|
+
begin
|
35
|
+
require 'rcov/rcovtask'
|
36
|
+
Rcov::RcovTask.new do |spec|
|
37
|
+
spec.libs << 'spec'
|
38
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
39
|
+
spec.verbose = true
|
40
|
+
end
|
41
|
+
rescue LoadError
|
42
|
+
task :rcov do
|
43
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
require 'rake/rdoctask'
|
48
|
+
Rake::RDocTask.new do |rdoc|
|
49
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
50
|
+
|
51
|
+
rdoc.rdoc_dir = 'rdoc'
|
52
|
+
rdoc.title = "rubyhaze #{version}"
|
53
|
+
rdoc.rdoc_files.include('README*')
|
54
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
55
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/bin/rh_console
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module RubyHaze::BaseMixin
|
2
|
+
|
3
|
+
java_import 'com.hazelcast.core.Hazelcast'
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
def crc
|
12
|
+
@crc ||= RubyHaze.crc @name
|
13
|
+
end
|
14
|
+
|
15
|
+
def respond_to?(meth)
|
16
|
+
@hco.respond_to?(meth) || super
|
17
|
+
end
|
18
|
+
|
19
|
+
def method_missing(meth, *args, &blk)
|
20
|
+
if @hco.respond_to? meth
|
21
|
+
@hco.send meth, *args, &blk
|
22
|
+
else
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def ==(other)
|
28
|
+
return false unless other.class.name == self.class.name
|
29
|
+
name == other.name
|
30
|
+
end
|
31
|
+
|
32
|
+
module ClassMethods
|
33
|
+
|
34
|
+
def [](name)
|
35
|
+
new(name)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'java'
|
2
|
+
|
3
|
+
module RubyHaze
|
4
|
+
|
5
|
+
MODE = "client" unless defined? MODE
|
6
|
+
GEM_JAR_PATH = File.expand_path(File.dirname(__FILE__) + '/../../jars/hazelcast-client-1.8.5.jar') unless defined? GEM_JAR_PATH
|
7
|
+
JAR_PATH = ENV['HAZELCAST_JAR_PATH'] || GEM_JAR_PATH unless defined? JAR_PATH
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../lib/rubyhaze')
|
12
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# Taken from http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/100177
|
2
|
+
class Exception
|
3
|
+
def errmsg
|
4
|
+
"%s: %s\n%s" % [self.class, message, (backtrace || []).join("\n") << "\n"]
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
# Taken from Active Support
|
9
|
+
class Array
|
10
|
+
# Extracts options from a set of arguments. Removes and returns the last
|
11
|
+
# element in the array if it's a hash, otherwise returns a blank hash.
|
12
|
+
#
|
13
|
+
# def options(*args)
|
14
|
+
# args.extract_options!
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# options(1, 2) # => {}
|
18
|
+
# options(1, 2, :a => :b) # => {:a=>:b}
|
19
|
+
def extract_options!
|
20
|
+
last.is_a?(::Hash) ? pop : {}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Extracted from truthy (http://github.com/ymendel/truthy/tree/master/lib/truthy.rb)
|
25
|
+
# and Rails (http://github.com/rails/rails/commit/823b623fe2de8846c37aa13250010809ac940b57) although changed to NOT look for private methods
|
26
|
+
|
27
|
+
class Object
|
28
|
+
|
29
|
+
# Tricky, tricky! (-:
|
30
|
+
def truthy?
|
31
|
+
!!self
|
32
|
+
end
|
33
|
+
|
34
|
+
# Tries to send the method only if object responds to it. Return +nil+ otherwise.
|
35
|
+
# It will also forward any arguments and/or block like Object#send does.
|
36
|
+
#
|
37
|
+
# ==== Example :
|
38
|
+
#
|
39
|
+
# # Without try
|
40
|
+
# @person ? @person.name : nil
|
41
|
+
#
|
42
|
+
# With try
|
43
|
+
# @person.try(:name)
|
44
|
+
#
|
45
|
+
# # try also accepts arguments/blocks for the method it is trying
|
46
|
+
# Person.try(:find, 1)
|
47
|
+
# @people.try(:map) {|p| p.name}
|
48
|
+
#
|
49
|
+
def try(method, *args, &block)
|
50
|
+
send(method, *args, &block) if respond_to?(method, true)
|
51
|
+
end
|
52
|
+
|
53
|
+
# List unique local methods
|
54
|
+
# Taken from http://giantrobots.thoughtbot.com/2008/12/23/script-console-tips
|
55
|
+
def local_methods
|
56
|
+
(methods - Object.instance_methods).sort
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
class String
|
62
|
+
def lines
|
63
|
+
self.split("\n").size
|
64
|
+
end
|
65
|
+
|
66
|
+
def valid_uuid_str(uuid)
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.random_uuid
|
70
|
+
java.util.UUID.randomUUID.toString
|
71
|
+
end
|
72
|
+
|
73
|
+
def valid_uuid?
|
74
|
+
!!(size == 36 && self =~ %r{^([A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12})$}i)
|
75
|
+
end
|
76
|
+
end
|
data/lib/rubyhaze/map.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../lib/rubyhaze')
|
2
|
+
|
3
|
+
class RubyHaze::Map
|
4
|
+
|
5
|
+
include RubyHaze::BaseMixin
|
6
|
+
|
7
|
+
java_import 'com.hazelcast.query.SqlPredicate'
|
8
|
+
|
9
|
+
def initialize(name)
|
10
|
+
@name = name.to_s
|
11
|
+
@hco = Hazelcast.get_map @name
|
12
|
+
rescue => e
|
13
|
+
puts e.errmsg
|
14
|
+
end
|
15
|
+
|
16
|
+
def each
|
17
|
+
@hco.each do |(key, value)|
|
18
|
+
yield key, value
|
19
|
+
end
|
20
|
+
rescue => e
|
21
|
+
puts e.errmsg
|
22
|
+
end
|
23
|
+
|
24
|
+
def [](key)
|
25
|
+
@hco[key.to_s]
|
26
|
+
rescue NativeException => x
|
27
|
+
x = x.cause while x.cause
|
28
|
+
x.print_stack_trace
|
29
|
+
rescue => e
|
30
|
+
puts e.errmsg
|
31
|
+
end
|
32
|
+
|
33
|
+
def []=(key,value)
|
34
|
+
@hco[key.to_s] = value
|
35
|
+
rescue NativeException => x
|
36
|
+
x = x.cause while x.cause
|
37
|
+
x.print_stack_trace
|
38
|
+
rescue => e
|
39
|
+
puts e.errmsg
|
40
|
+
end
|
41
|
+
|
42
|
+
def keys(predicate = nil)
|
43
|
+
@hco.key_set(prepare_predicate(predicate)).map
|
44
|
+
rescue NativeException => x
|
45
|
+
x = x.cause while x.cause
|
46
|
+
x.print_stack_trace
|
47
|
+
rescue => e
|
48
|
+
puts e.errmsg
|
49
|
+
end
|
50
|
+
|
51
|
+
def values(predicate = nil)
|
52
|
+
@hco.values(prepare_predicate(predicate)).map
|
53
|
+
rescue NativeException => x
|
54
|
+
x = x.cause while x.cause
|
55
|
+
x.print_stack_trace
|
56
|
+
rescue => e
|
57
|
+
puts e.errmsg
|
58
|
+
end
|
59
|
+
|
60
|
+
def local_keys(predicate = nil)
|
61
|
+
@hco.local_key_set(prepare_predicate(predicate)).map
|
62
|
+
rescue NativeException => x
|
63
|
+
x = x.cause while x.cause
|
64
|
+
x.print_stack_trace
|
65
|
+
rescue => e
|
66
|
+
puts e.errmsg
|
67
|
+
end
|
68
|
+
|
69
|
+
def local_stats
|
70
|
+
lsm = @hco.local_map_stats
|
71
|
+
{ :backup_count => lsm.backup_entry_count, :backup_memory => lsm.backup_entry_memory_cost,
|
72
|
+
:created => lsm.creation_time, :last_accessed => lsm.last_access_time, }
|
73
|
+
rescue => e
|
74
|
+
puts e.errmsg
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def prepare_predicate(predicate)
|
80
|
+
return if predicate.nil?
|
81
|
+
case predicate
|
82
|
+
when String
|
83
|
+
SqlPredicate.new predicate
|
84
|
+
when Hash
|
85
|
+
SqlPredicate.new predicate.map{|k,v| "#{k} = #{v}"}.join(' AND ')
|
86
|
+
when SqlPredicate
|
87
|
+
predicate
|
88
|
+
else
|
89
|
+
raise "Unknown predicate type"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
RubyHaze::Hash = RubyHaze::Map unless defined? RubyHaze::Hash
|
95
|
+
|
96
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'java'
|
2
|
+
|
3
|
+
module RubyHaze
|
4
|
+
|
5
|
+
MODE = "node" unless defined? MODE
|
6
|
+
GEM_JAR_PATH = File.expand_path(File.dirname(__FILE__) + '/../../jars/hazelcast-1.8.5.jar') unless defined? GEM_JAR_PATH
|
7
|
+
JAR_PATH = ENV['HAZELCAST_JAR_PATH'] || GEM_JAR_PATH unless defined? JAR_PATH
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../lib/rubyhaze')
|
12
|
+
|
data/lib/rubyhaze/set.rb
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../lib/rubyhaze')
|
2
|
+
require 'bitescript'
|
3
|
+
|
4
|
+
module RubyHaze::Stored
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.extend ClassMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(*args)
|
11
|
+
return if args.empty?
|
12
|
+
hash = args.extract_options!
|
13
|
+
set hash if hash
|
14
|
+
unless args.empty?
|
15
|
+
args.each_with_index do |value, idx|
|
16
|
+
set self.class.field_names[idx], value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def set(*args)
|
22
|
+
if args.size == 2
|
23
|
+
instance_variable_set "@#{args.first}", args.last
|
24
|
+
elsif args.size == 1 && args.first.is_a?(Hash)
|
25
|
+
args.first.each { |k,v| set k, v }
|
26
|
+
else
|
27
|
+
raise "Unknown parameters #{args.inspect} for set"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def get(*args)
|
32
|
+
if args.size == 1
|
33
|
+
instance_variable_get "@#{args.first}"
|
34
|
+
else
|
35
|
+
args.map { |k| get k }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def attributes
|
40
|
+
self.class.field_names.map{ |name| [ name, instance_variable_get("@#{name}") ] }
|
41
|
+
end
|
42
|
+
|
43
|
+
def values
|
44
|
+
self.class.field_names.map{ |name| instance_variable_get("@#{name}") }
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_ary
|
48
|
+
attributes.unshift [ 'class', self.class.name ]
|
49
|
+
end
|
50
|
+
|
51
|
+
def ==(other)
|
52
|
+
return false unless other.respond_to? :to_ary
|
53
|
+
to_ary == other.to_ary
|
54
|
+
end
|
55
|
+
|
56
|
+
def shadow_object
|
57
|
+
self.class.store_java_class.new *values
|
58
|
+
end
|
59
|
+
|
60
|
+
def load_shadow_object(shadow)
|
61
|
+
self.class.field_names.each do |name|
|
62
|
+
instance_variable_set "@#{name}", shadow.send(name)
|
63
|
+
end
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
attr_accessor :uid
|
68
|
+
|
69
|
+
def save
|
70
|
+
@uid ||= String.random_uuid
|
71
|
+
self.class.store[uid] = shadow_object
|
72
|
+
end
|
73
|
+
|
74
|
+
def load
|
75
|
+
raise "Missing uid for load" if uid.nil?
|
76
|
+
found = self.class.store[uid]
|
77
|
+
raise "Record not found" unless found
|
78
|
+
load_shadow_object(found)
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
alias :reload :load
|
83
|
+
|
84
|
+
def to_s
|
85
|
+
"<" + self.class.name + " " + attributes[1..-1].inspect + " >"
|
86
|
+
end
|
87
|
+
|
88
|
+
module ClassMethods
|
89
|
+
|
90
|
+
def create(*args)
|
91
|
+
obj = new(*args)
|
92
|
+
obj.save
|
93
|
+
obj
|
94
|
+
end
|
95
|
+
|
96
|
+
def store
|
97
|
+
@store ||= RubyHaze::Map.new store_java_class_name
|
98
|
+
end
|
99
|
+
|
100
|
+
def fields
|
101
|
+
@fields ||= [
|
102
|
+
[ :uid, :string, {} ]
|
103
|
+
]
|
104
|
+
end
|
105
|
+
|
106
|
+
def field_names() fields.map { |ary| ary[0] } end
|
107
|
+
def field_types() fields.map { |ary| ary[1] } end
|
108
|
+
def field_options() fields.map { |ary| ary[2] } end
|
109
|
+
|
110
|
+
def field(name, type, options = {})
|
111
|
+
puts "Defining :#{name}, :#{type}, #{options.inspect}..."
|
112
|
+
raise "Field [#{name} already defined" if field_names.include?(name)
|
113
|
+
fields << [ name, type, options ]
|
114
|
+
attr_accessor name
|
115
|
+
end
|
116
|
+
|
117
|
+
def field_loads
|
118
|
+
{
|
119
|
+
:string => :aload,
|
120
|
+
:int => :iload,
|
121
|
+
:boolean => :iload,
|
122
|
+
:double => :dload,
|
123
|
+
}
|
124
|
+
end
|
125
|
+
|
126
|
+
def store_java_class_name
|
127
|
+
'RubyHaze_Shadow__' + name
|
128
|
+
end
|
129
|
+
|
130
|
+
def store_java_class
|
131
|
+
RubyHaze.const_defined?(store_java_class_name) ?
|
132
|
+
RubyHaze.const_get(store_java_class_name) :
|
133
|
+
generate_java_class
|
134
|
+
end
|
135
|
+
|
136
|
+
def generate_java_class
|
137
|
+
builder = BiteScript::FileBuilder.new store_java_class_name + '.class'
|
138
|
+
class_dsl = []
|
139
|
+
class_dsl << %{public_class "#{store_java_class_name}", object, Java::JavaIo::Serializable do}
|
140
|
+
fields.each do |name, type, options|
|
141
|
+
class_dsl << %{ public_field :#{name}, send(:#{type})}
|
142
|
+
end
|
143
|
+
class_dsl << %{ public_constructor [], #{field_types.map{|x| x.to_s}.join(', ')} do}
|
144
|
+
class_dsl << %{ aload 0}
|
145
|
+
class_dsl << %{ invokespecial object, "<init>", [void]}
|
146
|
+
index = 1
|
147
|
+
fields.each do |name, type, options|
|
148
|
+
class_dsl << %{ aload 0}
|
149
|
+
class_dsl << %{ #{field_loads[type]} #{index}}
|
150
|
+
index += 1
|
151
|
+
class_dsl << %{ putfield this, :#{name}, send(:#{type})}
|
152
|
+
end
|
153
|
+
class_dsl << %{ returnvoid}
|
154
|
+
class_dsl << %{ end}
|
155
|
+
class_dsl << %{end}
|
156
|
+
class_dsl = class_dsl.join("\n")
|
157
|
+
if $DEBUG
|
158
|
+
FileUtils.mkdir_p RubyHaze::TMP_PATH
|
159
|
+
filename = RubyHaze::TMP_PATH + '/' + store_java_class_name + '.bc'
|
160
|
+
File.open(filename, 'w') { |file| file.write class_dsl }
|
161
|
+
end
|
162
|
+
builder.instance_eval class_dsl, __FILE__, __LINE__
|
163
|
+
builder.generate do |builder_filename, class_builder|
|
164
|
+
bytes = class_builder.generate
|
165
|
+
klass = JRuby.runtime.jruby_class_loader.define_class store_java_class_name, bytes.to_java_bytes
|
166
|
+
if $DEBUG
|
167
|
+
filename = RubyHaze::TMP_PATH + '/' + builder_filename
|
168
|
+
File.open(filename, 'w') { |file| file.write class_builder.generate }
|
169
|
+
end
|
170
|
+
RubyHaze.const_set store_java_class_name, JavaUtilities.get_proxy_class(klass.name)
|
171
|
+
end
|
172
|
+
RubyHaze.const_get store_java_class_name
|
173
|
+
end
|
174
|
+
|
175
|
+
def find(predicate)
|
176
|
+
store.values(predicate).map { |shadow| new.load_shadow_object shadow }
|
177
|
+
end
|
178
|
+
|
179
|
+
def find_uids(predicate)
|
180
|
+
store.keys(predicate)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class RubyHaze::FakeStore
|
2
|
+
|
3
|
+
java_import 'com.hazelcast.core.MapStore'
|
4
|
+
|
5
|
+
include MapStore
|
6
|
+
|
7
|
+
def delete(key)
|
8
|
+
puts "[FakeStore] Deleting key [#{key}]"
|
9
|
+
end
|
10
|
+
|
11
|
+
def delete_all(keys)
|
12
|
+
puts "[FakeStore] Deleting #{keys.size} keys"
|
13
|
+
keys.each { |key| delete key }
|
14
|
+
end
|
15
|
+
|
16
|
+
def store(key, value)
|
17
|
+
puts "[FakeStore] Storing key [#{key}] value [#{value}]"
|
18
|
+
end
|
19
|
+
|
20
|
+
def store_all(map)
|
21
|
+
puts "[FakeStore] Storing #{map.size} key/values"
|
22
|
+
map.each { |key, value| store key, value }
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../lib/rubyhaze')
|
2
|
+
|
3
|
+
class RubyHaze::Topic
|
4
|
+
|
5
|
+
include RubyHaze::BaseMixin
|
6
|
+
|
7
|
+
java_import 'com.hazelcast.core.MessageListener'
|
8
|
+
|
9
|
+
def initialize(name)
|
10
|
+
@name = name.to_s
|
11
|
+
@hco = Hazelcast.get_topic @name
|
12
|
+
end
|
13
|
+
|
14
|
+
def on_message(&blk)
|
15
|
+
klass = Class.new
|
16
|
+
klass.send :include, MessageListener
|
17
|
+
klass.send :define_method, :on_message, &blk
|
18
|
+
@hco.add_message_listener klass.new
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/lib/rubyhaze.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'java'
|
2
|
+
|
3
|
+
module RubyHaze
|
4
|
+
|
5
|
+
class Exception < StandardError; end
|
6
|
+
|
7
|
+
ROOT = File.expand_path File.join(File.dirname(__FILE__), '..') unless defined? ROOT
|
8
|
+
LIB_PATH = ROOT + "/lib/rubyhaze" unless defined? LIB_PATH
|
9
|
+
TMP_PATH = (ENV['RUBYHAZE_TMP_PATH'] || ROOT + '/tmp')
|
10
|
+
|
11
|
+
$CLASSPATH << TMP_PATH
|
12
|
+
|
13
|
+
unless defined? MODE
|
14
|
+
require LIB_PATH + '/' + (ENV['RUBYHAZE_MODE'] || 'node')
|
15
|
+
end
|
16
|
+
|
17
|
+
puts ">> Loading Hazelcast #{MODE} library..."
|
18
|
+
if File.file?(JAR_PATH)
|
19
|
+
require JAR_PATH
|
20
|
+
java_import 'com.hazelcast.core.Hazelcast'
|
21
|
+
Hazelcast.get_cluster
|
22
|
+
puts ">> ... loaded!"
|
23
|
+
else
|
24
|
+
puts "ERROR! Could not find the Hazelcast JAR file in [#{JAR_PATH}]."
|
25
|
+
abort
|
26
|
+
end
|
27
|
+
|
28
|
+
%w{core_ext base_mixin map multi_map set list queue topic lock stored}.each do |name|
|
29
|
+
require LIB_PATH + '/' + name
|
30
|
+
end
|
31
|
+
|
32
|
+
class << self
|
33
|
+
|
34
|
+
java_import 'com.hazelcast.core.Hazelcast'
|
35
|
+
|
36
|
+
def instances
|
37
|
+
Hazelcast.get_instances
|
38
|
+
end
|
39
|
+
|
40
|
+
def cluster
|
41
|
+
Hazelcast.get_cluster
|
42
|
+
end
|
43
|
+
|
44
|
+
def config
|
45
|
+
Hazelcast.get_config
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
RH = RubyHaze unless defined? RH
|
data/test/test_stored.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/rubyhaze')
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
class Foo
|
5
|
+
include RubyHaze::Stored
|
6
|
+
field :name, :string
|
7
|
+
field :age, :int
|
8
|
+
end unless defined? Foo
|
9
|
+
|
10
|
+
class TestRubyHazeStoredClassMethods < Test::Unit::TestCase
|
11
|
+
|
12
|
+
def test_right_store
|
13
|
+
store = Foo.store
|
14
|
+
assert_equal store.class.name, "RubyHaze::Map"
|
15
|
+
assert_equal store.name, "RubyHaze_Shadow__Foo"
|
16
|
+
assert_equal store.name, RubyHaze::Map.new("RubyHaze_Shadow__Foo").name
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_right_fields
|
20
|
+
fields = Foo.fields
|
21
|
+
assert_equal fields, [[:uid, :string, {}], [:name, :string, {}], [:age, :int, {}]]
|
22
|
+
assert_equal Foo.field_names, [:uid, :name, :age]
|
23
|
+
assert_equal Foo.field_types, [:string, :string, :int]
|
24
|
+
assert_equal Foo.field_options, [{}, {}, {}]
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_right_shadow_class
|
28
|
+
assert_equal Foo.store_java_class_name, "RubyHaze_Shadow__Foo"
|
29
|
+
assert_equal Foo.store_java_class.name, "Java::Default::RubyHaze_Shadow__Foo"
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
class TestRubyHazeStoredStorage < Test::Unit::TestCase
|
36
|
+
|
37
|
+
def test_store_reload_objects
|
38
|
+
Foo.store.clear
|
39
|
+
assert_equal Foo.store.size, 0
|
40
|
+
@a = Foo.create :name => "Leonardo", :age => 65
|
41
|
+
assert_equal Foo.store.size, 1
|
42
|
+
@b = Foo.create :name => "Michelangelo", :age => 45
|
43
|
+
assert_equal Foo.store.size, 2
|
44
|
+
@b.age = 47
|
45
|
+
@b.reload
|
46
|
+
assert_equal Foo.store.size, 2
|
47
|
+
assert_equal @b.age, 45
|
48
|
+
Foo.store.clear
|
49
|
+
assert_equal Foo.store.size, 0
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_find_through_predicates
|
53
|
+
Foo.store.clear
|
54
|
+
@a = Foo.create :name => "Leonardo", :age => 65
|
55
|
+
@b = Foo.create :name => "Michelangelo", :age => 45
|
56
|
+
@c = Foo.create :name => "Raffaello", :age => 32
|
57
|
+
|
58
|
+
res = Foo.find 'age < 40'
|
59
|
+
assert_equal res.size, 1
|
60
|
+
assert_equal res.first, @c
|
61
|
+
assert_equal res.first.name, @c.name
|
62
|
+
|
63
|
+
res = Foo.find 'age BETWEEN 40 AND 50'
|
64
|
+
assert_equal res.size, 1
|
65
|
+
assert_equal res.first, @b
|
66
|
+
assert_equal res.first.name, @b.name
|
67
|
+
|
68
|
+
res = Foo.find "name LIKE 'Leo%'"
|
69
|
+
assert_equal res.size, 1
|
70
|
+
assert_equal res.first, @a
|
71
|
+
assert_equal res.first.name, @a.name
|
72
|
+
|
73
|
+
# res = Foo.find "age IN (32, 65)"
|
74
|
+
# assert_equal res.size, 2
|
75
|
+
# names = res.map{|x| x.name }.sort
|
76
|
+
# assert_equal names.first, @a.name
|
77
|
+
# assert_equal names.last, @b.name
|
78
|
+
|
79
|
+
res = Foo.find "age < 40 AND name LIKE '%el%'"
|
80
|
+
assert_equal res.size, 1
|
81
|
+
assert_equal res.first, @c
|
82
|
+
assert_equal res.first.name, @c.name
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubyhaze
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: jruby
|
11
|
+
authors:
|
12
|
+
- Adrian Madrid
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-08-05 00:00:00 -06:00
|
18
|
+
default_executable: rh_console
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: bitescript
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
32
|
+
description: JRuby convenience library to connect with Hazelcast
|
33
|
+
email: aemadrid@gmail.com
|
34
|
+
executables:
|
35
|
+
- rh_console
|
36
|
+
extensions: []
|
37
|
+
|
38
|
+
extra_rdoc_files:
|
39
|
+
- LICENSE
|
40
|
+
- README.rdoc
|
41
|
+
files:
|
42
|
+
- LICENSE
|
43
|
+
- README.rdoc
|
44
|
+
- Rakefile
|
45
|
+
- VERSION
|
46
|
+
- bin/rh_console
|
47
|
+
- lib/rubyhaze.rb
|
48
|
+
- lib/rubyhaze/base_mixin.rb
|
49
|
+
- lib/rubyhaze/client.rb
|
50
|
+
- lib/rubyhaze/core_ext.rb
|
51
|
+
- lib/rubyhaze/list.rb
|
52
|
+
- lib/rubyhaze/lock.rb
|
53
|
+
- lib/rubyhaze/map.rb
|
54
|
+
- lib/rubyhaze/multi_map.rb
|
55
|
+
- lib/rubyhaze/node.rb
|
56
|
+
- lib/rubyhaze/queue.rb
|
57
|
+
- lib/rubyhaze/set.rb
|
58
|
+
- lib/rubyhaze/stored.rb
|
59
|
+
- lib/rubyhaze/stores/fake_store.rb
|
60
|
+
- lib/rubyhaze/topic.rb
|
61
|
+
- test/test_stored.rb
|
62
|
+
has_rdoc: true
|
63
|
+
homepage: http://github.com/aemadrid/rubyhaze
|
64
|
+
licenses: []
|
65
|
+
|
66
|
+
post_install_message:
|
67
|
+
rdoc_options:
|
68
|
+
- --charset=UTF-8
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
version: "0"
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
version: "0"
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 1.3.6
|
89
|
+
signing_key:
|
90
|
+
specification_version: 3
|
91
|
+
summary: JRuby convenience library to connect with Hazelcast
|
92
|
+
test_files:
|
93
|
+
- test/test_stored.rb
|