vagas-orientdb4r 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +26 -0
- data/.travis.yml +18 -0
- data/Gemfile +9 -0
- data/LICENSE +202 -0
- data/README.rdoc +124 -0
- data/Rakefile +43 -0
- data/changelog.txt +60 -0
- data/ci/initialize-ci.sh +36 -0
- data/fstudy/design_v1.dia +0 -0
- data/fstudy/design_v1.png +0 -0
- data/fstudy/domain_model.dia +0 -0
- data/fstudy/domain_model.png +0 -0
- data/fstudy/flat_class_perf.rb +56 -0
- data/fstudy/sample1_object_diagram.dia +0 -0
- data/fstudy/sample1_object_diagram.png +0 -0
- data/fstudy/study_case.rb +87 -0
- data/fstudy/technical_feasibility.rb +256 -0
- data/lib/orientdb4r.rb +115 -0
- data/lib/orientdb4r/bin/client.rb +86 -0
- data/lib/orientdb4r/bin/connection.rb +29 -0
- data/lib/orientdb4r/bin/constants.rb +20 -0
- data/lib/orientdb4r/bin/io.rb +38 -0
- data/lib/orientdb4r/bin/protocol28.rb +101 -0
- data/lib/orientdb4r/bin/protocol_factory.rb +25 -0
- data/lib/orientdb4r/chained_error.rb +37 -0
- data/lib/orientdb4r/client.rb +364 -0
- data/lib/orientdb4r/load_balancing.rb +113 -0
- data/lib/orientdb4r/node.rb +42 -0
- data/lib/orientdb4r/rest/client.rb +517 -0
- data/lib/orientdb4r/rest/excon_node.rb +115 -0
- data/lib/orientdb4r/rest/model.rb +159 -0
- data/lib/orientdb4r/rest/node.rb +43 -0
- data/lib/orientdb4r/rest/restclient_node.rb +77 -0
- data/lib/orientdb4r/rid.rb +54 -0
- data/lib/orientdb4r/utils.rb +203 -0
- data/lib/orientdb4r/version.rb +39 -0
- data/orientdb4r.gemspec +37 -0
- data/test/bin/test_client.rb +21 -0
- data/test/readme_sample.rb +38 -0
- data/test/test_client.rb +93 -0
- data/test/test_database.rb +261 -0
- data/test/test_ddo.rb +237 -0
- data/test/test_dmo.rb +115 -0
- data/test/test_document_crud.rb +184 -0
- data/test/test_gremlin.rb +52 -0
- data/test/test_helper.rb +10 -0
- data/test/test_loadbalancing.rb +81 -0
- data/test/test_utils.rb +67 -0
- metadata +136 -0
data/lib/orientdb4r.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'base64'
|
3
|
+
require 'logger'
|
4
|
+
require 'orientdb4r/version'
|
5
|
+
|
6
|
+
|
7
|
+
###
|
8
|
+
# This module represents the entry point for using the Ruby OrientDB client.
|
9
|
+
module Orientdb4r
|
10
|
+
|
11
|
+
module Binary
|
12
|
+
autoload :BinClient, 'orientdb4r/bin/client'
|
13
|
+
end
|
14
|
+
|
15
|
+
autoload :Utils, 'orientdb4r/utils'
|
16
|
+
autoload :Client, 'orientdb4r/client'
|
17
|
+
autoload :RestClient, 'orientdb4r/rest/client'
|
18
|
+
autoload :Rid, 'orientdb4r/rid'
|
19
|
+
autoload :HashExtension, 'orientdb4r/rest/model'
|
20
|
+
autoload :OClass, 'orientdb4r/rest/model'
|
21
|
+
autoload :ChainedError, 'orientdb4r/chained_error'
|
22
|
+
autoload :Node, 'orientdb4r/node'
|
23
|
+
autoload :RestNode, 'orientdb4r/rest/node'
|
24
|
+
autoload :RestClientNode, 'orientdb4r/rest/restclient_node'
|
25
|
+
autoload :ExconNode, 'orientdb4r/rest/excon_node'
|
26
|
+
autoload :Sequence, 'orientdb4r/load_balancing'
|
27
|
+
autoload :RoundRobin, 'orientdb4r/load_balancing'
|
28
|
+
autoload :DocumentMetadata, 'orientdb4r/rest/model'
|
29
|
+
|
30
|
+
MUTEX_CLIENT = Mutex.new
|
31
|
+
|
32
|
+
class << self
|
33
|
+
|
34
|
+
###
|
35
|
+
# Gets a new database client or an existing for the current thread.
|
36
|
+
# === options
|
37
|
+
# * :instance => :new
|
38
|
+
# * :binary => true
|
39
|
+
# * :connection_library => :restclient | :excon
|
40
|
+
def client options={}
|
41
|
+
if :new == options[:instance]
|
42
|
+
options.delete :instance
|
43
|
+
return options.delete(:binary) ? Binary::BinClient.new(options) : RestClient.new(options)
|
44
|
+
end
|
45
|
+
|
46
|
+
MUTEX_CLIENT.synchronize {
|
47
|
+
client = options.delete(:binary) ? Binary::BinClient.new(options) : RestClient.new(options)
|
48
|
+
Thread.current[:orientdb_client] ||= client
|
49
|
+
#Thread.current[:orientdb_client] ||= BinClient.new options
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
###
|
54
|
+
# Logger used for logging output
|
55
|
+
attr_accessor :logger
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
###
|
61
|
+
# Basic error that indicates an unexpected situation during the client call.
|
62
|
+
class OrientdbError < StandardError
|
63
|
+
include ChainedError
|
64
|
+
end
|
65
|
+
|
66
|
+
###
|
67
|
+
# Error indicating that the request is malformed of invalid somehow.
|
68
|
+
class InvalidRequestError < OrientdbError; end
|
69
|
+
|
70
|
+
###
|
71
|
+
# Error indicating that access to the resource requires user authentication.
|
72
|
+
class UnauthorizedError < OrientdbError; end
|
73
|
+
|
74
|
+
###
|
75
|
+
# Error indicating a conflict between database state and the request
|
76
|
+
class StateConflictError < OrientdbError; end
|
77
|
+
|
78
|
+
###
|
79
|
+
# Error indicating that the server encountered an unexpected condition which prevented it from fulfilling the request.
|
80
|
+
class ServerError < OrientdbError; end
|
81
|
+
|
82
|
+
###
|
83
|
+
# Error indicating problems with communicating with the database.
|
84
|
+
class ConnectionError < OrientdbError; end
|
85
|
+
|
86
|
+
###
|
87
|
+
# Error raised to inform that an object identified by RID cannot be get.
|
88
|
+
class NotFoundError < OrientdbError; end
|
89
|
+
|
90
|
+
###
|
91
|
+
# Error indicating that manipulation against the given data resulted in some illegal operation,
|
92
|
+
# mismatched types or incorrect cardinality.
|
93
|
+
class DataError < OrientdbError; end
|
94
|
+
|
95
|
+
# ---------------------------------------------------------- System Exceptions
|
96
|
+
|
97
|
+
###
|
98
|
+
# This exception represents a fatal failure which meens that the node is not accessible more.
|
99
|
+
# e.g. connection broken pipe
|
100
|
+
class NodeError < OrientdbError; end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
# Configuration of logging.
|
106
|
+
Orientdb4r::logger = Logger.new(STDOUT)
|
107
|
+
Orientdb4r::logger.level = Logger::INFO
|
108
|
+
|
109
|
+
Orientdb4r::logger.info \
|
110
|
+
"Orientdb4r #{Orientdb4r::VERSION}, running on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
|
111
|
+
|
112
|
+
|
113
|
+
#Orientdb4r::logger.level = Logger::DEBUG
|
114
|
+
#client = Orientdb4r.client
|
115
|
+
#client.connect :database => 'temp', :user => 'admin', :password => 'admin'
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'bindata'
|
3
|
+
require 'orientdb4r/bin/constants'
|
4
|
+
require 'orientdb4r/bin/protocol_factory'
|
5
|
+
require 'orientdb4r/bin/io'
|
6
|
+
require 'orientdb4r/bin/connection'
|
7
|
+
|
8
|
+
module Orientdb4r
|
9
|
+
|
10
|
+
module Binary
|
11
|
+
|
12
|
+
###
|
13
|
+
# This client implements the binary protocol.
|
14
|
+
class BinClient < Client
|
15
|
+
include Binary::Constants
|
16
|
+
include Binary::OIO
|
17
|
+
|
18
|
+
attr_reader :server_connection
|
19
|
+
attr_reader :db_connection
|
20
|
+
attr_reader :protocol
|
21
|
+
attr_reader :protocol_version
|
22
|
+
|
23
|
+
|
24
|
+
def initialize(options) #:nodoc:
|
25
|
+
super()
|
26
|
+
options_pattern = {
|
27
|
+
:host => 'localhost', :port => 2424
|
28
|
+
}
|
29
|
+
verify_and_sanitize_options(options, options_pattern)
|
30
|
+
|
31
|
+
@host = options[:host]
|
32
|
+
@port = options[:port]
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
# --------------------------------------------------------------- CONNECTION
|
37
|
+
|
38
|
+
def connect options #:nodoc:
|
39
|
+
options_pattern = { :database => :mandatory, :user => :mandatory, :password => :mandatory, :session => :optional, :db_type => 'document' }
|
40
|
+
verify_and_sanitize_options(options, options_pattern)
|
41
|
+
|
42
|
+
@socket = TCPSocket.open(@host, @port)
|
43
|
+
@protocol_version = BinData::Int16be.read(@socket).to_i
|
44
|
+
|
45
|
+
Orientdb4r::logger.info "Binary protocol version: #{@protocol_version}"
|
46
|
+
|
47
|
+
# check minimal protocol version which is supported
|
48
|
+
@protocol = ProtocolFactory.get_protocol(protocol_version)
|
49
|
+
|
50
|
+
command = protocol::DbOpenRequest.new(:protocol_version => protocol_version, :db_name => options[:database], :user => options[:user], :password => options[:password])
|
51
|
+
|
52
|
+
resp = req_resp(@socket, command, protocol::DbOpenResponse.new)
|
53
|
+
db_connection = Orientdb4r::Binary::Connection.new(resp.session, options)
|
54
|
+
Orientdb4r::logger.info "Database connected, session=#{db_connection.session_id}"
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def disconnect #:nodoc:
|
59
|
+
@socket.close
|
60
|
+
@protocol = nil
|
61
|
+
@protocol_version = 0
|
62
|
+
@db_connection.close unless @db_connection.nil?
|
63
|
+
@server_connection.close unless @server_connection.nil?
|
64
|
+
@db_connection = nil
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def server(options={})
|
69
|
+
raise NotImplementedError, 'this should be overridden by concrete client'
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
# ------------------------------------------------------------------ Helpers
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
# Gets a hash of parameters.
|
78
|
+
def params(args = {})
|
79
|
+
args.merge({ session: connection.session })
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Orientdb4r
|
2
|
+
|
3
|
+
module Binary
|
4
|
+
|
5
|
+
class Connection
|
6
|
+
|
7
|
+
attr_reader :session_id
|
8
|
+
attr_reader :params
|
9
|
+
|
10
|
+
def initialize(session_id, params)
|
11
|
+
@session_id = session_id
|
12
|
+
@params = params
|
13
|
+
end
|
14
|
+
|
15
|
+
def connected?
|
16
|
+
!session_id.nil? and session_id < 0
|
17
|
+
end
|
18
|
+
|
19
|
+
def close
|
20
|
+
@params.clear
|
21
|
+
@params = nil
|
22
|
+
@session_id = 0
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Orientdb4r
|
2
|
+
|
3
|
+
module Binary
|
4
|
+
|
5
|
+
module Constants
|
6
|
+
|
7
|
+
MINIMAL_PROTOCOL_VERSION = 28 # ODB v2.0.5
|
8
|
+
|
9
|
+
REQUEST_SHUTDOWN = 1
|
10
|
+
REQUEST_CONNECT = 2
|
11
|
+
REQUEST_DB_OPEN = 3
|
12
|
+
|
13
|
+
STATUS_OK = 0
|
14
|
+
STATUS_ERROR = 1
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'bindata'
|
2
|
+
require 'orientdb4r/bin/constants'
|
3
|
+
|
4
|
+
module Orientdb4r
|
5
|
+
|
6
|
+
module Binary
|
7
|
+
|
8
|
+
module OIO
|
9
|
+
|
10
|
+
def req_resp(socket, req, resp)
|
11
|
+
req.write(socket)
|
12
|
+
|
13
|
+
status = BinData::Int8.read(socket).to_i
|
14
|
+
if ::Orientdb4r::Binary::Constants::STATUS_ERROR == status
|
15
|
+
errors = protocol::Errors.read(socket)
|
16
|
+
exceptions = errors[:exceptions]
|
17
|
+
Orientdb4r::logger.error "exception(s): #{exceptions}"
|
18
|
+
|
19
|
+
# if exceptions[0] && exceptions[0][:exception_class] == "com.orientechnologies.orient.core.exception.ORecordNotFoundException"
|
20
|
+
# raise RecordNotFound.new(session)
|
21
|
+
# else
|
22
|
+
# raise ServerError.new(session, *exceptions)
|
23
|
+
# end
|
24
|
+
raise ServerError, exceptions[0..-2]
|
25
|
+
end
|
26
|
+
|
27
|
+
BinData::trace_reading do
|
28
|
+
resp.read(socket)
|
29
|
+
end
|
30
|
+
resp
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'bindata'
|
2
|
+
|
3
|
+
module Orientdb4r
|
4
|
+
|
5
|
+
module Binary
|
6
|
+
|
7
|
+
class Protocol28
|
8
|
+
|
9
|
+
# Common Constructs -----------------------------------------------------
|
10
|
+
|
11
|
+
class ProtocolString < BinData::Primitive
|
12
|
+
endian :big
|
13
|
+
|
14
|
+
int32 :len, :value => lambda { data.length }
|
15
|
+
string :data, :read_length => :len, :onlyif => :not_blank?
|
16
|
+
|
17
|
+
def get; self.data; end
|
18
|
+
def set(v) self.data = v; end
|
19
|
+
|
20
|
+
def not_blank?
|
21
|
+
len > 0
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
class Errors < BinData::Record
|
27
|
+
endian :big
|
28
|
+
|
29
|
+
int32 :session
|
30
|
+
array :exceptions, read_until: -> { element[:is_error] < 1 } do
|
31
|
+
int8 :is_error
|
32
|
+
protocol_string :exception_class, onlyif: -> { 1 == is_error }
|
33
|
+
protocol_string :exception_message, onlyif: -> { 1 == is_error }
|
34
|
+
end
|
35
|
+
|
36
|
+
int32 :len
|
37
|
+
skip :length => :len
|
38
|
+
end
|
39
|
+
|
40
|
+
# -----------------------------------------------------------------------
|
41
|
+
|
42
|
+
class DbOpenRequest < BinData::Record
|
43
|
+
endian :big
|
44
|
+
|
45
|
+
int8 :operation, :value => ::Orientdb4r::Binary::Constants::REQUEST_DB_OPEN
|
46
|
+
int32 :session, :value => -123456
|
47
|
+
|
48
|
+
protocol_string :driver_name, :value => Orientdb4r::DRIVER_NAME
|
49
|
+
protocol_string :driver_version, :value => Orientdb4r::VERSION
|
50
|
+
int16 :protocol_version
|
51
|
+
protocol_string :client_id
|
52
|
+
protocol_string :serialization_impl, :value => 'ORecordDocument2csv'
|
53
|
+
int8 :token_based, :value => 0
|
54
|
+
protocol_string :db_name
|
55
|
+
protocol_string :db_type, :value => 'document'
|
56
|
+
protocol_string :user
|
57
|
+
protocol_string :password
|
58
|
+
end
|
59
|
+
|
60
|
+
class DbOpenResponse < BinData::Record
|
61
|
+
endian :big
|
62
|
+
|
63
|
+
int32 :session
|
64
|
+
skip :length => 8
|
65
|
+
int16 :num_of_clusters
|
66
|
+
array :clusters, :initial_length => :num_of_clusters do
|
67
|
+
protocol_string :name
|
68
|
+
int16 :cluster_id
|
69
|
+
end
|
70
|
+
#int8 :cluster_config_bytes
|
71
|
+
protocol_string :cluster_config_bytes
|
72
|
+
#skip :length => 4
|
73
|
+
#protocol_string :neco
|
74
|
+
protocol_string :orientdb_release
|
75
|
+
end
|
76
|
+
|
77
|
+
class Connect < BinData::Record
|
78
|
+
endian :big
|
79
|
+
|
80
|
+
int8 :operation, :value => 2
|
81
|
+
int32 :session, :value => -1 #NEW_SESSION
|
82
|
+
protocol_string :driver, :value => 'Orientdb4r Ruby Client'
|
83
|
+
protocol_string :driver_version, :value => Orientdb4r::VERSION
|
84
|
+
int16 :version
|
85
|
+
protocol_string :client_id
|
86
|
+
protocol_string :user
|
87
|
+
protocol_string :password
|
88
|
+
end
|
89
|
+
|
90
|
+
class ConnectAnswer < BinData::Record
|
91
|
+
endian :big
|
92
|
+
|
93
|
+
skip length: 4
|
94
|
+
int32 :session
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'orientdb4r/bin/protocol28'
|
2
|
+
|
3
|
+
module Orientdb4r
|
4
|
+
|
5
|
+
class ProtocolFactory
|
6
|
+
|
7
|
+
PROTOCOLS = {
|
8
|
+
28 => Orientdb4r::Binary::Protocol28
|
9
|
+
}
|
10
|
+
|
11
|
+
def self.get_protocol(version)
|
12
|
+
return PROTOCOLS[version] if PROTOCOLS.include? version
|
13
|
+
|
14
|
+
#search for a smaller one
|
15
|
+
PROTOCOLS.keys.sort.each do |key|
|
16
|
+
next if key > version
|
17
|
+
return if key < version
|
18
|
+
end
|
19
|
+
|
20
|
+
raise OrientdbError, "Unsupported protocol version, desired=#{version}, supported=#{PROTOCOLS.key.sort}"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Orientdb4r
|
2
|
+
|
3
|
+
###
|
4
|
+
# This mixin extends an error to be able to track a chain of exceptions.
|
5
|
+
module ChainedError
|
6
|
+
|
7
|
+
attr_reader :cause
|
8
|
+
|
9
|
+
###
|
10
|
+
# Constructor.
|
11
|
+
def initialize message = nil, cause = $!
|
12
|
+
super message unless message.nil?
|
13
|
+
super $! if message.nil? and !cause.nil?
|
14
|
+
@cause = cause
|
15
|
+
end
|
16
|
+
|
17
|
+
###
|
18
|
+
# Modification of original method Error#set_backtrace
|
19
|
+
# to descend the full depth of the exception chain.
|
20
|
+
def set_backtrace bt
|
21
|
+
unless cause.nil?
|
22
|
+
cause.backtrace.reverse.each do |line|
|
23
|
+
if bt.last == line
|
24
|
+
bt.pop
|
25
|
+
next
|
26
|
+
end
|
27
|
+
break
|
28
|
+
end
|
29
|
+
bt.push "<<<CAUSED BY>>>: #{cause.class}: #{cause.message}"
|
30
|
+
bt.concat cause.backtrace
|
31
|
+
end
|
32
|
+
super bt
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|