sdsykes_acts_as_ferret 0.4.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README +51 -0
- data/bin/aaf_install +25 -0
- data/config/ferret_server.yml +23 -0
- data/doc/README.win32 +23 -0
- data/doc/monit-example +22 -0
- data/init.rb +22 -0
- data/install.rb +18 -0
- data/lib/act_methods.rb +254 -0
- data/lib/acts_as_ferret.rb +151 -0
- data/lib/bulk_indexer.rb +35 -0
- data/lib/class_methods.rb +459 -0
- data/lib/ferret_cap_tasks.rb +21 -0
- data/lib/ferret_extensions.rb +115 -0
- data/lib/ferret_result.rb +36 -0
- data/lib/ferret_server.rb +203 -0
- data/lib/index.rb +31 -0
- data/lib/instance_methods.rb +156 -0
- data/lib/local_index.rb +211 -0
- data/lib/more_like_this.rb +217 -0
- data/lib/multi_index.rb +83 -0
- data/lib/remote_index.rb +50 -0
- data/lib/search_results.rb +53 -0
- data/lib/server_manager.rb +46 -0
- data/lib/shared_index.rb +14 -0
- data/lib/shared_index_class_methods.rb +90 -0
- data/lib/unix_daemon.rb +63 -0
- data/script/ferret_daemon +94 -0
- data/script/ferret_server +10 -0
- data/script/ferret_service +178 -0
- data/sdsykes_acts_as_ferret.gemspec +21 -0
- metadata +99 -0
data/lib/remote_index.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'drb'
|
2
|
+
module ActsAsFerret
|
3
|
+
|
4
|
+
# This index implementation connects to a remote ferret server instance. It
|
5
|
+
# basically forwards all calls to the remote server.
|
6
|
+
class RemoteIndex < AbstractIndex
|
7
|
+
|
8
|
+
def initialize(config)
|
9
|
+
@config = config
|
10
|
+
@ferret_config = config[:ferret]
|
11
|
+
@server = DRbObject.new(nil, config[:remote])
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(method_name, *args)
|
15
|
+
args.unshift model_class_name
|
16
|
+
@server.send(method_name, *args)
|
17
|
+
end
|
18
|
+
|
19
|
+
def find_id_by_contents(q, options = {}, &proc)
|
20
|
+
total_hits, results = @server.find_id_by_contents(model_class_name, q, options)
|
21
|
+
block_given? ? yield_results(total_hits, results, &proc) : [ total_hits, results ]
|
22
|
+
end
|
23
|
+
|
24
|
+
def id_multi_search(query, models, options, &proc)
|
25
|
+
total_hits, results = @server.id_multi_search(model_class_name, query, models, options)
|
26
|
+
block_given? ? yield_results(total_hits, results, &proc) : [ total_hits, results ]
|
27
|
+
end
|
28
|
+
|
29
|
+
# add record to index
|
30
|
+
def add(record)
|
31
|
+
@server.add record.class.name, record.to_doc
|
32
|
+
end
|
33
|
+
alias << add
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def yield_results(total_hits, results)
|
38
|
+
results.each do |result|
|
39
|
+
yield result[:model], result[:id], result[:score], result[:data]
|
40
|
+
end
|
41
|
+
total_hits
|
42
|
+
end
|
43
|
+
|
44
|
+
def model_class_name
|
45
|
+
@config[:class_name]
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ActsAsFerret
|
2
|
+
|
3
|
+
# decorator that adds a total_hits accessor and will_paginate compatible
|
4
|
+
# paging support to search result arrays
|
5
|
+
class SearchResults
|
6
|
+
attr_reader :current_page, :per_page, :total_hits
|
7
|
+
|
8
|
+
def initialize(results, total_hits, current_page = 1, per_page = nil)
|
9
|
+
@results = results
|
10
|
+
@total_hits = total_hits
|
11
|
+
@current_page = current_page
|
12
|
+
@per_page = (per_page || total_hits)
|
13
|
+
@total_pages = @per_page > 0 ? (@total_hits / @per_page.to_f).ceil : 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_missing(symbol, *args, &block)
|
17
|
+
@results.send(symbol, *args, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def respond_to?(name)
|
21
|
+
self.methods.include?(name) || @results.respond_to?(name)
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
# code from here on was directly taken from will_paginate's collection.rb
|
26
|
+
|
27
|
+
#
|
28
|
+
# The total number of pages.
|
29
|
+
def page_count
|
30
|
+
@total_pages
|
31
|
+
end
|
32
|
+
|
33
|
+
# Current offset of the paginated collection. If we're on the first page,
|
34
|
+
# it is always 0. If we're on the 2nd page and there are 30 entries per page,
|
35
|
+
# the offset is 30. This property is useful if you want to render ordinals
|
36
|
+
# besides your records: simply start with offset + 1.
|
37
|
+
#
|
38
|
+
def offset
|
39
|
+
(current_page - 1) * per_page
|
40
|
+
end
|
41
|
+
|
42
|
+
# current_page - 1 or nil if there is no previous page
|
43
|
+
def previous_page
|
44
|
+
current_page > 1 ? (current_page - 1) : nil
|
45
|
+
end
|
46
|
+
|
47
|
+
# current_page + 1 or nil if there is no next page
|
48
|
+
def next_page
|
49
|
+
current_page < page_count ? (current_page + 1) : nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
################################################################################
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
################################################################################
|
5
|
+
$ferret_server_options = {
|
6
|
+
'environment' => nil,
|
7
|
+
'debug' => nil,
|
8
|
+
}
|
9
|
+
|
10
|
+
################################################################################
|
11
|
+
OptionParser.new do |optparser|
|
12
|
+
optparser.banner = "Usage: #{File.basename($0)} [options] {start|stop}"
|
13
|
+
|
14
|
+
optparser.on('-h', '--help', "This message") do
|
15
|
+
puts optparser
|
16
|
+
exit
|
17
|
+
end
|
18
|
+
|
19
|
+
optparser.on('-e', '--environment=NAME', 'Set RAILS_ENV to the given string') do |e|
|
20
|
+
$ferret_server_options['environment'] = e
|
21
|
+
end
|
22
|
+
|
23
|
+
optparser.on('--debug', 'Include full stack traces on exceptions') do
|
24
|
+
$ferret_server_options['debug'] = true
|
25
|
+
end
|
26
|
+
|
27
|
+
$ferret_server_action = optparser.permute!(ARGV)
|
28
|
+
(puts optparser; exit(1)) unless $ferret_server_action.size == 1
|
29
|
+
|
30
|
+
$ferret_server_action = $ferret_server_action.first
|
31
|
+
(puts optparser; exit(1)) unless %w(start stop).include?($ferret_server_action)
|
32
|
+
end
|
33
|
+
|
34
|
+
################################################################################
|
35
|
+
begin
|
36
|
+
ENV['FERRET_USE_LOCAL_INDEX'] = 'true'
|
37
|
+
ENV['RAILS_ENV'] = $ferret_server_options['environment']
|
38
|
+
#require(File.join(File.dirname(__FILE__), '../../../../config/environment'))
|
39
|
+
require(File.join(File.dirname(ENV['_']), '../config/environment'))
|
40
|
+
require 'acts_as_ferret'
|
41
|
+
ActsAsFerret::Remote::Server.new.send($ferret_server_action)
|
42
|
+
rescue Exception => e
|
43
|
+
$stderr.puts(e.message)
|
44
|
+
$stderr.puts(e.backtrace.join("\n")) if $ferret_server_options['debug']
|
45
|
+
exit(1)
|
46
|
+
end
|
data/lib/shared_index.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module ActsAsFerret
|
2
|
+
|
3
|
+
class SharedIndex < LocalIndex
|
4
|
+
|
5
|
+
# build a ferret query matching only the record with the given id and class
|
6
|
+
def query_for_record(id, class_name)
|
7
|
+
(bq = Ferret::Search::BooleanQuery.new).tap do
|
8
|
+
bq.add_query(Ferret::Search::TermQuery.new(:id, id.to_s), :must)
|
9
|
+
bq.add_query(Ferret::Search::TermQuery.new(:class_name, class_name), :must)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module ActsAsFerret
|
2
|
+
|
3
|
+
# class methods for classes using acts_as_ferret :single_index => true
|
4
|
+
module SharedIndexClassMethods
|
5
|
+
|
6
|
+
def find_id_by_contents(q, options = {}, &block)
|
7
|
+
# add class name scoping to query if necessary
|
8
|
+
unless options[:models] == :all # search needs to be restricted by one or more class names
|
9
|
+
options[:models] ||= []
|
10
|
+
# add this class to the list of given models
|
11
|
+
options[:models] << self unless options[:models].include?(self)
|
12
|
+
# keep original query
|
13
|
+
original_query = q
|
14
|
+
|
15
|
+
if original_query.is_a? String
|
16
|
+
model_query = options[:models].map(&:name).join '|'
|
17
|
+
q += %{ +class_name:"#{model_query}"}
|
18
|
+
else
|
19
|
+
q = Ferret::Search::BooleanQuery.new
|
20
|
+
q.add_query(original_query, :must)
|
21
|
+
model_query = Ferret::Search::BooleanQuery.new
|
22
|
+
options[:models].each do |model|
|
23
|
+
model_query.add_query(Ferret::Search::TermQuery.new(:class_name, model.name), :should)
|
24
|
+
end
|
25
|
+
q.add_query(model_query, :must)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
options.delete :models
|
29
|
+
|
30
|
+
super(q, options, &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Overrides the standard find_by_contents for searching a shared index.
|
34
|
+
#
|
35
|
+
# please note that records from different models will be fetched in
|
36
|
+
# separate sql calls, so any sql order_by clause given with
|
37
|
+
# find_options[:order] will be ignored.
|
38
|
+
def find_by_contents(q, options = {}, find_options = {})
|
39
|
+
if order = find_options.delete(:order)
|
40
|
+
logger.warn "using a shared index, so ignoring order_by clause #{order}"
|
41
|
+
end
|
42
|
+
total_hits, result = find_records_lazy_or_not q, options, find_options
|
43
|
+
# sort so results have the same order they had when originally retrieved
|
44
|
+
# from ferret
|
45
|
+
return SearchResults.new(result, total_hits)
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
def ar_find_by_contents(q, options = {}, find_options = {})
|
51
|
+
total_hits, id_arrays = collect_results(q, options)
|
52
|
+
result = retrieve_records(id_arrays, find_options)
|
53
|
+
result.sort! { |a, b| id_arrays[a.class.name][a.id.to_s].first <=> id_arrays[b.class.name][b.id.to_s].first }
|
54
|
+
[ total_hits, result ]
|
55
|
+
end
|
56
|
+
|
57
|
+
def collect_results(q, options = {})
|
58
|
+
id_arrays = {}
|
59
|
+
# get object ids for index hits
|
60
|
+
rank = 0
|
61
|
+
total_hits = find_id_by_contents(q, options) do |model, id, score, data|
|
62
|
+
id_arrays[model] ||= {}
|
63
|
+
# store result rank and score
|
64
|
+
id_arrays[model][id] = [ rank += 1, score ]
|
65
|
+
end
|
66
|
+
[ total_hits, id_arrays ]
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
# determine all field names in the shared index
|
71
|
+
# TODO unused
|
72
|
+
# def single_index_field_names(models)
|
73
|
+
# @single_index_field_names ||= (
|
74
|
+
# searcher = Ferret::Search::Searcher.new(class_index_dir)
|
75
|
+
# if searcher.reader.respond_to?(:get_field_names)
|
76
|
+
# (searcher.reader.send(:get_field_names) - ['id', 'class_name']).to_a
|
77
|
+
# else
|
78
|
+
# puts <<-END
|
79
|
+
#unable to retrieve field names for class #{self.name}, please
|
80
|
+
#consider naming all indexed fields in your call to acts_as_ferret!
|
81
|
+
# END
|
82
|
+
# models.map { |m| m.content_columns.map { |col| col.name } }.flatten
|
83
|
+
# end
|
84
|
+
# )
|
85
|
+
#
|
86
|
+
# end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
data/lib/unix_daemon.rb
ADDED
@@ -0,0 +1,63 @@
|
|
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
|
+
open(@cfg.pid_file, "w") {|f| f << Process.pid << "\n"}
|
53
|
+
at_exit { File.unlink(@cfg.pid_file) if read_pid_file == Process.pid }
|
54
|
+
end
|
55
|
+
|
56
|
+
#################################################################################
|
57
|
+
def read_pid_file
|
58
|
+
File.read(@cfg.pid_file).to_i if File.exist?(@cfg.pid_file)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -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,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)
|