diametric 0.0.4 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/Gemfile +21 -18
- data/Jarfile +15 -1
- data/README.md +22 -14
- data/Rakefile +17 -1
- data/bin/datomic-rest +33 -0
- data/bin/download-datomic +13 -0
- data/datomic_version.yml +4 -0
- data/diametric.gemspec +9 -6
- data/ext/diametric/DiametricCollection.java +147 -0
- data/ext/diametric/DiametricConnection.java +113 -0
- data/ext/diametric/DiametricDatabase.java +107 -0
- data/ext/diametric/DiametricEntity.java +90 -0
- data/ext/diametric/DiametricListenableFuture.java +47 -0
- data/ext/diametric/DiametricObject.java +66 -0
- data/ext/diametric/DiametricPeer.java +414 -0
- data/ext/diametric/DiametricService.java +102 -0
- data/ext/diametric/DiametricUUID.java +61 -0
- data/ext/diametric/DiametricUtils.java +183 -0
- data/lib/boolean_type.rb +3 -0
- data/lib/diametric.rb +24 -0
- data/lib/diametric/entity.rb +219 -14
- data/lib/diametric/generators/active_model.rb +2 -2
- data/lib/diametric/persistence.rb +0 -1
- data/lib/diametric/persistence/common.rb +28 -9
- data/lib/diametric/persistence/peer.rb +122 -87
- data/lib/diametric/persistence/rest.rb +4 -3
- data/lib/diametric/query.rb +94 -23
- data/lib/diametric/rest_service.rb +74 -0
- data/lib/diametric/service_base.rb +77 -0
- data/lib/diametric/transactor.rb +86 -0
- data/lib/diametric/version.rb +1 -1
- data/lib/diametric_service.jar +0 -0
- data/lib/value_enums.rb +8 -0
- data/spec/conf_helper.rb +55 -0
- data/spec/config/free-transactor-template.properties +73 -0
- data/spec/config/logback.xml +59 -0
- data/spec/data/seattle-data0.dtm +452 -0
- data/spec/data/seattle-data1.dtm +326 -0
- data/spec/developer_create_sample.rb +39 -0
- data/spec/developer_query_spec.rb +120 -0
- data/spec/diametric/config_spec.rb +1 -1
- data/spec/diametric/entity_spec.rb +263 -0
- data/spec/diametric/peer_api_spec.rb +147 -0
- data/spec/diametric/persistence/peer_many2many_spec.rb +76 -0
- data/spec/diametric/persistence/peer_spec.rb +13 -22
- data/spec/diametric/persistence/rest_spec.rb +12 -19
- data/spec/diametric/query_spec.rb +4 -5
- data/spec/diametric/rest_service_spec.rb +56 -0
- data/spec/diametric/transactor_spec.rb +68 -0
- data/spec/integration_spec.rb +5 -3
- data/spec/parent_child_sample.rb +42 -0
- data/spec/peer_integration_spec.rb +106 -22
- data/spec/peer_seattle_spec.rb +200 -0
- data/spec/rc2013_seattle_big.rb +82 -0
- data/spec/rc2013_seattle_small.rb +60 -0
- data/spec/rc2013_simple_sample.rb +72 -0
- data/spec/seattle_integration_spec.rb +106 -0
- data/spec/simple_validation_sample.rb +31 -0
- data/spec/spec_helper.rb +31 -45
- data/spec/support/entities.rb +157 -0
- data/spec/support/gen_entity_class.rb +2 -0
- data/spec/support/persistence_examples.rb +9 -5
- data/spec/test_version_file.yml +4 -0
- metadata +131 -75
- data/Jarfile.lock +0 -134
- data/lib/jrclj.rb +0 -63
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'diametric/service_base'
|
2
|
+
|
3
|
+
module Diametric
|
4
|
+
class RestService
|
5
|
+
include ::Diametric::ServiceBase
|
6
|
+
class << self
|
7
|
+
def datomic_command(datomic_home)
|
8
|
+
classpath = datomic_classpath(datomic_home)
|
9
|
+
command = ["java -server -Xmx1g", "-cp", classpath, "clojure.main", "-i", "#{datomic_home}/bin/bridge.clj", "--main datomic.rest"].flatten.join(" ")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :datomic_version, :datomic_version_no, :datomic_home, :pid
|
14
|
+
attr_accessor :host, :port, :db_alias, :uri
|
15
|
+
|
16
|
+
def initialize(conf="datomic_version.yml", dest="vendor/datomic")
|
17
|
+
@conf = conf
|
18
|
+
@dest = dest
|
19
|
+
@datomic_version = RestService.datomic_version(conf)
|
20
|
+
@datomic_home = File.join(File.dirname(__FILE__), "../..", dest, @datomic_version)
|
21
|
+
@datomic_version_no = RestService.datomic_version_no(@datomic_version)
|
22
|
+
@pid = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def start(opts={})
|
26
|
+
return if @pid
|
27
|
+
RestService.download(@conf, @dest)
|
28
|
+
command = RestService.datomic_command(@datomic_home)
|
29
|
+
|
30
|
+
require 'socket'
|
31
|
+
@host = opts[:host] ? opts[:host] : Socket.gethostname
|
32
|
+
@port = opts[:port] ? opts[:port] : 9000
|
33
|
+
@db_alias = opts[:db_alias] ? opts[:db_alias] : "free"
|
34
|
+
@uri = opts[:uri] ? opts[:uri] : "datomic:mem://"
|
35
|
+
|
36
|
+
uri = URI("http://#{@host}:#{@port}/")
|
37
|
+
|
38
|
+
unless port_available?(uri)
|
39
|
+
puts "Somebody is using #{@port}. Choose other."
|
40
|
+
return
|
41
|
+
end
|
42
|
+
|
43
|
+
temp_pid = spawn("#{command} -p #{@port} #{@db_alias} #{@uri}")
|
44
|
+
|
45
|
+
@pid = temp_pid if ready?(uri)
|
46
|
+
end
|
47
|
+
|
48
|
+
def stop
|
49
|
+
Process.kill("HUP", @pid) if @pid
|
50
|
+
@pid = nil
|
51
|
+
end
|
52
|
+
|
53
|
+
def port_available?(uri)
|
54
|
+
response = Net::HTTP.get_response(uri)
|
55
|
+
false
|
56
|
+
rescue Errno::ECONNREFUSED
|
57
|
+
true
|
58
|
+
end
|
59
|
+
|
60
|
+
def ready?(uri)
|
61
|
+
while true
|
62
|
+
begin
|
63
|
+
response = Net::HTTP.get_response(uri)
|
64
|
+
return true
|
65
|
+
rescue
|
66
|
+
sleep 1
|
67
|
+
redo
|
68
|
+
end
|
69
|
+
end
|
70
|
+
true
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'pathname'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Diametric
|
6
|
+
module ServiceBase
|
7
|
+
def self.included(base)
|
8
|
+
base.send(:extend, ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def datomic_conf_file?(file="datomic_version.yml")
|
13
|
+
if Pathname.new(file).relative?
|
14
|
+
file = File.join(File.dirname(__FILE__), "../..", file)
|
15
|
+
end
|
16
|
+
return File.exists?(file)
|
17
|
+
end
|
18
|
+
|
19
|
+
def datomic_version(conf="datomic_version.yml")
|
20
|
+
if datomic_conf_file?(conf)
|
21
|
+
datomic_names = File.read(File.join(File.dirname(__FILE__), "../..", conf))
|
22
|
+
datomic_versions = YAML.load(datomic_names)
|
23
|
+
if ENV['DIAMETRIC_ENV'] && (ENV['DIAMETRIC_ENV'] == "pro")
|
24
|
+
datomic_versions["pro"]
|
25
|
+
else
|
26
|
+
datomic_versions["free"]
|
27
|
+
end
|
28
|
+
else
|
29
|
+
conf
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def datomic_version_no(datomic_version_str)
|
34
|
+
/(\d|\.)+/.match(datomic_version_str)[0]
|
35
|
+
end
|
36
|
+
|
37
|
+
def downloaded?(conf="datomic_version.yml", dest="vendor/datomic")
|
38
|
+
datomic_home = datomic_version(conf)
|
39
|
+
if Pathname.new(dest).relative?
|
40
|
+
dest = File.join(File.dirname(__FILE__), "..", "..", dest)
|
41
|
+
end
|
42
|
+
File.exists?(File.join(dest, datomic_home))
|
43
|
+
end
|
44
|
+
|
45
|
+
def download(conf="datomic_version.yml", dest="vendor/datomic")
|
46
|
+
return true if downloaded?(conf, dest)
|
47
|
+
version = datomic_version(conf)
|
48
|
+
url = "http://downloads.datomic.com/#{datomic_version_no(version)}/#{version}.zip"
|
49
|
+
if Pathname.new(dest).relative?
|
50
|
+
dest = File.join(File.dirname(__FILE__), "../..", dest)
|
51
|
+
end
|
52
|
+
require 'open-uri'
|
53
|
+
require 'zip/zipfilesystem'
|
54
|
+
open(url) do |zip_file|
|
55
|
+
Zip::ZipFile.open(zip_file.path) do |zip_path|
|
56
|
+
zip_path.each do |zip_entry|
|
57
|
+
file_path = File.join(dest, zip_entry.to_s)
|
58
|
+
FileUtils.mkdir_p(File.dirname(file_path))
|
59
|
+
zip_path.extract(zip_entry, file_path) { true }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def datomic_classpath(datomic_home)
|
66
|
+
# Find jar archives
|
67
|
+
jars = Dir["#{datomic_home}/lib/*.jar"]
|
68
|
+
jars += Dir["#{datomic_home}/*transactor*.jar"]
|
69
|
+
|
70
|
+
# Setup CLASSPATH
|
71
|
+
classpath = jars.join(File::PATH_SEPARATOR)
|
72
|
+
files = ["samples/clj", "bin", "resources"]
|
73
|
+
classpath += File::PATH_SEPARATOR + files.collect {|f| datomic_home + "/" + f}.join(File::PATH_SEPARATOR)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'diametric/service_base'
|
2
|
+
require 'pathname'
|
3
|
+
require 'securerandom'
|
4
|
+
|
5
|
+
module Diametric
|
6
|
+
class Transactor
|
7
|
+
include ::Diametric::ServiceBase
|
8
|
+
class << self
|
9
|
+
def datomic_command(datomic_home)
|
10
|
+
classpath = datomic_classpath(datomic_home)
|
11
|
+
java_opts = "-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly"
|
12
|
+
command = ["java -server -Xmx1g -Xms1g", java_opts, "-cp", classpath, "clojure.main", "--main datomic.launcher"].flatten.join(" ")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_accessor :datomic_version, :datomic_version_no, :datomic_home, :pid
|
17
|
+
attr_accessor :host, :port, :db_alias, :uri
|
18
|
+
|
19
|
+
def initialize(conf="datomic_version.yml", dest="vendor/datomic")
|
20
|
+
@conf = conf
|
21
|
+
@dest = dest
|
22
|
+
@datomic_version = Transactor.datomic_version(conf)
|
23
|
+
if Pathname.new(dest).relative?
|
24
|
+
@datomic_home = File.join(File.dirname(__FILE__), "../..", dest, @datomic_version)
|
25
|
+
else
|
26
|
+
@datomic_home = File.join(dest, @datomic_version)
|
27
|
+
end
|
28
|
+
@datomic_version_no = Transactor.datomic_version_no(@datomic_version)
|
29
|
+
@hostname = nil
|
30
|
+
@port = nil
|
31
|
+
@pid = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def start(props)
|
35
|
+
return if @pid
|
36
|
+
Transactor.download(@conf, @dest)
|
37
|
+
command = Transactor.datomic_command(@datomic_home)
|
38
|
+
|
39
|
+
unless File.exists?(props)
|
40
|
+
puts "Transactor property file #{props} doesn't exist."
|
41
|
+
return
|
42
|
+
end
|
43
|
+
properties(props)
|
44
|
+
tmp_pid = spawn("#{command} #{props}")
|
45
|
+
if ready?
|
46
|
+
@pid = tmp_pid
|
47
|
+
end
|
48
|
+
@pid
|
49
|
+
end
|
50
|
+
|
51
|
+
def stop
|
52
|
+
Process.kill("HUP", @pid) if @pid
|
53
|
+
@pid = nil
|
54
|
+
end
|
55
|
+
|
56
|
+
def properties(props)
|
57
|
+
File.readlines(props).each do |line|
|
58
|
+
m = /^(host=)(.+)/.match(line)
|
59
|
+
if m && m[2]
|
60
|
+
@hostname = m[2]
|
61
|
+
end
|
62
|
+
m = /^(port=)(\d+)/.match(line)
|
63
|
+
if m && m[2]
|
64
|
+
@port = m[2]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def ready?
|
70
|
+
tmp_database = "datomic:free://#{@hostname}:#{port}/tmp_database-#{SecureRandom.uuid}"
|
71
|
+
while true
|
72
|
+
begin
|
73
|
+
if Diametric::Persistence::Peer.create_database(tmp_database)
|
74
|
+
Diametric::Persistence::Peer.delete_database(tmp_database)
|
75
|
+
return true
|
76
|
+
end
|
77
|
+
rescue
|
78
|
+
sleep 1
|
79
|
+
redo
|
80
|
+
end
|
81
|
+
end
|
82
|
+
true
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
data/lib/diametric/version.rb
CHANGED
Binary file
|
data/lib/value_enums.rb
ADDED
data/spec/conf_helper.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
#require 'pry'
|
3
|
+
|
4
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
|
5
|
+
require 'lock_jar'
|
6
|
+
jar_file = File.join(File.dirname(__FILE__), "..", "Jarfile")
|
7
|
+
lock_file = File.join(File.dirname(__FILE__), "..", "Jarfile.lock")
|
8
|
+
LockJar.lock(jar_file)
|
9
|
+
LockJar.install(lock_file)
|
10
|
+
LockJar.load(lock_file)
|
11
|
+
end
|
12
|
+
require 'diametric'
|
13
|
+
#Dir["./spec/support/**/*.rb"].each {|f| require f}
|
14
|
+
|
15
|
+
RSpec.configure do |c|
|
16
|
+
# c.fail_fast = true
|
17
|
+
|
18
|
+
c.filter_run_excluding :integration => true unless ENV['INTEGRATION']
|
19
|
+
c.filter_run_excluding :jruby => (not is_jruby?)
|
20
|
+
c.filter_run_excluding :service => true unless ENV['RESTSERVICE']
|
21
|
+
|
22
|
+
c.filter_run_including :focused => true
|
23
|
+
c.alias_example_to :fit, :focused => true
|
24
|
+
|
25
|
+
c.run_all_when_everything_filtered = true
|
26
|
+
c.treat_symbols_as_metadata_keys_with_true_values = true
|
27
|
+
|
28
|
+
c.before(:suite) do
|
29
|
+
#@rest = Diametric::RestService.new("spec/test_version_file.cnf", "tmp/datomic")
|
30
|
+
#@rest.start(:port => 46291, :db_alias => @storage, :uri => "datomic:mem://")
|
31
|
+
#PID = @rest.pid
|
32
|
+
end
|
33
|
+
|
34
|
+
c.after(:suite) do
|
35
|
+
Diametric::Persistence::Peer.shutdown(true) if is_jruby?
|
36
|
+
#Process.kill("HUP", PID)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
shared_examples "ActiveModel" do |model|
|
41
|
+
require 'test/unit/assertions'
|
42
|
+
require 'active_model/lint'
|
43
|
+
include Test::Unit::Assertions
|
44
|
+
include ActiveModel::Lint::Tests
|
45
|
+
|
46
|
+
active_model_lints = ActiveModel::Lint::Tests.public_instance_methods.map(&:to_s).grep(/^test/)
|
47
|
+
|
48
|
+
let(:model) { subject }
|
49
|
+
|
50
|
+
active_model_lints.each do |test_name|
|
51
|
+
it "#{test_name.sub(/^test_/, '')}" do
|
52
|
+
send(test_name)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
################################################################
|
2
|
+
# Basic connection settings.
|
3
|
+
|
4
|
+
protocol=free
|
5
|
+
host=localhost
|
6
|
+
port=39082
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
## OPTIONAL ####################################################
|
11
|
+
# The dev: and free: protocols typically use three ports
|
12
|
+
# starting with the selected :port, but you can specify the
|
13
|
+
# other ports explicitly, e.g. for virtualization environs
|
14
|
+
# that do not issue contiguous ports.
|
15
|
+
|
16
|
+
# h2-port=4335
|
17
|
+
# h2-web-port=4336
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
################################################################
|
22
|
+
# See http://docs.datomic.com/capacity.html
|
23
|
+
|
24
|
+
|
25
|
+
# Recommended settings for -Xmx4g, ongoing usage.
|
26
|
+
memory-index-threshold=32m
|
27
|
+
memory-index-max=128m
|
28
|
+
object-cache-max=1g
|
29
|
+
|
30
|
+
# Recommended settings for -Xmx4g import jobs.
|
31
|
+
# memory-index-threshold=512m
|
32
|
+
# memory-index-max=1g
|
33
|
+
# object-cache-max=1g
|
34
|
+
|
35
|
+
# Recommended settings for -Xmx1g usage, e.g. dev laptops.
|
36
|
+
# memory-index-threshold=32m
|
37
|
+
# memory-index-max=128m
|
38
|
+
# object-cache-max=128m
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
## OPTIONAL ####################################################
|
43
|
+
|
44
|
+
|
45
|
+
# Set to false to disable SSL between the peers and the transactor.
|
46
|
+
# Default: true
|
47
|
+
# encrypt-channel=true
|
48
|
+
|
49
|
+
# Data directory is used for dev: and free: storage, and
|
50
|
+
# as a temporary directory for all storages.
|
51
|
+
data-dir=tmp/data
|
52
|
+
|
53
|
+
# Transactor will log here, see bin/logback.xml to configure logging.
|
54
|
+
log-dir=tmp/log
|
55
|
+
|
56
|
+
# Transactor will write process pid here on startup
|
57
|
+
pid-file=tmp/transactor.pid
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
## OPTIONAL ####################################################
|
62
|
+
# See http://docs.datomic.com/capacity.html
|
63
|
+
|
64
|
+
|
65
|
+
# Soft limit on the number of concurrent writes to storage.
|
66
|
+
# Default: 4, Miniumum: 2
|
67
|
+
# write-concurrency=4
|
68
|
+
|
69
|
+
# Soft limit on the number of concurrent reads to storage.
|
70
|
+
# Default: 2 times write-concurrency, Miniumum: 2
|
71
|
+
# read-concurrency=8
|
72
|
+
|
73
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
<configuration>
|
2
|
+
|
3
|
+
<!-- prevent per-message overhead for jul logging calls, e.g. Hornet -->
|
4
|
+
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
|
5
|
+
<resetJUL>true</resetJUL>
|
6
|
+
</contextListener>
|
7
|
+
|
8
|
+
<appender name="MAIN" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
9
|
+
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
10
|
+
<fileNamePattern>${DATOMIC_LOG_DIR:-log}/%d{yyyy-MM-dd}.log</fileNamePattern>
|
11
|
+
<maxHistory>72</maxHistory>
|
12
|
+
</rollingPolicy>
|
13
|
+
<prudent>true</prudent> <!-- multi jvm safe, slower -->
|
14
|
+
<encoder>
|
15
|
+
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %-10contextName %logger{36} - %msg%n</pattern>
|
16
|
+
</encoder>
|
17
|
+
</appender>
|
18
|
+
|
19
|
+
<!-- uncomment to log storage access -->
|
20
|
+
<!-- <logger name="datomic.kv-cluster" level="DEBUG"/> -->
|
21
|
+
|
22
|
+
<!-- uncomment to log transactor heartbeat -->
|
23
|
+
<!-- <logger name="datomic.lifecycle" level="DEBUG"/> -->
|
24
|
+
|
25
|
+
<!-- uncomment to log transactions (transactor side) -->
|
26
|
+
<!-- <logger name="datomic.transaction" level="DEBUG"/> -->
|
27
|
+
|
28
|
+
<!-- uncomment to log transactions (peer side) -->
|
29
|
+
<!-- <logger name="datomic.peer" level="DEBUG"/> -->
|
30
|
+
|
31
|
+
<!-- uncomment to log the transactor log -->
|
32
|
+
<!-- <logger name="datomic.log" level="DEBUG"/> -->
|
33
|
+
|
34
|
+
<!-- uncomment to log peer connection to transactor -->
|
35
|
+
<!-- <logger name="datomic.connector" level="DEBUG"/> -->
|
36
|
+
|
37
|
+
<!-- uncomment to log storage gc -->
|
38
|
+
<!-- <logger name="datomic.garbage" level="DEBUG"/> -->
|
39
|
+
|
40
|
+
<!-- these namespsaces create a ton of log noise -->
|
41
|
+
<logger name="httpclient" level="INFO"/>
|
42
|
+
<logger name="org.apache.commons.httpclient" level="INFO"/>
|
43
|
+
<logger name="org.apache.http" level="INFO"/>
|
44
|
+
<logger name="org.jets3t" level="INFO"/>
|
45
|
+
<logger name="com.amazonaws" level="INFO"/>
|
46
|
+
<logger name="com.amazonaws.request" level="WARN"/>
|
47
|
+
<logger name="sun.rmi" level="INFO"/>
|
48
|
+
<logger name="net.spy.memcached" level="INFO"/>
|
49
|
+
<logger name="com.couchbase.client" level="INFO"/>
|
50
|
+
<logger name="org.apache.zookeeper" level="INFO"/>
|
51
|
+
<logger name="com.ning.http.client.providers.netty" level="INFO"/>
|
52
|
+
<logger name="org.eclipse.jetty" level="INFO"/>
|
53
|
+
<logger name="org.hornetq.core.client.impl" level="INFO"/>
|
54
|
+
<logger name="org.apache.tomcat.jdbc.pool" level="INFO"/>
|
55
|
+
|
56
|
+
<root level="info">
|
57
|
+
<appender-ref ref="MAIN"/>
|
58
|
+
</root>
|
59
|
+
</configuration>
|