vagas-orientdb4r 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +26 -0
  4. data/.travis.yml +18 -0
  5. data/Gemfile +9 -0
  6. data/LICENSE +202 -0
  7. data/README.rdoc +124 -0
  8. data/Rakefile +43 -0
  9. data/changelog.txt +60 -0
  10. data/ci/initialize-ci.sh +36 -0
  11. data/fstudy/design_v1.dia +0 -0
  12. data/fstudy/design_v1.png +0 -0
  13. data/fstudy/domain_model.dia +0 -0
  14. data/fstudy/domain_model.png +0 -0
  15. data/fstudy/flat_class_perf.rb +56 -0
  16. data/fstudy/sample1_object_diagram.dia +0 -0
  17. data/fstudy/sample1_object_diagram.png +0 -0
  18. data/fstudy/study_case.rb +87 -0
  19. data/fstudy/technical_feasibility.rb +256 -0
  20. data/lib/orientdb4r.rb +115 -0
  21. data/lib/orientdb4r/bin/client.rb +86 -0
  22. data/lib/orientdb4r/bin/connection.rb +29 -0
  23. data/lib/orientdb4r/bin/constants.rb +20 -0
  24. data/lib/orientdb4r/bin/io.rb +38 -0
  25. data/lib/orientdb4r/bin/protocol28.rb +101 -0
  26. data/lib/orientdb4r/bin/protocol_factory.rb +25 -0
  27. data/lib/orientdb4r/chained_error.rb +37 -0
  28. data/lib/orientdb4r/client.rb +364 -0
  29. data/lib/orientdb4r/load_balancing.rb +113 -0
  30. data/lib/orientdb4r/node.rb +42 -0
  31. data/lib/orientdb4r/rest/client.rb +517 -0
  32. data/lib/orientdb4r/rest/excon_node.rb +115 -0
  33. data/lib/orientdb4r/rest/model.rb +159 -0
  34. data/lib/orientdb4r/rest/node.rb +43 -0
  35. data/lib/orientdb4r/rest/restclient_node.rb +77 -0
  36. data/lib/orientdb4r/rid.rb +54 -0
  37. data/lib/orientdb4r/utils.rb +203 -0
  38. data/lib/orientdb4r/version.rb +39 -0
  39. data/orientdb4r.gemspec +37 -0
  40. data/test/bin/test_client.rb +21 -0
  41. data/test/readme_sample.rb +38 -0
  42. data/test/test_client.rb +93 -0
  43. data/test/test_database.rb +261 -0
  44. data/test/test_ddo.rb +237 -0
  45. data/test/test_dmo.rb +115 -0
  46. data/test/test_document_crud.rb +184 -0
  47. data/test/test_gremlin.rb +52 -0
  48. data/test/test_helper.rb +10 -0
  49. data/test/test_loadbalancing.rb +81 -0
  50. data/test/test_utils.rb +67 -0
  51. metadata +136 -0
