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.
Files changed (162) hide show
  1. data/LICENSE +20 -0
  2. data/README +104 -0
  3. data/acts_as_ferret.gemspec +58 -0
  4. data/bin/aaf_install +29 -0
  5. data/config/ferret_server.yml +24 -0
  6. data/doc/README.win32 +23 -0
  7. data/doc/demo/README +154 -0
  8. data/doc/demo/README_DEMO +23 -0
  9. data/doc/demo/Rakefile +10 -0
  10. data/doc/demo/app/controllers/admin/backend_controller.rb +14 -0
  11. data/doc/demo/app/controllers/admin_area_controller.rb +4 -0
  12. data/doc/demo/app/controllers/application.rb +5 -0
  13. data/doc/demo/app/controllers/contents_controller.rb +49 -0
  14. data/doc/demo/app/controllers/searches_controller.rb +8 -0
  15. data/doc/demo/app/helpers/admin/backend_helper.rb +2 -0
  16. data/doc/demo/app/helpers/application_helper.rb +3 -0
  17. data/doc/demo/app/helpers/content_helper.rb +2 -0
  18. data/doc/demo/app/helpers/search_helper.rb +2 -0
  19. data/doc/demo/app/models/comment.rb +48 -0
  20. data/doc/demo/app/models/content.rb +12 -0
  21. data/doc/demo/app/models/content_base.rb +28 -0
  22. data/doc/demo/app/models/search.rb +19 -0
  23. data/doc/demo/app/models/shared_index1.rb +3 -0
  24. data/doc/demo/app/models/shared_index2.rb +3 -0
  25. data/doc/demo/app/models/special_content.rb +3 -0
  26. data/doc/demo/app/models/stats.rb +20 -0
  27. data/doc/demo/app/views/admin/backend/search.rhtml +18 -0
  28. data/doc/demo/app/views/contents/_form.rhtml +10 -0
  29. data/doc/demo/app/views/contents/edit.rhtml +9 -0
  30. data/doc/demo/app/views/contents/index.rhtml +24 -0
  31. data/doc/demo/app/views/contents/new.rhtml +8 -0
  32. data/doc/demo/app/views/contents/show.rhtml +8 -0
  33. data/doc/demo/app/views/layouts/application.html.erb +17 -0
  34. data/doc/demo/app/views/searches/_content.html.erb +2 -0
  35. data/doc/demo/app/views/searches/search.html.erb +20 -0
  36. data/doc/demo/config/boot.rb +109 -0
  37. data/doc/demo/config/database.yml +38 -0
  38. data/doc/demo/config/environment.rb +69 -0
  39. data/doc/demo/config/environments/development.rb +16 -0
  40. data/doc/demo/config/environments/production.rb +19 -0
  41. data/doc/demo/config/environments/test.rb +21 -0
  42. data/doc/demo/config/ferret_server.yml +18 -0
  43. data/doc/demo/config/lighttpd.conf +40 -0
  44. data/doc/demo/config/routes.rb +9 -0
  45. data/doc/demo/db/development_structure.sql +15 -0
  46. data/doc/demo/db/migrate/001_initial_migration.rb +18 -0
  47. data/doc/demo/db/migrate/002_add_type_to_contents.rb +9 -0
  48. data/doc/demo/db/migrate/003_create_shared_index1s.rb +11 -0
  49. data/doc/demo/db/migrate/004_create_shared_index2s.rb +11 -0
  50. data/doc/demo/db/migrate/005_special_field.rb +9 -0
  51. data/doc/demo/db/migrate/006_create_stats.rb +15 -0
  52. data/doc/demo/db/schema.sql +18 -0
  53. data/doc/demo/db/schema.sqlite +14 -0
  54. data/doc/demo/doc/README_FOR_APP +2 -0
  55. data/doc/demo/doc/howto.txt +70 -0
  56. data/doc/demo/public/404.html +8 -0
  57. data/doc/demo/public/500.html +8 -0
  58. data/doc/demo/public/dispatch.cgi +10 -0
  59. data/doc/demo/public/dispatch.fcgi +24 -0
  60. data/doc/demo/public/dispatch.rb +10 -0
  61. data/doc/demo/public/favicon.ico +0 -0
  62. data/doc/demo/public/images/rails.png +0 -0
  63. data/doc/demo/public/index.html +277 -0
  64. data/doc/demo/public/robots.txt +1 -0
  65. data/doc/demo/public/stylesheets/scaffold.css +74 -0
  66. data/doc/demo/script/about +3 -0
  67. data/doc/demo/script/breakpointer +3 -0
  68. data/doc/demo/script/console +3 -0
  69. data/doc/demo/script/destroy +3 -0
  70. data/doc/demo/script/ferret_server +10 -0
  71. data/doc/demo/script/generate +3 -0
  72. data/doc/demo/script/performance/benchmarker +3 -0
  73. data/doc/demo/script/performance/profiler +3 -0
  74. data/doc/demo/script/plugin +3 -0
  75. data/doc/demo/script/process/inspector +3 -0
  76. data/doc/demo/script/process/reaper +3 -0
  77. data/doc/demo/script/process/spawner +3 -0
  78. data/doc/demo/script/process/spinner +3 -0
  79. data/doc/demo/script/runner +3 -0
  80. data/doc/demo/script/server +3 -0
  81. data/doc/demo/test/fixtures/comments.yml +12 -0
  82. data/doc/demo/test/fixtures/contents.yml +13 -0
  83. data/doc/demo/test/fixtures/remote_contents.yml +9 -0
  84. data/doc/demo/test/fixtures/shared_index1s.yml +7 -0
  85. data/doc/demo/test/fixtures/shared_index2s.yml +7 -0
  86. data/doc/demo/test/functional/admin/backend_controller_test.rb +35 -0
  87. data/doc/demo/test/functional/contents_controller_test.rb +81 -0
  88. data/doc/demo/test/functional/searches_controller_test.rb +71 -0
  89. data/doc/demo/test/smoke/drb_smoke_test.rb +321 -0
  90. data/doc/demo/test/smoke/process_stats.rb +21 -0
  91. data/doc/demo/test/test_helper.rb +30 -0
  92. data/doc/demo/test/unit/comment_test.rb +217 -0
  93. data/doc/demo/test/unit/content_test.rb +705 -0
  94. data/doc/demo/test/unit/ferret_result_test.rb +24 -0
  95. data/doc/demo/test/unit/multi_index_test.rb +329 -0
  96. data/doc/demo/test/unit/remote_index_test.rb +23 -0
  97. data/doc/demo/test/unit/shared_index1_test.rb +108 -0
  98. data/doc/demo/test/unit/shared_index2_test.rb +13 -0
  99. data/doc/demo/test/unit/sort_test.rb +21 -0
  100. data/doc/demo/test/unit/special_content_test.rb +25 -0
  101. data/doc/demo/vendor/plugins/will_paginate/LICENSE +18 -0
  102. data/doc/demo/vendor/plugins/will_paginate/README +108 -0
  103. data/doc/demo/vendor/plugins/will_paginate/Rakefile +23 -0
  104. data/doc/demo/vendor/plugins/will_paginate/init.rb +21 -0
  105. data/doc/demo/vendor/plugins/will_paginate/lib/will_paginate/collection.rb +45 -0
  106. data/doc/demo/vendor/plugins/will_paginate/lib/will_paginate/core_ext.rb +44 -0
  107. data/doc/demo/vendor/plugins/will_paginate/lib/will_paginate/finder.rb +159 -0
  108. data/doc/demo/vendor/plugins/will_paginate/lib/will_paginate/view_helpers.rb +95 -0
  109. data/doc/demo/vendor/plugins/will_paginate/test/array_pagination_test.rb +23 -0
  110. data/doc/demo/vendor/plugins/will_paginate/test/boot.rb +27 -0
  111. data/doc/demo/vendor/plugins/will_paginate/test/console +10 -0
  112. data/doc/demo/vendor/plugins/will_paginate/test/finder_test.rb +219 -0
  113. data/doc/demo/vendor/plugins/will_paginate/test/fixtures/admin.rb +3 -0
  114. data/doc/demo/vendor/plugins/will_paginate/test/fixtures/companies.yml +24 -0
  115. data/doc/demo/vendor/plugins/will_paginate/test/fixtures/company.rb +23 -0
  116. data/doc/demo/vendor/plugins/will_paginate/test/fixtures/developer.rb +11 -0
  117. data/doc/demo/vendor/plugins/will_paginate/test/fixtures/developers_projects.yml +13 -0
  118. data/doc/demo/vendor/plugins/will_paginate/test/fixtures/project.rb +4 -0
  119. data/doc/demo/vendor/plugins/will_paginate/test/fixtures/projects.yml +7 -0
  120. data/doc/demo/vendor/plugins/will_paginate/test/fixtures/replies.yml +20 -0
  121. data/doc/demo/vendor/plugins/will_paginate/test/fixtures/reply.rb +5 -0
  122. data/doc/demo/vendor/plugins/will_paginate/test/fixtures/schema.sql +44 -0
  123. data/doc/demo/vendor/plugins/will_paginate/test/fixtures/topic.rb +19 -0
  124. data/doc/demo/vendor/plugins/will_paginate/test/fixtures/topics.yml +30 -0
  125. data/doc/demo/vendor/plugins/will_paginate/test/fixtures/user.rb +2 -0
  126. data/doc/demo/vendor/plugins/will_paginate/test/fixtures/users.yml +35 -0
  127. data/doc/demo/vendor/plugins/will_paginate/test/helper.rb +42 -0
  128. data/doc/demo/vendor/plugins/will_paginate/test/lib/activerecord_test_connector.rb +64 -0
  129. data/doc/demo/vendor/plugins/will_paginate/test/lib/load_fixtures.rb +10 -0
  130. data/doc/demo/vendor/plugins/will_paginate/test/pagination_test.rb +136 -0
  131. data/doc/monit-example +22 -0
  132. data/init.rb +24 -0
  133. data/install.rb +18 -0
  134. data/lib/act_methods.rb +147 -0
  135. data/lib/acts_as_ferret.rb +593 -0
  136. data/lib/ar_mysql_auto_reconnect_patch.rb +41 -0
  137. data/lib/blank_slate.rb +54 -0
  138. data/lib/bulk_indexer.rb +56 -0
  139. data/lib/class_methods.rb +279 -0
  140. data/lib/ferret_extensions.rb +192 -0
  141. data/lib/ferret_find_methods.rb +142 -0
  142. data/lib/ferret_result.rb +58 -0
  143. data/lib/ferret_server.rb +238 -0
  144. data/lib/index.rb +99 -0
  145. data/lib/instance_methods.rb +172 -0
  146. data/lib/local_index.rb +202 -0
  147. data/lib/more_like_this.rb +217 -0
  148. data/lib/multi_index.rb +133 -0
  149. data/lib/rdig_adapter.rb +149 -0
  150. data/lib/remote_functions.rb +43 -0
  151. data/lib/remote_index.rb +54 -0
  152. data/lib/remote_multi_index.rb +20 -0
  153. data/lib/search_results.rb +50 -0
  154. data/lib/server_manager.rb +71 -0
  155. data/lib/unix_daemon.rb +86 -0
  156. data/lib/without_ar.rb +52 -0
  157. data/recipes/aaf_recipes.rb +116 -0
  158. data/script/ferret_daemon +94 -0
  159. data/script/ferret_server +12 -0
  160. data/script/ferret_service +178 -0
  161. data/tasks/ferret.rake +39 -0
  162. metadata +246 -0
