epi 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/epi +1 -1
- data/lib/epi/cli/command.rb +7 -0
- data/lib/epi/cli/commands/concerns/daemon.rb +33 -0
- data/lib/epi/cli/commands/config.rb +11 -3
- data/lib/epi/cli/commands/daemon.rb +14 -0
- data/lib/epi/cli/commands/help.rb +0 -0
- data/lib/epi/cli/commands/job.rb +1 -1
- data/lib/epi/cli/commands/restart.rb +16 -0
- data/lib/epi/cli/commands/start.rb +15 -0
- data/lib/epi/cli/commands/status.rb +6 -2
- data/lib/epi/cli/commands/stop.rb +16 -0
- data/lib/epi/cli.rb +1 -1
- data/lib/epi/connection.rb +7 -0
- data/lib/epi/core_ext/inflector.rb +1 -1
- data/lib/epi/daemon/receiver.rb +37 -0
- data/lib/epi/{server → daemon}/responder.rb +14 -5
- data/lib/epi/{server → daemon}/responders/config.rb +14 -2
- data/lib/epi/{server → daemon}/responders/job.rb +5 -6
- data/lib/epi/{server → daemon}/responders/shutdown.rb +1 -1
- data/lib/epi/daemon/responders/start.rb +19 -0
- data/lib/epi/{server → daemon}/responders/status.rb +4 -2
- data/lib/epi/daemon/responders/stop_all.rb +20 -0
- data/lib/epi/daemon/sender.rb +74 -0
- data/lib/epi/{server.rb → daemon.rb} +26 -27
- data/lib/epi/data.rb +4 -5
- data/lib/epi/job.rb +60 -2
- data/lib/epi/job_description.rb +6 -8
- data/lib/epi/jobs.rb +30 -2
- data/lib/epi/launch.rb +1 -1
- data/lib/epi/logging.rb +33 -0
- data/lib/epi/process_status.rb +1 -1
- data/lib/epi/running_process.rb +21 -3
- data/lib/epi/trigger.rb +53 -0
- data/lib/epi/triggers/concerns/comparison.rb +43 -0
- data/lib/epi/triggers/memory.rb +16 -0
- data/lib/epi/triggers/touch.rb +37 -0
- data/lib/epi/triggers/uptime.rb +12 -0
- data/lib/epi/version.rb +1 -1
- data/lib/epi.rb +4 -22
- metadata +26 -26
- data/lib/epi/cli/commands/server.rb +0 -38
- data/lib/epi/server/receiver.rb +0 -46
- data/lib/epi/server/responders/command.rb +0 -15
- data/lib/epi/server/sender.rb +0 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff6e7a2df3b27a605072bbedff81ea4ebb5b7c1b
|
4
|
+
data.tar.gz: 4609bab09c0142f2206cb733d28fb22387806fa0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb50900af4312e6959956ec5a61af06f7dee51d8f509577e56eb55027c23a7a7c43e6dd2ea4ec03425e1bc0f880d9926e094667f55b0a7eb2d7b2c3ace8427bb
|
7
|
+
data.tar.gz: 491f3d33d0b2be9d558f159c0ac8f502a037cbea1536444c4a53ea9c77739f208ebe05507c0c895fc47e2e4b3be29401618abba1ff3ea17448b283e23c5e3608
|
data/bin/epi
CHANGED
data/lib/epi/cli/command.rb
CHANGED
@@ -19,8 +19,15 @@ module Epi
|
|
19
19
|
@args = args
|
20
20
|
end
|
21
21
|
|
22
|
+
def need_root!
|
23
|
+
process = Epi::Daemon.process
|
24
|
+
raise Exceptions::Fatal, 'You need root privileges to manage this daemon' if
|
25
|
+
process && process.was_alive? && process.root? && !Epi.root?
|
26
|
+
end
|
27
|
+
|
22
28
|
end
|
23
29
|
|
30
|
+
Dir[File.expand_path '../commands/concerns/*.rb', __FILE__].each { |f| require f }
|
24
31
|
Dir[File.expand_path '../commands/*.rb', __FILE__].each { |f| require f }
|
25
32
|
end
|
26
33
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Epi
|
2
|
+
module Cli
|
3
|
+
module Concerns
|
4
|
+
module Daemon
|
5
|
+
|
6
|
+
protected
|
7
|
+
|
8
|
+
def need_daemon!
|
9
|
+
raise Exceptions::Fatal, 'No daemon is running' unless Epi::Daemon.running?
|
10
|
+
end
|
11
|
+
|
12
|
+
def need_no_daemon!
|
13
|
+
raise Exceptions::Fatal, 'Daemon is already running' if Epi::Daemon.running?
|
14
|
+
end
|
15
|
+
|
16
|
+
def shutdown(&callback)
|
17
|
+
Epi::Daemon.send :shutdown, &callback
|
18
|
+
puts 'Shutting down ...'
|
19
|
+
end
|
20
|
+
|
21
|
+
def resume(&callback)
|
22
|
+
begin
|
23
|
+
Timeout::timeout(5) { sleep 0.05 while Epi::Daemon.socket_path.exist? }
|
24
|
+
rescue Timeout::Error
|
25
|
+
raise Exceptions::Fatal, 'Daemon failed to stop after 5 seconds'
|
26
|
+
end
|
27
|
+
Epi::Daemon.send :start, &callback
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -6,20 +6,28 @@ module Epi
|
|
6
6
|
def run
|
7
7
|
case args.shift
|
8
8
|
when 'add' then add
|
9
|
-
|
9
|
+
when 'remove' then remove
|
10
|
+
else raise Exceptions::Fatal, 'Unknown config command, use [ add | remove ]'
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
13
14
|
private
|
14
15
|
|
15
16
|
def add
|
17
|
+
Epi::Daemon.send config: {add_paths: paths}
|
18
|
+
end
|
19
|
+
|
20
|
+
def remove
|
21
|
+
Epi::Daemon.send config: {remove_paths: paths}
|
22
|
+
end
|
23
|
+
|
24
|
+
def paths
|
16
25
|
raise Exceptions::Fatal, 'No path given' unless args.first
|
17
|
-
paths
|
26
|
+
@paths ||= args.map do |path|
|
18
27
|
path = Pathname(path)
|
19
28
|
path = Pathname('.').realpath.join(path) unless path.absolute?
|
20
29
|
path.to_s
|
21
30
|
end
|
22
|
-
Epi::Server.send config: {add_paths: paths}
|
23
31
|
end
|
24
32
|
|
25
33
|
end
|
File without changes
|
data/lib/epi/cli/commands/job.rb
CHANGED
@@ -10,7 +10,7 @@ module Epi
|
|
10
10
|
raise Exceptions::Fatal, 'No instruction given' if instruction.empty?
|
11
11
|
raise Exceptions::Fatal, 'Invalid instruction' unless
|
12
12
|
instruction =~ /^((\d+ )?(more|less)|\d+|pause|resume|reset|max|min|restart)$/
|
13
|
-
Epi::
|
13
|
+
Epi::Daemon.send job: {id: id, instruction: instruction}
|
14
14
|
end
|
15
15
|
|
16
16
|
end
|
data/lib/epi/cli.rb
CHANGED
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative '../connection'
|
2
|
+
|
3
|
+
module Epi
|
4
|
+
module Daemon
|
5
|
+
class Receiver < Connection
|
6
|
+
|
7
|
+
def logger
|
8
|
+
Epi.logger
|
9
|
+
end
|
10
|
+
|
11
|
+
def receive_object(data)
|
12
|
+
logger.debug "Received message of type '#{data[:type]}'"
|
13
|
+
begin
|
14
|
+
Responder.run(self, data.delete(:type).to_s, data) { |result| send_object result: result }
|
15
|
+
rescue Exceptions::Shutdown
|
16
|
+
send_object result: nil
|
17
|
+
Daemon.shutdown
|
18
|
+
rescue => error
|
19
|
+
send_object error: {
|
20
|
+
class: error.class.name,
|
21
|
+
message: error.message,
|
22
|
+
backtrace: error.backtrace
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def puts(text)
|
28
|
+
print "#{text}\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
def print(text)
|
32
|
+
send_object print: text.to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Epi
|
2
|
-
module
|
2
|
+
module Daemon
|
3
3
|
unless defined? Responder
|
4
4
|
class Responder
|
5
5
|
include Exceptions
|
@@ -9,13 +9,17 @@ module Epi
|
|
9
9
|
# @param receiver [Receiver] The receiver that is running the responder
|
10
10
|
# @param name [String] Name of the responder to invoke, e.g. 'command'
|
11
11
|
# @param data [Hash] Data included in the message, to be extracted onto the responder before it is run
|
12
|
-
def self.run(receiver, name, data)
|
12
|
+
def self.run(receiver, name, data, &callback)
|
13
13
|
klass_name = name.camelize.to_sym
|
14
14
|
klass = Responders.const_defined?(klass_name) && Responders.const_get(klass_name)
|
15
15
|
raise Fatal, 'Unknown message type' unless Class === klass && klass < Responder
|
16
|
-
responder = klass.new(receiver)
|
16
|
+
responder = klass.new(receiver, callback)
|
17
17
|
data.each { |key, value| responder.__send__ :"#{key}=", value }
|
18
|
-
responder.
|
18
|
+
if responder.respond_to? :run_async
|
19
|
+
responder.run_async
|
20
|
+
else
|
21
|
+
yield responder.run
|
22
|
+
end
|
19
23
|
end
|
20
24
|
|
21
25
|
attr_reader :receiver
|
@@ -24,8 +28,9 @@ module Epi
|
|
24
28
|
Epi.logger
|
25
29
|
end
|
26
30
|
|
27
|
-
def initialize(receiver)
|
31
|
+
def initialize(receiver, callback)
|
28
32
|
@receiver = receiver
|
33
|
+
@callback = callback
|
29
34
|
end
|
30
35
|
|
31
36
|
def run
|
@@ -36,6 +41,10 @@ module Epi
|
|
36
41
|
receiver.puts text
|
37
42
|
end
|
38
43
|
|
44
|
+
def done(result = nil)
|
45
|
+
@callback.call result
|
46
|
+
end
|
47
|
+
|
39
48
|
end
|
40
49
|
|
41
50
|
Dir[File.expand_path '../responders/*.rb', __FILE__].each { |f| require f }
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module Epi
|
2
|
-
module
|
2
|
+
module Daemon
|
3
3
|
module Responders
|
4
4
|
class Config < Responder
|
5
5
|
|
6
|
-
attr_accessor :add_paths
|
6
|
+
attr_accessor :add_paths, :remove_paths
|
7
7
|
|
8
8
|
def run
|
9
9
|
result = []
|
@@ -19,6 +19,18 @@ module Epi
|
|
19
19
|
result << "Added config path: #{path}"
|
20
20
|
end
|
21
21
|
end if add_paths
|
22
|
+
remove_paths.each do |path|
|
23
|
+
path = path.to_s
|
24
|
+
if configs.include?(path)
|
25
|
+
logger.info "Removing config path: #{path}"
|
26
|
+
# TODO: clean up any junk the config file may have left
|
27
|
+
configs.delete path
|
28
|
+
result << "Removed config path: #{path}"
|
29
|
+
else
|
30
|
+
logger.warn "Tried to remove unknown config path: #{path}"
|
31
|
+
result << "Config path not loaded: #{path}"
|
32
|
+
end
|
33
|
+
end if remove_paths
|
22
34
|
Data.save
|
23
35
|
Jobs.beat!
|
24
36
|
result.join ' '
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Epi
|
2
|
-
module
|
2
|
+
module Daemon
|
3
3
|
module Responders
|
4
4
|
class Job < Responder
|
5
5
|
|
@@ -21,11 +21,11 @@ module Epi
|
|
21
21
|
@job ||= Jobs[id]
|
22
22
|
end
|
23
23
|
|
24
|
-
def set(count
|
24
|
+
def set(count)
|
25
25
|
allowed = job.allowed_processes
|
26
|
-
raise Exceptions::Fatal, "Requested count #{count} is outside allowed range #{allowed}" unless
|
26
|
+
raise Exceptions::Fatal, "Requested count #{count} is outside allowed range #{allowed}" unless allowed === count
|
27
27
|
original = job.expected_count
|
28
|
-
raise Exceptions::Fatal, "Already running #{count} process#{count != 1 ? 'es' : ''}" unless
|
28
|
+
raise Exceptions::Fatal, "Already running #{count} process#{count != 1 ? 'es' : ''}" unless original != count
|
29
29
|
job.expected_count = count
|
30
30
|
job.sync!
|
31
31
|
"#{count < original ? 'De' : 'In'}creasing '#{job.name}' processes by #{(original - count).abs} (from #{original} to #{count})"
|
@@ -59,8 +59,7 @@ module Epi
|
|
59
59
|
def restart
|
60
60
|
count = job.expected_count
|
61
61
|
raise Exceptions::Fatal, 'This job has no processes to restart' if count == 0
|
62
|
-
|
63
|
-
set count
|
62
|
+
job.restart!
|
64
63
|
"Replacing #{count} '#{job.name}' process#{count != 1 ? 'es' : ''}"
|
65
64
|
end
|
66
65
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Epi
|
2
|
+
module Daemon
|
3
|
+
module Responders
|
4
|
+
|
5
|
+
class Start < Responder
|
6
|
+
|
7
|
+
def run
|
8
|
+
count = Jobs.running_process_count
|
9
|
+
if count == 0
|
10
|
+
'Starting ...'
|
11
|
+
else
|
12
|
+
"Starting #{count} process#{count == 1 ? '' : 'es'} ..."
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
1
3
|
module Epi
|
2
|
-
module
|
4
|
+
module Daemon
|
3
5
|
module Responders
|
4
6
|
# noinspection RubyStringKeysInHashInspection
|
5
7
|
class Status < Responder
|
@@ -14,7 +16,7 @@ module Epi
|
|
14
16
|
def stats
|
15
17
|
{
|
16
18
|
'Running as' => `whoami`.chomp,
|
17
|
-
'Since' =>
|
19
|
+
'Since' => Daemon.start_time.strftime('%c'),
|
18
20
|
'Jobs' => jobs
|
19
21
|
}
|
20
22
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Epi
|
2
|
+
module Daemon
|
3
|
+
module Responders
|
4
|
+
|
5
|
+
class StopAll < Responder
|
6
|
+
|
7
|
+
def run_async
|
8
|
+
count = Jobs.running_process_count
|
9
|
+
if count > 0
|
10
|
+
puts "Stopping #{count} process#{count == 1 ? '' : 'es'} ..."
|
11
|
+
Jobs.shutdown! { done }
|
12
|
+
else
|
13
|
+
done
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require_relative '../connection'
|
2
|
+
|
3
|
+
module Epi
|
4
|
+
module Daemon
|
5
|
+
class Sender < Connection
|
6
|
+
include Exceptions
|
7
|
+
|
8
|
+
# Send a message to the Epi server
|
9
|
+
#
|
10
|
+
# @example Get Epi's status
|
11
|
+
# Sender.send :status
|
12
|
+
#
|
13
|
+
# @example Add a config file
|
14
|
+
# Sender.send config: {add_paths: ['config.epi']}
|
15
|
+
#
|
16
|
+
# @param what [Hash|Symbol] Either a symbol being the message type, or a hash
|
17
|
+
# with a single key (a symbol) being the message type, and value (a hash) being the message.
|
18
|
+
def self.send(what, &callback)
|
19
|
+
|
20
|
+
raise ArgumentError, 'Expected a hash with one key (a symbol) and value (a hash)' unless
|
21
|
+
Symbol === what ||
|
22
|
+
(Hash === what && what.count == 1 && Symbol === what.keys.first && Hash === what.values.first)
|
23
|
+
|
24
|
+
data = case what
|
25
|
+
when Symbol then {type: what}
|
26
|
+
when Hash then what.values.first.merge(type: what.keys.first)
|
27
|
+
else nil
|
28
|
+
end
|
29
|
+
|
30
|
+
EventMachine.connect Daemon.socket_path.to_s, Sender, data, callback
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(data, callback)
|
35
|
+
@callback = callback
|
36
|
+
send_object data
|
37
|
+
end
|
38
|
+
|
39
|
+
def receive_object(data)
|
40
|
+
if data[:print]
|
41
|
+
STDOUT << data[:print]
|
42
|
+
return
|
43
|
+
end
|
44
|
+
|
45
|
+
if data.key? :result
|
46
|
+
result = data[:result]
|
47
|
+
|
48
|
+
if @callback
|
49
|
+
@callback.call result
|
50
|
+
else
|
51
|
+
puts result unless result.nil?
|
52
|
+
EM.stop
|
53
|
+
end
|
54
|
+
|
55
|
+
elsif data[:error]
|
56
|
+
|
57
|
+
error = data[:error]
|
58
|
+
if error[:class] == Fatal.name
|
59
|
+
STDERR << error[:message]
|
60
|
+
STDERR << "\n"
|
61
|
+
else
|
62
|
+
STDERR << "#{error[:class]}: #{error[:message]}\n"
|
63
|
+
error[:backtrace].each { |x| STDERR << "\t#{x}\n" }
|
64
|
+
end
|
65
|
+
|
66
|
+
EM.stop
|
67
|
+
end
|
68
|
+
|
69
|
+
close_connection
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'eventmachine'
|
2
2
|
|
3
|
-
require_relative '
|
4
|
-
require_relative '
|
5
|
-
require_relative '
|
3
|
+
require_relative 'daemon/sender'
|
4
|
+
require_relative 'daemon/receiver'
|
5
|
+
require_relative 'daemon/responder'
|
6
6
|
|
7
7
|
module Epi
|
8
|
-
module
|
8
|
+
module Daemon
|
9
9
|
|
10
10
|
class << self
|
11
11
|
|
@@ -19,7 +19,7 @@ module Epi
|
|
19
19
|
should_run_as_root = Data.root?
|
20
20
|
|
21
21
|
if running? && should_run_as_root && !process.root?
|
22
|
-
logger.info "
|
22
|
+
logger.info "Daemon needs to run as root, but is running as #{process.user}"
|
23
23
|
shutdown
|
24
24
|
end
|
25
25
|
|
@@ -29,15 +29,15 @@ module Epi
|
|
29
29
|
'or specify EPI_HOME as a directory other than /etc/epi'
|
30
30
|
end
|
31
31
|
|
32
|
-
logger.info 'Starting
|
33
|
-
Epi.launch [$0, '
|
34
|
-
|
35
|
-
|
32
|
+
logger.info 'Starting daemon'
|
33
|
+
Epi.launch [$0, 'daemon'],
|
34
|
+
stdout: Data.home + 'daemon.log',
|
35
|
+
stderr: Data.home + 'daemon_errors.log'
|
36
36
|
|
37
37
|
begin
|
38
38
|
Timeout::timeout(5) { sleep 0.05 until socket_path.exist? }
|
39
39
|
rescue Timeout::Error
|
40
|
-
raise Exceptions::Fatal, '
|
40
|
+
raise Exceptions::Fatal, 'Daemon not started after 5 seconds'
|
41
41
|
end unless socket_path.exist?
|
42
42
|
end
|
43
43
|
end
|
@@ -47,43 +47,42 @@ module Epi
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def run
|
50
|
-
raise Exceptions::Fatal, '
|
50
|
+
raise Exceptions::Fatal, 'Daemon already running' if running?
|
51
51
|
|
52
|
-
# Save the
|
53
|
-
Data.
|
52
|
+
# Save the daemon PID
|
53
|
+
Data.daemon_pid = Process.pid
|
54
54
|
|
55
55
|
# Run an initial beat
|
56
56
|
Jobs.beat!
|
57
57
|
|
58
|
-
# Start a
|
58
|
+
# Start a daemon
|
59
59
|
EventMachine.start_unix_domain_server socket_path.to_s, Receiver
|
60
60
|
logger.info "Listening on socket #{socket_path}"
|
61
61
|
|
62
|
-
# Make sure other users can connect to the
|
62
|
+
# Make sure other users can connect to the daemon
|
63
63
|
socket_path.chmod 0777 #TODO: make configurable
|
64
64
|
|
65
|
-
# Ensure the socket is destroyed when the
|
65
|
+
# Ensure the socket is destroyed when the daemon exits
|
66
66
|
EventMachine.add_shutdown_hook { socket_path.delete }
|
67
67
|
|
68
68
|
@start_time = Time.now
|
69
69
|
end
|
70
70
|
|
71
|
-
def send(*args)
|
71
|
+
def send(*args, &callback)
|
72
72
|
ensure_running
|
73
|
-
Sender.send *args
|
73
|
+
Sender.send *args, &callback
|
74
74
|
end
|
75
75
|
|
76
76
|
def shutdown(process = nil)
|
77
|
-
|
78
|
-
|
79
|
-
if process.pid == Process.pid
|
77
|
+
raise Exceptions::Fatal, 'Attempted to shut down daemon when no daemon is running' unless running?
|
78
|
+
if (process || self.process).pid == Process.pid
|
80
79
|
EventMachine.next_tick do
|
81
80
|
EventMachine.stop_event_loop
|
82
|
-
Data.
|
83
|
-
logger.info '
|
81
|
+
Data.daemon_pid = nil
|
82
|
+
logger.info 'Daemon has shut down'
|
84
83
|
end
|
85
84
|
else
|
86
|
-
logger.info '
|
85
|
+
logger.info 'Daemon will shut down'
|
87
86
|
send :shutdown
|
88
87
|
end
|
89
88
|
end
|
@@ -93,9 +92,9 @@ module Epi
|
|
93
92
|
end
|
94
93
|
|
95
94
|
def process
|
96
|
-
|
97
|
-
@process = nil if @process && @process.pid !=
|
98
|
-
@process ||=
|
95
|
+
daemon_pid = Data.daemon_pid
|
96
|
+
@process = nil if @process && @process.pid != daemon_pid
|
97
|
+
@process ||= daemon_pid && RunningProcess.new(daemon_pid)
|
99
98
|
end
|
100
99
|
|
101
100
|
end
|
data/lib/epi/data.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'pathname'
|
2
|
-
require 'bson'
|
3
2
|
require 'forwardable'
|
4
3
|
|
5
4
|
module Epi
|
@@ -13,7 +12,7 @@ module Epi
|
|
13
12
|
|
14
13
|
delegate [:[], :[]=, :read, :write, :root?, :save, :reload, :home] => :default_instance
|
15
14
|
|
16
|
-
%w[
|
15
|
+
%w[daemon_pid].each do |property|
|
17
16
|
define_method(property) { read property }
|
18
17
|
define_method(property + '=') { |value| write property, value }
|
19
18
|
end
|
@@ -104,7 +103,7 @@ module Epi
|
|
104
103
|
end
|
105
104
|
|
106
105
|
def data_file
|
107
|
-
@data_file ||= home + 'data
|
106
|
+
@data_file ||= home + 'data'
|
108
107
|
end
|
109
108
|
|
110
109
|
# Force reload of data from disk
|
@@ -114,12 +113,12 @@ module Epi
|
|
114
113
|
|
115
114
|
# Save data to disk
|
116
115
|
def save
|
117
|
-
data_file.binwrite hash
|
116
|
+
data_file.binwrite Marshal.dump hash
|
118
117
|
data_file.chmod 0644
|
119
118
|
end
|
120
119
|
|
121
120
|
def hash
|
122
|
-
@hash ||= data_file.exist? ?
|
121
|
+
@hash ||= data_file.exist? ? Marshal.load(data_file.binread) : {}
|
123
122
|
end
|
124
123
|
|
125
124
|
# Returns true if using root data at /etc/epi, or false if using user data
|