@@ -0,0 +1,36 @@
1
+ #!/bin/bash
2
+
3
+ PARENT_DIR=$(dirname $(cd "$(dirname "$0")"; pwd))
4
+ CI_DIR="$PARENT_DIR/ci/environment"
5
+ #CI_DIR=/tmp/travis
6
+
7
+ ODB_VERSION=${1:-"2.0.4"}
8
+ ODB_DIR="${CI_DIR}/orientdb-community-${ODB_VERSION}"
9
+ ODB_LAUNCHER="${ODB_DIR}/bin/server.sh"
10
+
11
+
12
+
13
+ echo "=== Initializing CI environment ==="
14
+ cd "$PARENT_DIR"
15
+ mkdir -p $CI_DIR
16
+
17
+ echo "--- Downloading OrientDB v${ODB_VERSION} ---"
18
+ wget -q -O "$CI_DIR/orientdb-community-${ODB_VERSION}.tar.gz" "http://www.orientechnologies.com/download.php?email=unknown@unknown.com&file=orientdb-community-${ODB_VERSION}.tar.gz&os=linux"
19
+
20
+ echo "--- Unpacking ---------------------"
21
+ tar xf $CI_DIR/orientdb-community-${ODB_VERSION}.tar.gz -C $CI_DIR
22
+
23
+ echo "--- Setting up --------------------"
24
+ chmod +x $ODB_LAUNCHER
25
+ chmod -R +rw "${ODB_DIR}/config/"
26
+ ODB_ADMIN="<users><user resources=\"*\" password=\"root\" name=\"root\"/></users>"
27
+ sed "s:^[ \t]*<users.*$: $ODB_ADMIN:" -i ${ODB_DIR}/config/orientdb-server-config.xml
28
+ sed "s:^[ \t]*<\/users.*$: <!-- \/users -->:" -i ${ODB_DIR}/config/orientdb-server-config.xml
29
+ sed "s:^handlers = .*$:handlers = java.util.logging.ConsoleHandler:" -i ${ODB_DIR}/config/orientdb-server-log.properties
30
+
31
+ echo "--- Starting server ---------------"
32
+ sh -c $ODB_LAUNCHER </dev/null &>/dev/null &
33
+
34
+ # Wait a bit for OrientDB to finish the initialization phase.
35
+ sleep 5
36
+ printf "=== The CI environment has been initialized ===\n"
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,56 @@
1
+ require 'study_case'
2
+
3
+ # This class tests performance on a simple flat class.
4
+ class FlatClassPerf < FStudy::Case
5
+
6
+ def db; 'perf'; end
7
+
8
+ def drop
9
+ client.drop_class 'User'
10
+ end
11
+ def model
12
+ drop
13
+ client.create_class 'User' do |c|
14
+ c.property 'username', :string, :mandatory => true
15
+ c.property 'name', :string, :mandatory => true
16
+ c.property 'admin', :boolean
17
+ end
18
+ end
19
+ def del
20
+ client.command 'DELETE FROM User'
21
+ end
22
+ def data
23
+ 1.upto(100000) do |i|
24
+ Orientdb4r::logger.info "...done: #{i}" if 0 == (i % 1000)
25
+ first_name = dg.word
26
+ surname = dg.word
27
+ begin
28
+ client.create_document({ '@class' => 'User', \
29
+ :username => "#{first_name}.#{surname}", \
30
+ :name => "#{first_name.capitalize} #{surname.capitalize}", \
31
+ :admin => (0 == rand(2)) })
32
+ rescue Exception => e
33
+ Orientdb4r::logger.error e
34
+ end
35
+ end
36
+ end
37
+
38
+ def product
39
+ 1.upto(500000) do |i|
40
+ Orientdb4r::logger.info "...done: #{i}" if 0 == (i % 100000)
41
+ name = dg.word
42
+ type = (rand(3) == 0) ? 'a' : 'b'
43
+ begin
44
+ client.command "insert into product cluster #{type} (name,type) values ('#{name}','#{type}')"
45
+ # client.command "insert into product_simple (name,type) values ('#{name}','#{type}')"
46
+ rescue Exception => e
47
+ Orientdb4r::logger.error e
48
+ end
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ c = FlatClassPerf.new
55
+ c.run
56
+ puts 'OK'
@@ -0,0 +1,87 @@
1
+ require 'orientdb4r'
2
+
3
+ module FStudy
4
+
5
+ ###
6
+ # This class represents a elaboration infrastructure.
7
+ class Case
8
+
9
+ attr_reader :dg
10
+
11
+ def initialize
12
+ @dg = DataGenerator.new
13
+ end
14
+
15
+ def db
16
+ 'temp' # default DB is 'temp'
17
+ end
18
+ def host
19
+ 'localhost'
20
+ end
21
+
22
+ def client
23
+ Orientdb4r.client :host => host
24
+ end
25
+
26
+ def watch method
27
+ start = Time.now
28
+ self.send method.to_sym
29
+ Orientdb4r::logger.info "method '#{method}' performed in #{Time.now - start} [s]"
30
+ end
31
+
32
+ def run
33
+ threads = []
34
+ thread_cnt = 1
35
+ thc = ARGV.select { |arg| arg if arg =~ /-th=\d+/ }
36
+ thread_cnt = thc[0][4..-1].to_i unless thc.empty?
37
+
38
+ if thread_cnt > 1
39
+ 1.upto(thread_cnt) do
40
+ threads << Thread.new do
41
+ run_threaded
42
+ end
43
+ end
44
+ else
45
+ run_threaded
46
+ end
47
+ threads.each { |th| th.join }
48
+ end
49
+
50
+
51
+ private
52
+
53
+ def run_threaded
54
+ Orientdb4r::logger.info "started thread #{Thread.current}"
55
+ client.connect :database => db, :user => 'admin', :password => 'admin'
56
+ ARGV.each do |arg|
57
+ watch arg[2..-1].to_sym if arg =~ /^--\w/
58
+ end
59
+ client.disconnect
60
+ end
61
+
62
+ end
63
+
64
+
65
+ class DataGenerator
66
+
67
+ def initialize
68
+ @words = IO.readlines('/usr/share/dict/words')
69
+ 0.upto(@words.size - 1) do |i|
70
+ word = @words[i]
71
+ word.strip!.downcase!
72
+ idx = word.index("'")
73
+ word = word[0..(idx - 1)] unless idx.nil?
74
+ @words[i] = word
75
+ end
76
+ @words.uniq!
77
+ Orientdb4r::logger.info "DataGenerator: #{@words.size} words"
78
+ end
79
+
80
+ # Gets a random word.
81
+ def word
82
+ @words[rand(@words.size)]
83
+ end
84
+
85
+ end
86
+
87
+ end
@@ -0,0 +1,256 @@
1
+ require 'study_case'
2
+
3
+ # This class represents model and data for Technical Feasibility Study.
4
+ # See here for more info:
5
+ # https://github.com/veny/orientdb4r/wiki/Technical-Feasibility
6
+ class TechnicalFeasibility < FStudy::Case
7
+
8
+ def db; 'perf'; end
9
+
10
+ # Dropes the document model.
11
+ def drop
12
+ classes_definition.reverse.each do |clazz|
13
+ client.drop_class clazz[:class]
14
+ puts "droped class: #{clazz[:class]}"
15
+ end
16
+ end
17
+
18
+ # Creates the document model.
19
+ def model
20
+ drop
21
+ classes_definition.each do |clazz|
22
+ class_name = clazz.delete :class
23
+ client.create_class(class_name, clazz)
24
+ puts "created class: #{class_name}"
25
+ end
26
+ end
27
+
28
+ # Deletes data.
29
+ def del
30
+ classes_definition.each do |clazz|
31
+ client.command "DELETE FROM #{clazz[:class]}"
32
+ puts "deleted from class: #{clazz[:class]}"
33
+ end
34
+ end
35
+
36
+ # Prepares data.
37
+ def data
38
+ communities = insert_communities
39
+ units = insert_org_units
40
+ users = insert_users(10000, units, communities)
41
+ insert_contacts(users, 7) # max pro user => ~ coeficient 4.0 pro user
42
+ contents = insert_contents(users, communities, 1.0) # coeficient pro user
43
+ insert_activities(users, communities, contents, 100) # coeficient pro user
44
+ end
45
+
46
+ def count
47
+ puts client.query 'SELECT count(*) FROM User'
48
+ end
49
+
50
+
51
+ private
52
+
53
+ def insert_communities
54
+ communities = [
55
+ { :name => 'Pianists' },
56
+ { :name => 'Violinists' },
57
+ { :name => 'Dog fanciers' },
58
+ { :name => 'Cat fanciers' },
59
+ { :name => 'Soccer fans' },
60
+ { :name => 'Ski fans' },
61
+ { :name => 'Basket fans' },
62
+ { :name => 'Gourmets' },
63
+ { :name => 'Scifi reader' },
64
+ { :name => 'Comic reader' }
65
+ ]
66
+
67
+ start = Time.now
68
+ communities.each do |c|
69
+ c['@class'] = 'Community'
70
+ c[:rid] = client.create_document(c)
71
+ end
72
+ puts "Created Communities: #{communities.size}, time = #{Time.now - start} [s]"
73
+ communities
74
+ end
75
+
76
+ def insert_org_units
77
+ units = [
78
+ { :name => 'BigCompany', :descendants => [ 'Automotive', 'Research', 'Infrastructure' ] },
79
+ { :name => 'Automotive', :descendants => [ 'Sales', 'Marketing', 'Design' ] },
80
+ { :name => 'Sales' },
81
+ { :name => 'Marketing' },
82
+ { :name => 'Design' },
83
+ { :name => 'Research', :descendants => [ 'Scientist', 'Spies' ] },
84
+ { :name => 'Scientist' },
85
+ { :name => 'Spies' },
86
+ { :name => 'Infrastructure', :descendants => [ 'Accounting', 'HumanResources' ] },
87
+ { :name => 'Accounting' },
88
+ { :name => 'HumanResources' , :descendants => [ 'Recruitment' ] },
89
+ { :name => 'Recruitment' }
90
+ ]
91
+
92
+ start = Time.now
93
+ units.each { |unit| insert_org_unit_helper(unit, units) }
94
+ puts "Created OrgUnits: #{units.size}, time = #{Time.now - start} [s]"
95
+ units
96
+ end
97
+ def insert_org_unit_helper(unit, all)
98
+ return if unit.include? :rid
99
+
100
+ if unit.include? :descendants
101
+ # recursion
102
+ unit[:descendants].each do |desc_name|
103
+ next_unit = all.select { |u| u if u[:name] == desc_name }[0]
104
+ insert_org_unit_helper(next_unit, all) unless next_unit.include? :rid
105
+ end
106
+ end
107
+
108
+ cloned = unit.clone
109
+ cloned['@class'] = 'OrgUnit'
110
+ cloned.delete :descendants
111
+
112
+ if unit.include? :descendants
113
+ descendants = []
114
+ unit[:descendants].each do |name|
115
+ descendants << all.select { |ou| ou if ou[:name] == name }[0][:rid]
116
+ end
117
+ cloned[:descendants] = descendants
118
+ end
119
+
120
+ rid = client.create_document(cloned)
121
+ unit[:rid] = rid
122
+ end
123
+
124
+ def insert_users(count, units, communities)
125
+ start = Time.now
126
+ users = []
127
+ 1.upto(count) do
128
+ firstname = dg.word
129
+ surname = dg.word
130
+ username = "#{firstname}.#{surname}"
131
+ # random distribution of Units (1) & Communities (0..3)
132
+ unit = units[rand(units.size)]
133
+ comms = []
134
+ 0.upto(rand(4)) { |i| comms << communities[rand(communities.size)][:rid] if i > 0 }
135
+
136
+ user = { '@class' => 'User', \
137
+ :username => username, \
138
+ :firstname => firstname.capitalize, \
139
+ :surname => surname.capitalize, \
140
+ :unit => unit[:rid], \
141
+ :communities => comms }
142
+ rid = client.create_document(user)
143
+ user[:rid] = rid
144
+ users << user
145
+ end
146
+ puts "Created Users: #{users.size}, time = #{Time.now - start} [s]"
147
+ users
148
+ end
149
+
150
+ def insert_contacts(users, max_contacts)
151
+ start = Time.now
152
+ count = 0
153
+ types = [:friend, :family, :coworker, :enemy]
154
+ 0.upto(users.size - 1) do |i|
155
+ a = users[i]
156
+ 0.upto(rand(max_contacts)) do
157
+ b = users[rand(users.size)]
158
+ client.create_document({'@class' => 'Contact', :a => a[:rid], :b => b[:rid], :type => rand(types.size)})
159
+ count += 1
160
+ end
161
+ end
162
+ puts "Created Contacts: #{count}, time = #{Time.now - start} [s]"
163
+ end
164
+
165
+ def insert_contents(users, communities, user_coef = 1.0)
166
+ start = Time.now
167
+ contents = []
168
+ classes = [['Article', 'body'], ['Gallery', 'description'], ['Term', 'topic']]
169
+ limit = (users.size * user_coef).to_i
170
+
171
+ 1.upto(limit) do
172
+ clazz = classes[rand(classes.size)]
173
+ content = {'@class' => clazz[0], :title => "#{dg.word} #{dg.word}", clazz[1] => dg.word}
174
+ # random distribution of Users (1) & Communities (0..3)
175
+ content[:author] = users[rand(users.size)][:rid]
176
+ comms = []
177
+ 0.upto(rand(4)) { |i| comms << communities[rand(communities.size)][:rid] if i > 0 }
178
+ content[:communities] = comms
179
+
180
+ rid = client.create_document(content)
181
+ content[:rid] = rid
182
+ contents << content
183
+ end
184
+ puts "Created ContentTypes: #{contents.size}, time = #{Time.now - start} [s]"
185
+ contents
186
+ end
187
+
188
+ def insert_activities(users, communities, contents, user_coef)
189
+ start = Time.now
190
+ types = [:login, :logout, :likeit, :rated, :saw, :commented]
191
+ limit = users.size * user_coef
192
+ 1.upto(limit) do |i|
193
+ puts "... #{i} #{Time.now - start}" if 0 == i % 100000
194
+ type = rand(types.size)
195
+ activity = { '@class' => 'Activity', :type => type, :stamp => (Time.now.to_i - rand(3600*23*30)) }
196
+ # random distribution of Users (1) & the same communities as user
197
+ user = users[rand(users.size)]
198
+ activity[:source] = user[:rid]
199
+ activity[:communities] = user[:communities]
200
+ # content
201
+ content = (types[type] == :login or types[type] == :logout) ? nil : contents[rand(contents.size)]
202
+ activity[content['@class'].downcase] = content[:rid] unless content.nil?
203
+
204
+ begin
205
+ client.create_document(activity)
206
+ rescue Exception => e
207
+ Orientdb4r::logger.error "problem storing index=#{i}, user=#{user.inspect}"
208
+ Orientdb4r::logger.error e
209
+ end
210
+ end
211
+ puts "Created Activities: #{limit}, time = #{Time.now - start} [s]"
212
+ end
213
+
214
+ def classes_definition
215
+ # TODO rdbms_id
216
+ [
217
+ { :class => 'OrgUnit', :properties => [
218
+ { :property => 'name', :type => :string, :mandatory => true },
219
+ # TODO domain
220
+ { :property => 'descendants', :type => :linkset, :linked_class => 'OrgUnit' }]},
221
+ { :class => 'Community', :properties => [
222
+ { :property => 'name', :type => :string, :mandatory => true }]},
223
+ { :class => 'User', :properties => [
224
+ { :property => 'username', :type => :string, :mandatory => true },
225
+ { :property => 'firstname', :type => :string, :mandatory => true },
226
+ { :property => 'surname', :type => :string, :mandatory => true },
227
+ # TODO roles
228
+ { :property => 'unit', :type => :link, :linked_class => 'OrgUnit', :mandatory => true },
229
+ { :property => 'communities', :type => :linkset, :linked_class => 'Community' }]},
230
+ { :class => 'Contact', :properties => [
231
+ { :property => 'type', :type => :integer, :mandatory => true },
232
+ { :property => 'a', :type => :link, :linked_class => 'User', :mandatory => true },
233
+ { :property => 'b', :type => :link, :linked_class => 'User', :mandatory => true }]},
234
+ { :class => 'Content', :properties => [
235
+ { :property => 'title', :type => :string, :mandatory => true },
236
+ { :property => 'author', :type => :link, :linked_class => 'User', :mandatory => true },
237
+ { :property => 'accessible_in', :type => :linkset, :linked_class => 'Community' }]},
238
+ { :class => 'Article', :extends => 'Content', :properties => [
239
+ { :property => 'body', :type => :string, :mandatory => true }]},
240
+ { :class => 'Gallery', :extends => 'Content', :properties => [
241
+ { :property => 'description', :type => :string, :mandatory => true }]},
242
+ { :class => 'Term', :extends => 'Content', :properties => [
243
+ { :property => 'topic', :type => :string, :mandatory => true }]},
244
+ { :class => 'Activity', :properties => [
245
+ { :property => 'type', :type => :integer, :mandatory => true },
246
+ { :property => 'stamp', :type => :integer, :mandatory => true },
247
+ { :property => 'source', :type => :link, :linked_class => 'User', :mandatory => true },
248
+ { :property => 'communities', :type => :linkset, :linked_class => 'Community' }]}
249
+ ]
250
+ end
251
+
252
+ end
253
+
254
+ c = TechnicalFeasibility.new
255
+ c.run
256
+ puts 'OK'