@@ -0,0 +1,71 @@
1
+ ################################################################################
2
+ require 'optparse'
3
+
4
+ ################################################################################
5
+ $ferret_server_options = {
6
+ 'environment' => nil,
7
+ 'debug' => nil,
8
+ 'root' => nil
9
+ }
10
+
11
+ ################################################################################
12
+ OptionParser.new do |optparser|
13
+ optparser.banner = "Usage: #{File.basename($0)} [options] {start|stop|run}"
14
+
15
+ optparser.on('-h', '--help', "This message") do
16
+ puts optparser
17
+ exit
18
+ end
19
+
20
+ optparser.on('-R', '--root=PATH', 'Set RAILS_ROOT to the given string') do |r|
21
+ $ferret_server_options['root'] = r
22
+ end
23
+
24
+ optparser.on('-e', '--environment=NAME', 'Set RAILS_ENV to the given string') do |e|
25
+ $ferret_server_options['environment'] = e
26
+ end
27
+
28
+ optparser.on('--debug', 'Include full stack traces on exceptions') do
29
+ $ferret_server_options['debug'] = true
30
+ end
31
+
32
+ $ferret_server_action = optparser.permute!(ARGV)
33
+ (puts optparser; exit(1)) unless $ferret_server_action.size == 1
34
+
35
+ $ferret_server_action = $ferret_server_action.first
36
+ (puts optparser; exit(1)) unless %w(start stop run).include?($ferret_server_action)
37
+ end
38
+
39
+ ################################################################################
40
+
41
+ def determine_rails_root
42
+ possible_rails_roots = [
43
+ $ferret_server_options['root'],
44
+ (defined?(FERRET_SERVER) ? File.join(File.dirname(FERRET_SERVER), '..') : nil),
45
+ File.join(File.dirname(__FILE__), *(['..']*4)),
46
+ '.'
47
+ ].compact
48
+ # take the first dir where environment.rb can be found
49
+ possible_rails_roots.find{ |dir| File.readable?(File.join(dir, 'config', 'environment.rb')) }
50
+ end
51
+
52
+ begin
53
+ ENV['FERRET_USE_LOCAL_INDEX'] = 'true'
54
+ ENV['RAILS_ENV'] = $ferret_server_options['environment']
55
+ # determine RAILS_ROOT unless already set
56
+ RAILS_ROOT = determine_rails_root unless defined?(RAILS_ROOT)
57
+
58
+ begin
59
+ require File.join(RAILS_ROOT, 'config', 'environment')
60
+ rescue LoadError
61
+ puts "Unable to find Rails environment.rb in any of these locations:\n#{possible_rails_roots.join("\n")}\nPlease use the --root option of ferret_server to point it to your RAILS_ROOT."
62
+ raise $!
63
+ end
64
+
65
+ # require 'acts_as_ferret'
66
+ ActsAsFerret::Remote::Server.new.send($ferret_server_action)
67
+ rescue Exception => e
68
+ $stderr.puts(e.message)
69
+ $stderr.puts(e.backtrace.join("\n")) if $ferret_server_options['debug']
70
+ exit(1)
71
+ end
@@ -0,0 +1,86 @@
1
+ ################################################################################
2
+ module ActsAsFerret
3
+ module Remote
4
+
5
+ ################################################################################
6
+ # methods for becoming a daemon on Unix-like operating systems
7
+ module UnixDaemon
8
+
9
+ ################################################################################
10
+ def platform_daemon (&block)
11
+ safefork do
12
+ write_pid_file
13
+ trap("TERM") { exit(0) }
14
+ sess_id = Process.setsid
15
+ STDIN.reopen("/dev/null")
16
+ STDOUT.reopen("#{RAILS_ROOT}/log/ferret_server.out", "a")
17
+ STDERR.reopen(STDOUT)
18
+ block.call
19
+ end
20
+ end
21
+
22
+ ################################################################################
23
+ # stop the daemon, nicely at first, and then forcefully if necessary
24
+ def stop
25
+ pid = read_pid_file
26
+ raise "ferret_server doesn't appear to be running" unless pid
27
+ $stdout.puts("stopping ferret server...")
28
+ Process.kill("TERM", pid)
29
+ 30.times { Process.kill(0, pid); sleep(0.5) }
30
+ $stdout.puts("using kill -9 #{pid}")
31
+ Process.kill(9, pid)
32
+ rescue Errno::ESRCH => e
33
+ $stdout.puts("process #{pid} has stopped")
34
+ ensure
35
+ File.unlink(@cfg.pid_file) if File.exist?(@cfg.pid_file)
36
+ end
37
+
38
+ ################################################################################
39
+ def safefork (&block)
40
+ @fork_tries ||= 0
41
+ fork(&block)
42
+ rescue Errno::EWOULDBLOCK
43
+ raise if @fork_tries >= 20
44
+ @fork_tries += 1
45
+ sleep 5
46
+ retry
47
+ end
48
+
49
+ #################################################################################
50
+ # create the PID file and install an at_exit handler
51
+ def write_pid_file
52
+ ensure_stopped
53
+ open(@cfg.pid_file, "w") {|f| f << Process.pid << "\n"}
54
+ at_exit { File.unlink(@cfg.pid_file) if read_pid_file == Process.pid }
55
+ end
56
+
57
+ #################################################################################
58
+ def read_pid_file
59
+ File.read(@cfg.pid_file).to_i if File.exist?(@cfg.pid_file)
60
+ end
61
+
62
+ #################################################################################
63
+ def ensure_stopped
64
+ if pid = read_pid_file
65
+ if process_exists(pid)
66
+ raise "ferret_server may already be running, a pid file exists: #{@cfg.pid_file} and a ferret_server process exists with matching pid #{pid}"
67
+ else
68
+ $stdout.puts("removing stale pid file...")
69
+ File.unlink(@cfg.pid_file) if File.exist?(@cfg.pid_file)
70
+ end
71
+ end
72
+ end
73
+
74
+ #################################################################################
75
+ # Check for existence of ferret_server process with PID from pid file
76
+ # checked on ubuntu and OSX only
77
+ def process_exists(pid)
78
+ ps = IO.popen("ps -fp #{pid}", "r")
79
+ process = ps.to_a[1]
80
+ ps.close
81
+ process =~ /ferret_server/
82
+ end
83
+
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,52 @@
1
+ module ActsAsFerret
2
+
3
+ # Include this module to use acts_as_ferret with model classes
4
+ # not based on ActiveRecord.
5
+ #
6
+ # Implement the find_for_id(id) class method in your model class in
7
+ # order to make search work.
8
+ module WithoutAR
9
+ def self.included(target)
10
+ target.extend ClassMethods
11
+ target.extend ActsAsFerret::ActMethods
12
+ target.send :include, InstanceMethods
13
+ end
14
+
15
+ module ClassMethods
16
+ def logger
17
+ RAILS_DEFAULT_LOGGER
18
+ end
19
+ def table_name
20
+ self.name.underscore
21
+ end
22
+ def primary_key
23
+ 'id'
24
+ end
25
+ def find(what, args = {})
26
+ case what
27
+ when :all
28
+ ids = args[:conditions][1]
29
+ ids.map { |id| find id }
30
+ else
31
+ find_for_id what
32
+ end
33
+ end
34
+ def find_for_id(id)
35
+ raise NotImplementedError.new("implement find_for_id in class #{self.name}")
36
+ end
37
+ def count
38
+ 0
39
+ end
40
+ end
41
+
42
+ module InstanceMethods
43
+ def logger
44
+ self.class.logger
45
+ end
46
+ def new_record?
47
+ false
48
+ end
49
+ end
50
+ end
51
+
52
+ end
@@ -0,0 +1,116 @@
1
+ # Ferret DRb server Capistrano tasks
2
+ #
3
+ # Usage:
4
+ # in your Capfile, add acts_as_ferret's recipes directory to your load path and
5
+ # load the ferret tasks:
6
+ #
7
+ # load_paths << 'vendor/plugins/acts_as_ferret/recipes'
8
+ # load 'aaf_recipes'
9
+ #
10
+ # This will hook aaf's DRb start/stop tasks into the standard
11
+ # deploy:{start|restart|stop} tasks so the server will be restarted along with
12
+ # the rest of your application.
13
+ # Also an index directory in the shared folder will be created and symlinked
14
+ # into current/ when you deploy.
15
+ #
16
+ # In order to use the ferret:index:rebuild task, declare the indexes you intend to
17
+ # rebuild remotely in config/deploy.rb:
18
+ #
19
+ # set :ferret_indexes, %w( model another_model shared )
20
+ #
21
+ # HINT: To be very sure that your DRb server and application are always using
22
+ # the same model and schema versions, and you never lose any index updates because
23
+ # of the DRb server being restarted in that moment, use the following sequence
24
+ # to update your application:
25
+ #
26
+ # cap deploy:stop deploy:update deploy:migrate deploy:start
27
+ #
28
+ # That will stop the DRb server after stopping your application, and bring it
29
+ # up before starting the application again. Plus they'll never use different
30
+ # versions of model classes (which might happen otherwise)
31
+ # Downside: Your downtime is a bit longer than with the usual deploy, so be sure to
32
+ # put up some maintenance page for the meantime. Obviously this won't work if
33
+ # your migrations need acts_as_ferret (i.e. if you update model instances which
34
+ # would lead to index updates). In this case bring up the DRb server before
35
+ # running your migrations:
36
+ #
37
+ # cap deploy:stop deploy:update ferret:start deploy:migrate ferret:stop deploy:start
38
+ #
39
+ # Chances are that you're still not safe if your migrations not only modify the index,
40
+ # but also change the structure of your models. So just don't do both things in
41
+ # one go - I can't think of an easy way to handle this case automatically.
42
+ # Suggestions and patches are of course very welcome :-)
43
+
44
+ namespace :ferret do
45
+
46
+ desc "Stop the Ferret DRb server"
47
+ task :stop, :roles => :app do
48
+ rails_env = fetch(:rails_env, 'production')
49
+ ruby = fetch(:ruby, '/usr/bin/env ruby')
50
+ run "cd #{current_path}; #{ruby} script/ferret_server -e #{rails_env} --root #{current_path} stop || true"
51
+ end
52
+
53
+ desc "Start the Ferret DRb server"
54
+ task :start, :roles => :app do
55
+ rails_env = fetch(:rails_env, 'production')
56
+ ruby = fetch(:ruby, '/usr/bin/env ruby')
57
+ run "cd #{current_path}; #{ruby} script/ferret_server -e #{rails_env} --root #{current_path} start"
58
+ end
59
+
60
+ desc "Restart the Ferret DRb server"
61
+ task :restart, :roles => :app do
62
+ top.ferret.stop
63
+ sleep 1
64
+ top.ferret.start
65
+ end
66
+
67
+ namespace :index do
68
+
69
+ desc "Rebuild the Ferret index. See aaf_recipes.rb for instructions."
70
+ task :rebuild, :roles => :app do
71
+ rake = fetch(:rake, 'rake')
72
+ rails_env = fetch(:rails_env, 'production')
73
+ indexes = fetch(:ferret_indexes, [])
74
+ if indexes.any?
75
+ run "cd #{current_path}; LANG=da_DK.UTF-8 RAILS_ENV=#{rails_env} INDEXES='#{indexes.join(' ')}' #{rake} ferret:rebuild"
76
+ end
77
+ end
78
+
79
+ desc "purges all indexes for the current environment"
80
+ task :purge, :roles => :app do
81
+ run "rm -fr #{shared_path}/index/#{rails_env}"
82
+ end
83
+
84
+ desc "symlinks index folder"
85
+ task :symlink, :roles => :app do
86
+ run "mkdir -p #{shared_path}/index && rm -rf #{release_path}/index && ln -nfs #{shared_path}/index #{release_path}/index"
87
+ end
88
+
89
+ desc "Clean up old index versions"
90
+ task :cleanup, :roles => :app do
91
+ indexes = fetch(:ferret_indexes, [])
92
+ indexes.each do |index|
93
+ ferret_index_path = "#{shared_path}/index/#{rails_env}/#{index}"
94
+ releases = capture("ls -x #{ferret_index_path}").split.sort
95
+ count = 2
96
+ if count >= releases.length
97
+ logger.important "no old indexes to clean up"
98
+ else
99
+ logger.info "keeping #{count} of #{releases.length} indexes"
100
+ directories = (releases - releases.last(count)).map { |release|
101
+ File.join(ferret_index_path, release) }.join(" ")
102
+ sudo "rm -rf #{directories}"
103
+ end
104
+ end
105
+ end
106
+ end
107
+
108
+ end
109
+
110
+ after "deploy:stop", "ferret:stop"
111
+ before "deploy:start", "ferret:start"
112
+
113
+ before "deploy:restart", "ferret:stop"
114
+ after "deploy:restart", "ferret:start"
115
+ after "deploy:symlink", "ferret:index:symlink"
116
+
@@ -0,0 +1,94 @@
1
+ # Ferret Win32 Service Daemon, called by Win 32 service,
2
+ # created by Herryanto Siatono <herryanto@pluitsolutions.com>
3
+ #
4
+ # see doc/README.win32 for usage instructions
5
+ #
6
+ require 'optparse'
7
+ require 'win32/service'
8
+ include Win32
9
+
10
+ # Read options
11
+ options = {}
12
+ ARGV.options do |opts|
13
+ opts.banner = 'Usage: ferret_daemon [options]'
14
+ opts.on("-l", "--log FILE", "Daemon log file") {|file| options[:log] = file }
15
+ opts.on("-c","--console","Run Ferret server on console.") {options[:console] = true}
16
+ opts.on_tail("-h","--help", "Show this help message") {puts opts; exit}
17
+ opts.on("-e", "--environment ENV ", "Rails environment") {|env|
18
+ options[:environment] = env
19
+ ENV['RAILS_ENV'] = env
20
+ }
21
+ opts.parse!
22
+ end
23
+
24
+ require File.dirname(__FILE__) + '/../config/environment'
25
+
26
+ # Ferret Win32 Service Daemon, called by Win 32 service,
27
+ # to run on the console, use -c or --console option.
28
+ module Ferret
29
+ class FerretDaemon < Daemon
30
+ # Standard logger to redirect STDOUT and STDERR to a log file
31
+ class FerretStandardLogger
32
+ def initialize(logger)
33
+ @logger = logger
34
+ end
35
+
36
+ def write(s)
37
+ @logger.info s
38
+ end
39
+ end
40
+
41
+ def initialize(options={})
42
+ @options = options
43
+
44
+ # initialize logger
45
+ if options[:log]
46
+ @logger = Logger.new @options[:log]
47
+ else
48
+ @logger = Logger.new RAILS_ROOT + "/log/ferret_service_#{RAILS_ENV}.log"
49
+ end
50
+
51
+ # redirect stout and stderr to Ferret logger if running as windows service
52
+ $stdout = $stderr = FerretStandardLogger.new(@logger) unless @options[:console]
53
+
54
+ log "Initializing FerretDaemon..."
55
+ if @options[:console]
56
+ self.service_init
57
+ self.service_main
58
+ end
59
+ end
60
+
61
+ def service_main
62
+ log "Service main enterred..."
63
+
64
+ while running?
65
+ log "Listening..."
66
+ sleep
67
+ end
68
+
69
+ log "Service main exit..."
70
+ end
71
+
72
+ def service_init
73
+ log "Starting Ferret DRb server..."
74
+ ActsAsFerret::Remote::Server.start
75
+ log "FerretDaemon started."
76
+ end
77
+
78
+ def service_stop
79
+ log "Stopping service..."
80
+ DRb.stop_service
81
+ log "FerretDaemon stopped."
82
+ end
83
+
84
+ def log(msg)
85
+ @logger.info msg
86
+ puts msg if @options[:console]
87
+ end
88
+ end
89
+ end
90
+
91
+ if __FILE__ == $0
92
+ d = Ferret::FerretDaemon.new(options)
93
+ d.mainloop
94
+ end
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ FERRET_SERVER = File.expand_path(__FILE__)
4
+
5
+ begin
6
+ require File.join(File.dirname(__FILE__), '../vendor/plugins/acts_as_ferret/lib/server_manager')
7
+ rescue LoadError
8
+ # try the gem
9
+ require 'rubygems'
10
+ gem 'acts_as_ferret'
11
+ require 'server_manager'
12
+ end
@@ -0,0 +1,178 @@
1
+ # Ferret Win32 Service Daemon install script
2
+ # created by Herryanto Siatono <herryanto@pluitsolutions.com>
3
+ #
4
+ # see doc/README.win32 for usage instructions
5
+ #
6
+ require 'optparse'
7
+ require 'win32/service'
8
+ include Win32
9
+
10
+ module Ferret
11
+ # Parse and validate service command and options
12
+ class FerretServiceCommand
13
+ COMMANDS = ['install', 'remove', 'start', 'stop', 'help']
14
+ BANNER = "Usage: ruby script/ferret_service <command> [options]"
15
+
16
+ attr_reader :options, :command
17
+
18
+ def initialize
19
+ @options = {}
20
+ end
21
+
22
+ def valid_command?
23
+ COMMANDS.include?@command
24
+ end
25
+
26
+ def valid_options?
27
+ @options[:name] and !@options[:name].empty?
28
+ end
29
+
30
+ def print_command_list
31
+ puts BANNER
32
+ puts "\nAvailable commands:\n"
33
+ puts COMMANDS.map {|cmd| " - #{cmd}\n"}
34
+ puts "\nUse option -h for each command to help."
35
+ exit
36
+ end
37
+
38
+ def validate_options
39
+ errors = []
40
+ errors << "Service name is required." unless @options[:name]
41
+
42
+ if (errors.size > 0)
43
+ errors << "Error found. Use: 'ruby script/ferret_service #{@command} -h' for to get help."
44
+ puts errors.join("\n")
45
+ exit
46
+ end
47
+ end
48
+
49
+ def run(args)
50
+ @command = args.shift
51
+ @command = @command.dup.downcase if @command
52
+
53
+ # validate command and options
54
+ print_command_list unless valid_command? or @command == 'help'
55
+
56
+ opts_parser = create_options_parser
57
+ begin
58
+ opts_parser.parse!(args)
59
+ rescue OptionParser::ParseError => e
60
+ puts e
61
+ puts opts_parser
62
+ end
63
+
64
+ # validate required options
65
+ validate_options
66
+ end
67
+
68
+ def create_options_parser
69
+ opts_parser = OptionParser.new
70
+ opts_parser.banner = BANNER
71
+ opts_parser.on("-n", "--name=NAME", "Service name") {|name| @options[:name] = name }
72
+ opts_parser.on_tail("-t", "--trace", "Display stack trace when exception thrown") { @options[:trace] = true }
73
+ opts_parser.on_tail("-h", "--help", "Show this help message") { puts opts_parser; exit }
74
+
75
+ if ['install'].include?@command
76
+ opts_parser.on("-d", "--display=NAME", "Service display name") {|name| @options[:display] = name }
77
+
78
+ opts_parser.on("-l", "--log FILE", "Service log file") {|file| @options[:log] = file }
79
+ opts_parser.on("-e", "--environment ENV ", "Rails environment") { |env|
80
+ @options[:environment] = env
81
+ ENV['RAILS_ENV'] = env
82
+ }
83
+ end
84
+ opts_parser
85
+ end
86
+ end
87
+
88
+ # Install, Remove, Start and Stop Ferret DRb server Win32 service
89
+ class FerretService
90
+ FERRET_DAEMON = 'ferret_daemon'
91
+
92
+ def initialize
93
+ end
94
+
95
+ def install
96
+ svc = Service.new
97
+
98
+ begin
99
+ if Service.exists?(@options[:name])
100
+ puts "Service name '#{@options[:name]}' already exists."
101
+ return
102
+ end
103
+
104
+ svc.create_service do |s|
105
+ s.service_name = @options[:name]
106
+ s.display_name = @options[:display]
107
+ s.binary_path_name = binary_path_name
108
+ s.dependencies = []
109
+ end
110
+
111
+ svc.close
112
+ puts "'#{@options[:name]}' service installed."
113
+ rescue => e
114
+ handle_error(e)
115
+ end
116
+ end
117
+
118
+ def remove
119
+ begin
120
+ Service.stop(@options[:name])
121
+ rescue
122
+ end
123
+
124
+ begin
125
+ Service.delete(@options[:name])
126
+ puts "'#{@options[:name]}' service removed."
127
+ rescue => e
128
+ handle_error(e)
129
+ end
130
+ end
131
+
132
+ def start
133
+ begin
134
+ Service.start(@options[:name])
135
+ puts "'#{@options[:name]}' successfully started."
136
+ rescue => e
137
+ handle_error(e)
138
+ end
139
+ end
140
+
141
+ def stop
142
+ begin
143
+ Service.stop(@options[:name])
144
+ puts "'#{@options[:name]}' successfully stopped.\n"
145
+ rescue => e
146
+ handle_error(e)
147
+ end
148
+ end
149
+
150
+ def run(args)
151
+ svc_cmd = FerretServiceCommand.new
152
+ svc_cmd.run(args)
153
+ @options = svc_cmd.options
154
+ self.send(svc_cmd.command.to_sym)
155
+ end
156
+
157
+ protected
158
+ def handle_error(e)
159
+ if @options[:trace]
160
+ raise e
161
+ else
162
+ puts e
163
+ end
164
+ end
165
+
166
+ def binary_path_name
167
+ path = ""
168
+ path << "#{ENV['RUBY_HOME']}/bin/" if ENV['RUBY_HOME']
169
+ path << "ruby.exe "
170
+ path << File.expand_path("script/" + FERRET_DAEMON)
171
+ path << " -e #{@options[:environment]} " if @options[:environment]
172
+ path << " -l #{@options[:log]} " if @options[:log]
173
+ path
174
+ end
175
+ end
176
+ end
177
+
178
+ Ferret::FerretService.new.run(ARGV)