watson-acts_as_ferret 0.4.8.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README +104 -0
- data/acts_as_ferret.gemspec +58 -0
- data/bin/aaf_install +29 -0
- data/config/ferret_server.yml +24 -0
- data/doc/README.win32 +23 -0
- data/doc/demo/README +154 -0
- data/doc/demo/README_DEMO +23 -0
- data/doc/demo/Rakefile +10 -0
- data/doc/demo/app/controllers/admin/backend_controller.rb +14 -0
- data/doc/demo/app/controllers/admin_area_controller.rb +4 -0
- data/doc/demo/app/controllers/application.rb +5 -0
- data/doc/demo/app/controllers/contents_controller.rb +49 -0
- data/doc/demo/app/controllers/searches_controller.rb +8 -0
- data/doc/demo/app/helpers/admin/backend_helper.rb +2 -0
- data/doc/demo/app/helpers/application_helper.rb +3 -0
- data/doc/demo/app/helpers/content_helper.rb +2 -0
- data/doc/demo/app/helpers/search_helper.rb +2 -0
- data/doc/demo/app/models/comment.rb +48 -0
- data/doc/demo/app/models/content.rb +12 -0
- data/doc/demo/app/models/content_base.rb +28 -0
- data/doc/demo/app/models/search.rb +19 -0
- data/doc/demo/app/models/shared_index1.rb +3 -0
- data/doc/demo/app/models/shared_index2.rb +3 -0
- data/doc/demo/app/models/special_content.rb +3 -0
- data/doc/demo/app/models/stats.rb +20 -0
- data/doc/demo/app/views/admin/backend/search.rhtml +18 -0
- data/doc/demo/app/views/contents/_form.rhtml +10 -0
- data/doc/demo/app/views/contents/edit.rhtml +9 -0
- data/doc/demo/app/views/contents/index.rhtml +24 -0
- data/doc/demo/app/views/contents/new.rhtml +8 -0
- data/doc/demo/app/views/contents/show.rhtml +8 -0
- data/doc/demo/app/views/layouts/application.html.erb +17 -0
- data/doc/demo/app/views/searches/_content.html.erb +2 -0
- data/doc/demo/app/views/searches/search.html.erb +20 -0
- data/doc/demo/config/boot.rb +109 -0
- data/doc/demo/config/database.yml +38 -0
- data/doc/demo/config/environment.rb +69 -0
- data/doc/demo/config/environments/development.rb +16 -0
- data/doc/demo/config/environments/production.rb +19 -0
- data/doc/demo/config/environments/test.rb +21 -0
- data/doc/demo/config/ferret_server.yml +18 -0
- data/doc/demo/config/lighttpd.conf +40 -0
- data/doc/demo/config/routes.rb +9 -0
- data/doc/demo/db/development_structure.sql +15 -0
- data/doc/demo/db/migrate/001_initial_migration.rb +18 -0
- data/doc/demo/db/migrate/002_add_type_to_contents.rb +9 -0
- data/doc/demo/db/migrate/003_create_shared_index1s.rb +11 -0
- data/doc/demo/db/migrate/004_create_shared_index2s.rb +11 -0
- data/doc/demo/db/migrate/005_special_field.rb +9 -0
- data/doc/demo/db/migrate/006_create_stats.rb +15 -0
- data/doc/demo/db/schema.sql +18 -0
- data/doc/demo/db/schema.sqlite +14 -0
- data/doc/demo/doc/README_FOR_APP +2 -0
- data/doc/demo/doc/howto.txt +70 -0
- data/doc/demo/public/404.html +8 -0
- data/doc/demo/public/500.html +8 -0
- data/doc/demo/public/dispatch.cgi +10 -0
- data/doc/demo/public/dispatch.fcgi +24 -0
- data/doc/demo/public/dispatch.rb +10 -0
- data/doc/demo/public/favicon.ico +0 -0
- data/doc/demo/public/images/rails.png +0 -0
- data/doc/demo/public/index.html +277 -0
- data/doc/demo/public/robots.txt +1 -0
- data/doc/demo/public/stylesheets/scaffold.css +74 -0
- data/doc/demo/script/about +3 -0
- data/doc/demo/script/breakpointer +3 -0
- data/doc/demo/script/console +3 -0
- data/doc/demo/script/destroy +3 -0
- data/doc/demo/script/ferret_server +10 -0
- data/doc/demo/script/generate +3 -0
- data/doc/demo/script/performance/benchmarker +3 -0
- data/doc/demo/script/performance/profiler +3 -0
- data/doc/demo/script/plugin +3 -0
- data/doc/demo/script/process/inspector +3 -0
- data/doc/demo/script/process/reaper +3 -0
- data/doc/demo/script/process/spawner +3 -0
- data/doc/demo/script/process/spinner +3 -0
- data/doc/demo/script/runner +3 -0
- data/doc/demo/script/server +3 -0
- data/doc/demo/test/fixtures/comments.yml +12 -0
- data/doc/demo/test/fixtures/contents.yml +13 -0
- data/doc/demo/test/fixtures/remote_contents.yml +9 -0
- data/doc/demo/test/fixtures/shared_index1s.yml +7 -0
- data/doc/demo/test/fixtures/shared_index2s.yml +7 -0
- data/doc/demo/test/functional/admin/backend_controller_test.rb +35 -0
- data/doc/demo/test/functional/contents_controller_test.rb +81 -0
- data/doc/demo/test/functional/searches_controller_test.rb +71 -0
- data/doc/demo/test/smoke/drb_smoke_test.rb +321 -0
- data/doc/demo/test/smoke/process_stats.rb +21 -0
- data/doc/demo/test/test_helper.rb +30 -0
- data/doc/demo/test/unit/comment_test.rb +217 -0
- data/doc/demo/test/unit/content_test.rb +705 -0
- data/doc/demo/test/unit/ferret_result_test.rb +24 -0
- data/doc/demo/test/unit/multi_index_test.rb +329 -0
- data/doc/demo/test/unit/remote_index_test.rb +23 -0
- data/doc/demo/test/unit/shared_index1_test.rb +108 -0
- data/doc/demo/test/unit/shared_index2_test.rb +13 -0
- data/doc/demo/test/unit/sort_test.rb +21 -0
- data/doc/demo/test/unit/special_content_test.rb +25 -0
- data/doc/demo/vendor/plugins/will_paginate/LICENSE +18 -0
- data/doc/demo/vendor/plugins/will_paginate/README +108 -0
- data/doc/demo/vendor/plugins/will_paginate/Rakefile +23 -0
- data/doc/demo/vendor/plugins/will_paginate/init.rb +21 -0
- data/doc/demo/vendor/plugins/will_paginate/lib/will_paginate/collection.rb +45 -0
- data/doc/demo/vendor/plugins/will_paginate/lib/will_paginate/core_ext.rb +44 -0
- data/doc/demo/vendor/plugins/will_paginate/lib/will_paginate/finder.rb +159 -0
- data/doc/demo/vendor/plugins/will_paginate/lib/will_paginate/view_helpers.rb +95 -0
- data/doc/demo/vendor/plugins/will_paginate/test/array_pagination_test.rb +23 -0
- data/doc/demo/vendor/plugins/will_paginate/test/boot.rb +27 -0
- data/doc/demo/vendor/plugins/will_paginate/test/console +10 -0
- data/doc/demo/vendor/plugins/will_paginate/test/finder_test.rb +219 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/admin.rb +3 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/companies.yml +24 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/company.rb +23 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/developer.rb +11 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/developers_projects.yml +13 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/project.rb +4 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/projects.yml +7 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/replies.yml +20 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/reply.rb +5 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/schema.sql +44 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/topic.rb +19 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/topics.yml +30 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/user.rb +2 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/users.yml +35 -0
- data/doc/demo/vendor/plugins/will_paginate/test/helper.rb +42 -0
- data/doc/demo/vendor/plugins/will_paginate/test/lib/activerecord_test_connector.rb +64 -0
- data/doc/demo/vendor/plugins/will_paginate/test/lib/load_fixtures.rb +10 -0
- data/doc/demo/vendor/plugins/will_paginate/test/pagination_test.rb +136 -0
- data/doc/monit-example +22 -0
- data/init.rb +24 -0
- data/install.rb +18 -0
- data/lib/act_methods.rb +147 -0
- data/lib/acts_as_ferret.rb +593 -0
- data/lib/ar_mysql_auto_reconnect_patch.rb +41 -0
- data/lib/blank_slate.rb +54 -0
- data/lib/bulk_indexer.rb +56 -0
- data/lib/class_methods.rb +279 -0
- data/lib/ferret_extensions.rb +192 -0
- data/lib/ferret_find_methods.rb +142 -0
- data/lib/ferret_result.rb +58 -0
- data/lib/ferret_server.rb +238 -0
- data/lib/index.rb +99 -0
- data/lib/instance_methods.rb +172 -0
- data/lib/local_index.rb +202 -0
- data/lib/more_like_this.rb +217 -0
- data/lib/multi_index.rb +133 -0
- data/lib/rdig_adapter.rb +149 -0
- data/lib/remote_functions.rb +43 -0
- data/lib/remote_index.rb +54 -0
- data/lib/remote_multi_index.rb +20 -0
- data/lib/search_results.rb +50 -0
- data/lib/server_manager.rb +71 -0
- data/lib/unix_daemon.rb +86 -0
- data/lib/without_ar.rb +52 -0
- data/recipes/aaf_recipes.rb +116 -0
- data/script/ferret_daemon +94 -0
- data/script/ferret_server +12 -0
- data/script/ferret_service +178 -0
- data/tasks/ferret.rake +39 -0
- metadata +246 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../test_helper'
|
2
|
+
require 'admin/backend_controller'
|
3
|
+
|
4
|
+
# Re-raise errors caught by the controller.
|
5
|
+
class Admin::BackendController; def rescue_action(e) raise e end; end
|
6
|
+
|
7
|
+
class Admin::BackendControllerTest < Test::Unit::TestCase
|
8
|
+
def setup
|
9
|
+
@controller = Admin::BackendController.new
|
10
|
+
@request = ActionController::TestRequest.new
|
11
|
+
@response = ActionController::TestResponse.new
|
12
|
+
Content.destroy_all
|
13
|
+
Content.create(:title => 'my title', :description => 'a little bit of content')
|
14
|
+
end
|
15
|
+
|
16
|
+
def teardown
|
17
|
+
Content.destroy_all
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_search
|
21
|
+
get :search
|
22
|
+
assert_response :success
|
23
|
+
assert_template 'search'
|
24
|
+
assert_nil assigns(:results)
|
25
|
+
|
26
|
+
post :search, :query => 'title'
|
27
|
+
assert_template 'search'
|
28
|
+
assert_equal 1, assigns(:results).size
|
29
|
+
|
30
|
+
post :search, :query => 'monkey'
|
31
|
+
assert_template 'search'
|
32
|
+
assert assigns(:results).empty?
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
require 'contents_controller'
|
3
|
+
|
4
|
+
# Re-raise errors caught by the controller.
|
5
|
+
class ContentsController; def rescue_action(e) raise e end; end
|
6
|
+
|
7
|
+
class ContentsControllerTest < Test::Unit::TestCase
|
8
|
+
fixtures :contents
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@controller = ContentsController.new
|
12
|
+
@request = ActionController::TestRequest.new
|
13
|
+
@response = ActionController::TestResponse.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_index
|
17
|
+
get :index
|
18
|
+
assert_response :success
|
19
|
+
assert_template 'index'
|
20
|
+
assert_not_nil assigns(:contents)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_show
|
24
|
+
get :show, :id => 1
|
25
|
+
|
26
|
+
assert_response :success
|
27
|
+
assert_template 'show'
|
28
|
+
|
29
|
+
assert_not_nil assigns(:content)
|
30
|
+
assert assigns(:content).valid?
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_new
|
34
|
+
get :new
|
35
|
+
|
36
|
+
assert_response :success
|
37
|
+
assert_template 'new'
|
38
|
+
|
39
|
+
assert_not_nil assigns(:content)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_create
|
43
|
+
num_contents = Content.count
|
44
|
+
|
45
|
+
post :create, :content => {}
|
46
|
+
|
47
|
+
assert_response :redirect
|
48
|
+
assert_redirected_to contents_url
|
49
|
+
|
50
|
+
assert_equal num_contents + 1, Content.count
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_edit
|
54
|
+
get :edit, :id => 1
|
55
|
+
|
56
|
+
assert_response :success
|
57
|
+
assert_template 'edit'
|
58
|
+
|
59
|
+
assert_not_nil assigns(:content)
|
60
|
+
assert assigns(:content).valid?
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_update
|
64
|
+
post :update, :id => 1
|
65
|
+
assert_response :redirect
|
66
|
+
assert_redirected_to :action => 'show', :id => 1
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_destroy
|
70
|
+
assert_not_nil Content.find(1)
|
71
|
+
|
72
|
+
post :destroy, :id => 1
|
73
|
+
assert_response :redirect
|
74
|
+
assert_redirected_to :action => 'list'
|
75
|
+
|
76
|
+
assert_raise(ActiveRecord::RecordNotFound) {
|
77
|
+
Content.find(1)
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
require 'searches_controller'
|
3
|
+
|
4
|
+
# Re-raise errors caught by the controller.
|
5
|
+
class SearchesController; def rescue_action(e) raise e end; end
|
6
|
+
|
7
|
+
class SearchesControllerTest < Test::Unit::TestCase
|
8
|
+
fixtures :contents
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@controller = SearchesController.new
|
12
|
+
@request = ActionController::TestRequest.new
|
13
|
+
@response = ActionController::TestResponse.new
|
14
|
+
ContentBase.rebuild_index
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_search
|
18
|
+
get :search
|
19
|
+
assert_template 'search'
|
20
|
+
assert_response :success
|
21
|
+
assert_nil assigns(:results)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_search
|
25
|
+
get :search, :q => 'title'
|
26
|
+
assert_template 'search'
|
27
|
+
assert_equal 1, assigns(:results).total_hits
|
28
|
+
assert_equal 1, assigns(:results).size
|
29
|
+
|
30
|
+
get :search, :q => 'monkey'
|
31
|
+
assert_template 'search'
|
32
|
+
assert assigns(:results).empty?
|
33
|
+
|
34
|
+
# check that model changes are picked up by the searcher (searchers have to
|
35
|
+
# be reopened to reflect changes done to the index)
|
36
|
+
# wait for the searcher to age a bit (it seems fs timestamp resolution is
|
37
|
+
# only 1 sec)
|
38
|
+
sleep 1
|
39
|
+
Content.create :title => 'another content object', :description => 'description goes hers'
|
40
|
+
get :search, :q => 'another'
|
41
|
+
assert_template 'search'
|
42
|
+
assert_equal 1, assigns(:results).total_hits
|
43
|
+
assert_equal 1, assigns(:results).size
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_pagination
|
48
|
+
Content.destroy_all
|
49
|
+
30.times do |i|
|
50
|
+
Content.create! :title => "title of Content #{i}", :description => "#{i}"
|
51
|
+
end
|
52
|
+
get :search, :q => 'title'
|
53
|
+
r = assigns(:results)
|
54
|
+
assert_equal 30, r.total_hits
|
55
|
+
assert_equal 10, r.size
|
56
|
+
assert_equal "title of Content 0", r.first.title
|
57
|
+
assert_equal "title of Content 9", r.last.title
|
58
|
+
assert_equal 1, r.current_page
|
59
|
+
assert_equal 3, r.page_count
|
60
|
+
|
61
|
+
get :search, :q => 'title', :page => 2
|
62
|
+
r = assigns(:results)
|
63
|
+
assert_equal 30, r.total_hits
|
64
|
+
assert_equal 10, r.size
|
65
|
+
assert_equal "title of Content 10", r.first.title
|
66
|
+
assert_equal "title of Content 19", r.last.title
|
67
|
+
assert_equal 2, r.current_page
|
68
|
+
assert_equal 3, r.page_count
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,321 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'benchmark'
|
3
|
+
require 'gruff'
|
4
|
+
|
5
|
+
# Simple smoke test for the DRb server
|
6
|
+
# usage:
|
7
|
+
#
|
8
|
+
# # start the DRb server
|
9
|
+
# script/ferret_server -e test start
|
10
|
+
#
|
11
|
+
# # run the script
|
12
|
+
# AAF_REMOTE=true script/runner -e test test/smoke/drb_smoke_test.rb
|
13
|
+
|
14
|
+
module DrbSmokeTest
|
15
|
+
|
16
|
+
RECORDS_PER_PROCESS = 100000
|
17
|
+
NUM_PROCESSES = 10 # should be an even number
|
18
|
+
NUM_DOCS = 50
|
19
|
+
NUM_TERMS = 600
|
20
|
+
START_TIME = Time.now
|
21
|
+
|
22
|
+
class Words
|
23
|
+
DICTIONARY = '/usr/share/dict/words'
|
24
|
+
def initialize
|
25
|
+
@words = []
|
26
|
+
File.open(DICTIONARY) do |file|
|
27
|
+
file.each_line do |word|
|
28
|
+
@words << word.strip unless word =~ /'/
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
"#{@words.size} words"
|
35
|
+
end
|
36
|
+
|
37
|
+
def random_word
|
38
|
+
@words[rand(@words.size)]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
puts "compiling sample documents..."
|
43
|
+
WORDS = Words.new
|
44
|
+
puts WORDS
|
45
|
+
DOCUMENTS = []
|
46
|
+
|
47
|
+
NUM_DOCS.times do
|
48
|
+
doc = ''
|
49
|
+
NUM_TERMS.times { doc << WORDS.random_word << ' ' }
|
50
|
+
DOCUMENTS << doc
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.random_document
|
54
|
+
DOCUMENTS[rand(DOCUMENTS.size)]
|
55
|
+
end
|
56
|
+
|
57
|
+
puts "built #{NUM_DOCS} documents with an avg. size of #{DOCUMENTS.join.size / NUM_DOCS} Bytes."
|
58
|
+
|
59
|
+
class Monitor
|
60
|
+
class << self
|
61
|
+
def count_connections
|
62
|
+
res = Content.connection.execute("show status where variable_name = 'Threads_connected'")
|
63
|
+
if res
|
64
|
+
res.fetch_row.last
|
65
|
+
else
|
66
|
+
"error getting connection count"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
def writers_running?
|
70
|
+
Dir['*.finished'].size < (NUM_PROCESSES/2)
|
71
|
+
end
|
72
|
+
def running?
|
73
|
+
Dir['*.finished'].size < NUM_PROCESSES
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class WorkerBase
|
79
|
+
def initialize(id)
|
80
|
+
@id = id
|
81
|
+
end
|
82
|
+
|
83
|
+
# time since startup in msec
|
84
|
+
def get_time
|
85
|
+
((Time.now - START_TIME)*1000).to_i
|
86
|
+
end
|
87
|
+
|
88
|
+
def log(data)
|
89
|
+
data << get_time
|
90
|
+
@logfile << data.join(',') << "\n"
|
91
|
+
end
|
92
|
+
|
93
|
+
def log_finished
|
94
|
+
File.open("#{@id}.finished", 'w') do |f|
|
95
|
+
f << "finished at #{Time.now}\n"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def clear_logs
|
100
|
+
FileUtils.rm_f "#{@id}.*"
|
101
|
+
end
|
102
|
+
|
103
|
+
def run
|
104
|
+
File.open("#{self.class.prefix}_#{@id}.log",'w') do |f|
|
105
|
+
clear_logs
|
106
|
+
sleep 1 # allow other processes to get ready
|
107
|
+
@logfile = f
|
108
|
+
do_run
|
109
|
+
log_finished
|
110
|
+
puts "#{@id} finished"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
class Writer < WorkerBase
|
117
|
+
def self.prefix; 'writer' end
|
118
|
+
def do_run
|
119
|
+
log_interval = RECORDS_PER_PROCESS / 100
|
120
|
+
RECORDS_PER_PROCESS.times do |i|
|
121
|
+
log create_record(i)
|
122
|
+
if i % log_interval == 0
|
123
|
+
# log progress
|
124
|
+
puts "#{@id}: #{i} records indexed"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def create_record(i)
|
130
|
+
time = Benchmark.realtime do
|
131
|
+
Content.create! :title => "record #{@id} / #{i}", :description => DrbSmokeTest::random_document
|
132
|
+
end
|
133
|
+
[ time ]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
class Searcher < WorkerBase
|
138
|
+
def self.prefix; 'searcher' end
|
139
|
+
def do_run
|
140
|
+
while Monitor::writers_running?
|
141
|
+
# search with concurrent writes
|
142
|
+
log do_search
|
143
|
+
end
|
144
|
+
t = Time.now
|
145
|
+
while (Time.now - t) < 2.minutes
|
146
|
+
# the writers have finished, now hammer the server with searches for another 5 minutes
|
147
|
+
log do_search
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# run a search and log it's results.
|
152
|
+
# Search is done with a query consisting of the term 'findme'
|
153
|
+
# (which is guaranteed to yield 20 results) and a random term from
|
154
|
+
# the word list, ORed together
|
155
|
+
def do_search
|
156
|
+
result = nil
|
157
|
+
query = "findme OR #{WORDS.random_word}"
|
158
|
+
time = Benchmark.realtime do
|
159
|
+
result = Content.find_id_by_contents query
|
160
|
+
end
|
161
|
+
# time, no of hits
|
162
|
+
[ time, result.first, query ]
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def self.run
|
167
|
+
@start = Time.now
|
168
|
+
|
169
|
+
NUM_PROCESSES.times do |i|
|
170
|
+
unless fork
|
171
|
+
@id = i
|
172
|
+
break
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
if @id
|
177
|
+
@id.even? ? Writer.new(@id).run : Searcher.new(@id).run
|
178
|
+
else
|
179
|
+
|
180
|
+
# create some records to search for
|
181
|
+
20.times do |i|
|
182
|
+
Content.create! :title => "to find #{i}", :description => ("findme #{i} " << random_document)
|
183
|
+
end
|
184
|
+
|
185
|
+
while Monitor::running?
|
186
|
+
puts "open connections: #{Monitor::count_connections}; time elapsed: #{Time.now - @start} seconds"
|
187
|
+
sleep 10
|
188
|
+
end
|
189
|
+
puts "doing the math now..."
|
190
|
+
DrbSmokeTest::Stats.new(DrbSmokeTest::Writer::prefix).run
|
191
|
+
DrbSmokeTest::Stats.new(DrbSmokeTest::Searcher::prefix).run
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
module Statistics
|
196
|
+
def odd?(value)
|
197
|
+
value % 2 == 1
|
198
|
+
end
|
199
|
+
|
200
|
+
def median(population)
|
201
|
+
if odd?(population.size)
|
202
|
+
population[population.size/2]
|
203
|
+
else
|
204
|
+
mean [ population[population.size/2-1], population[population.size/2] ]
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def mean(population)
|
209
|
+
sum = population.inject(0) { |sum, v| sum + v }
|
210
|
+
sum / population.size.to_f
|
211
|
+
end
|
212
|
+
|
213
|
+
# variance and standard_deviation methods from
|
214
|
+
# http://warrenseen.com/blog/2006/03/13/how-to-calculate-standard-deviation/
|
215
|
+
def variance(population)
|
216
|
+
n = 0
|
217
|
+
mean = 0.0
|
218
|
+
s = 0.0
|
219
|
+
population.each { |x|
|
220
|
+
n = n + 1
|
221
|
+
delta = x - mean
|
222
|
+
mean = mean + (delta / n)
|
223
|
+
s = s + delta * (x - mean)
|
224
|
+
}
|
225
|
+
# if you want to calculate std deviation
|
226
|
+
# of a sample change this to "s / (n-1)"
|
227
|
+
return s / n
|
228
|
+
end
|
229
|
+
|
230
|
+
# calculate the standard deviation of a population
|
231
|
+
# accepts: an array, the population
|
232
|
+
# returns: the standard deviation
|
233
|
+
def standard_deviation(population)
|
234
|
+
Math.sqrt(variance(population))
|
235
|
+
rescue
|
236
|
+
puts "pop: #{population.inspect}"
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
class Stats
|
241
|
+
include Statistics
|
242
|
+
|
243
|
+
def initialize(prefix)
|
244
|
+
@prefix = prefix
|
245
|
+
@stats = []
|
246
|
+
end
|
247
|
+
|
248
|
+
def collect_stats
|
249
|
+
Dir["#{@prefix}_*.log"].each do |logfile|
|
250
|
+
puts logfile
|
251
|
+
File.open(logfile) do |f|
|
252
|
+
while line = f.gets
|
253
|
+
row = line.split(',')
|
254
|
+
row[row.size-1] = row.last.to_i
|
255
|
+
@stats << row
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
puts "#{@stats.size} lines read, now sorting..."
|
260
|
+
@stats.sort! { |row1, row2| row1.last <=> row2.last }
|
261
|
+
end
|
262
|
+
|
263
|
+
def with_segments(segment_count)
|
264
|
+
t0 = @stats.first.last.to_i
|
265
|
+
t1 = @stats.last.last.to_i
|
266
|
+
timespan = t1 - t0
|
267
|
+
puts "test run took: #{timespan/1000} seconds"
|
268
|
+
# we want to draw 1000 points, determine which timespan one point covers
|
269
|
+
segment_length = timespan / segment_count
|
270
|
+
t = 0
|
271
|
+
i = 0
|
272
|
+
while t <= t1
|
273
|
+
t += segment_length
|
274
|
+
segment_stats = []
|
275
|
+
while @stats.any? && @stats.first.last.to_i < t
|
276
|
+
segment_stats << @stats.shift
|
277
|
+
end
|
278
|
+
yield segment_stats unless segment_stats.empty?
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
def run
|
283
|
+
collect_stats
|
284
|
+
segments = []
|
285
|
+
with_segments(500) do |segment_stats|
|
286
|
+
segments << process_segment(segment_stats)
|
287
|
+
end
|
288
|
+
|
289
|
+
chart("#{@prefix} mean", "#{@prefix.downcase}_mean") do |g|
|
290
|
+
g.data :mean, segments.map{ |row| row[0] }
|
291
|
+
g.data :stddev, segments.map{ |row| row[1] }
|
292
|
+
end
|
293
|
+
chart("#{@prefix} median", "#{@prefix.downcase}_median") do |g|
|
294
|
+
g.data :median, segments.map{ |row| row[2] }
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
def process_segment(segment)
|
299
|
+
times = segment.map{|row|row.first.to_i * 1000}
|
300
|
+
[mean(times), standard_deviation(times), median(times), segment.size]
|
301
|
+
end
|
302
|
+
|
303
|
+
def chart(title, fname)
|
304
|
+
g = Gruff::Line.new do |g|
|
305
|
+
g.title = title
|
306
|
+
g.theme = {
|
307
|
+
:background_colors => ["#e6e6e6", "#e6e6e6"],
|
308
|
+
:colors => ["#ff43a7", '#666666', 'black', 'white', 'grey'],
|
309
|
+
:marker_color => "white"
|
310
|
+
}
|
311
|
+
end
|
312
|
+
yield g
|
313
|
+
g.write "#{fname}.png"
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
end
|
318
|
+
|
319
|
+
|
320
|
+
DrbSmokeTest::run
|
321
|
+
|