process_command 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.
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # ProcessCommand
2
+
3
+ Interprocess communication with command for ruby
4
+
5
+ ## Usage
6
+
7
+ #in receiver process(pid: 9999)
8
+ require 'process_command'
9
+ ProcessCommand.init_receiver
10
+ ProcessCommand.on(:pause) { p "server paused" }
11
+ ProcessCommand.on(:resume) { p "server resumed" }
12
+
13
+ #in sender process
14
+ require 'process_command'
15
+ ProcessCommand.send :pause, 9999
16
+
17
+ ## Mode
18
+
19
+ * Unix socket (default)
20
+
21
+ ProcessCommand.mode = :socket
22
+
23
+ * Signal
24
+
25
+ ProcessCommand.mode = :signal
26
+
27
+ ## Customization
28
+
29
+ For logger
30
+
31
+ ProcessCommand.logger = ProcessCommand::Logger
32
+
33
+ For mode socket, default path /tmp, you can change it
34
+ ProcessCommand::Socket::Setting.set_path(path)
35
+
36
+ For mode signal, default signals are USR1, USR2, HUP, you can change them both in sender and receiver
37
+
38
+ ProcessCommand::Signal::Setting.set_bits(bit0_signal, bit1_signal)
39
+ ProcessCommand::Signal::Setting.set_control(control_signal)
@@ -0,0 +1,40 @@
1
+ module ProcessCommand
2
+
3
+ class BaseReceiver
4
+
5
+
6
+ class << self
7
+
8
+ def init
9
+ init_listener
10
+ Thread.new do
11
+ init_handler
12
+ end
13
+ end
14
+
15
+ def add_command_block(command, block)
16
+ @command_blocks ||= {}
17
+ @command_blocks[command.to_s] = block
18
+ end
19
+
20
+ def run_command_block(command)
21
+ command = command.to_s
22
+ block = @command_blocks[command]
23
+ if block
24
+ Thread.new do
25
+ begin
26
+ block.call
27
+ rescue Exception => e
28
+ ProcessCommand.logger.error "block execute error for command (#{command}), error: #{e.message}"
29
+ end
30
+ end
31
+ else
32
+ ProcessCommand.logger.error "block not found for command (#{command})"
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,19 @@
1
+ module ProcessCommand
2
+
3
+ class Logger
4
+
5
+ class << self
6
+
7
+ def info(message)
8
+ p "INFO: #{message}"
9
+ end
10
+
11
+ def error(message)
12
+ p "ERROR: #{message}"
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,20 @@
1
+ module ProcessCommand
2
+
3
+ module Signal
4
+
5
+ class Command
6
+
7
+ def self.i2s(command)
8
+ command.to_s(16).scan(/.{2}/).map{|c| c.to_i(16).chr}.join
9
+ end
10
+
11
+ def self.s2i(command)
12
+ command.to_s.each_char.map{|c| c.ord.to_s(16)}.join.to_i(16)
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+
@@ -0,0 +1,55 @@
1
+ module ProcessCommand
2
+
3
+ module Signal
4
+
5
+ class Receiver < ProcessCommand::BaseReceiver
6
+
7
+ class << self
8
+
9
+ attr_accessor :command
10
+ RECEIVER_QUEUE = Queue.new
11
+
12
+ def init
13
+ @command = 0
14
+ super
15
+ end
16
+
17
+ def init_listener
18
+ ::Signal.trap(Setting.bit0) do
19
+ Thread.new{ RECEIVER_QUEUE << 0}
20
+ end
21
+ ::Signal.trap(Setting.bit1) do
22
+ Thread.new{ RECEIVER_QUEUE << 1}
23
+ end
24
+ ::Signal.trap(Setting.control) do
25
+ Thread.new{ RECEIVER_QUEUE << :control}
26
+ end
27
+ end
28
+
29
+ def init_handler
30
+ while value = RECEIVER_QUEUE.pop
31
+ command = Receiver.command
32
+ case value
33
+ when 0
34
+ command <<= 1
35
+ when 1
36
+ command <<= 1
37
+ command |= 1
38
+ when :control
39
+ run_command_block Command.i2s(command) if command
40
+ command = 0
41
+ else
42
+ ProcessCommand.logger.error "illegal value #{value}, reset command 0"
43
+ command = 0
44
+ end
45
+ self.command = command
46
+ end
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+
55
+ end
@@ -0,0 +1,37 @@
1
+ module ProcessCommand
2
+
3
+ module Signal
4
+
5
+ class Sender
6
+
7
+ SENDER_LOCK = Mutex.new
8
+ DEFAULT_DELAY = 0.05
9
+
10
+ class << self
11
+
12
+ def set_delay(delay)
13
+ @delay = delay
14
+ end
15
+
16
+ def send(command, pid)
17
+ @delay ||= DEFAULT_DELAY
18
+ command = Command.s2i(command).to_s(2)
19
+ return if command.empty?
20
+ SENDER_LOCK.synchronize do
21
+ while bit = command.slice!(0)
22
+ signal = bit == '0' ? Setting.bit0 : Setting.bit1
23
+ Process.kill(signal, pid)
24
+ sleep @delay
25
+ end
26
+ Process.kill(Setting.control, pid)
27
+ end
28
+ end
29
+
30
+
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,41 @@
1
+ module ProcessCommand
2
+
3
+ module Signal
4
+
5
+ class Setting
6
+
7
+ DEFAULT_BIT0 = :USR1
8
+ DEFAULT_BIT1 = :USR2
9
+ DEFAULT_CONTROL = :HUP
10
+
11
+ class << self
12
+
13
+ def set_bits(bit0, bit1)
14
+ @bit0 = bit0
15
+ @bit1 = bit1
16
+ end
17
+
18
+ def set_control(control)
19
+ @control = control
20
+ end
21
+
22
+ def bit0
23
+ @bit0 ||= DEFAULT_BIT0
24
+ end
25
+
26
+ def bit1
27
+ @bit1 ||= DEFAULT_BIT1
28
+ end
29
+
30
+ def control
31
+ @control ||= DEFAULT_CONTROL
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+
@@ -0,0 +1,33 @@
1
+ require 'socket'
2
+ module ProcessCommand
3
+
4
+ module Socket
5
+
6
+ class Receiver < ProcessCommand::BaseReceiver
7
+
8
+ class << self
9
+
10
+ RECEIVER_QUEUE = Queue.new
11
+
12
+ def init_listener
13
+ path = Setting.socket_path Process.pid
14
+ File.delete path if File.exists? path
15
+ @server = UNIXServer.new path
16
+ end
17
+
18
+ def init_handler
19
+ while client = @server.accept
20
+ Thread.new do
21
+ command = client.read
22
+ run_command_block command
23
+ end
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,26 @@
1
+ require 'socket'
2
+ module ProcessCommand
3
+
4
+ module Socket
5
+
6
+ class Sender
7
+
8
+ class << self
9
+
10
+ def send(command, pid)
11
+ command = command.to_s
12
+ path = Setting.socket_path pid
13
+ server = UNIXSocket.new path
14
+ server.write command
15
+ server.close
16
+ rescue Exception => e
17
+ ProcessCommand.logger.error "send error, #{e.message}"
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,31 @@
1
+ module ProcessCommand
2
+
3
+ module Socket
4
+
5
+ class Setting
6
+
7
+ DEFAULT_PATH = "/tmp"
8
+
9
+ class << self
10
+
11
+ def set_path(path)
12
+ @path = path
13
+ end
14
+
15
+ def path
16
+ @path ||= DEFAULT_PATH
17
+ end
18
+
19
+ def socket_path(pid)
20
+ "#{self.path}/process_command_#{pid}.sock"
21
+ end
22
+
23
+
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+
@@ -0,0 +1,57 @@
1
+ require 'process_command/base_receiver'
2
+ require 'process_command/logger'
3
+ require 'process_command/signal/command'
4
+ require 'process_command/signal/setting'
5
+ require 'process_command/signal/receiver'
6
+ require 'process_command/signal/sender'
7
+ require 'process_command/socket/setting'
8
+ require 'process_command/socket/receiver'
9
+ require 'process_command/socket/sender'
10
+ require 'active_support/core_ext/module/attribute_accessors'
11
+
12
+ module ProcessCommand
13
+
14
+ mattr_accessor :mode
15
+ mattr_accessor :logger
16
+
17
+ def self.receiver
18
+ case self.mode
19
+ when :signal
20
+ ProcessCommand::Signal::Receiver
21
+ when :socket
22
+ ProcessCommand::Socket::Receiver
23
+ else
24
+ nil
25
+ end
26
+ end
27
+
28
+ def self.sender
29
+ case self.mode
30
+ when :signal
31
+ ProcessCommand::Signal::Sender
32
+ when :socket
33
+ ProcessCommand::Socket::Sender
34
+ else
35
+ nil
36
+ end
37
+ end
38
+
39
+ def self.init_receiver
40
+ self.receiver.init
41
+ end
42
+
43
+ #for receiver
44
+ def self.on(command, &block)
45
+ self.receiver.add_command_block command, block
46
+ end
47
+
48
+ #for sender
49
+ def self.send(command, pid)
50
+ self.sender.send(command, pid)
51
+ end
52
+
53
+ end
54
+
55
+ ProcessCommand.mode = :socket #:signal
56
+ ProcessCommand.logger = ProcessCommand::Logger
57
+
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: process_command
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Leon Li
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-06 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: Interprocess communication with command for ruby
15
+ email: qianthinking@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/process_command/base_receiver.rb
21
+ - lib/process_command/logger.rb
22
+ - lib/process_command/signal/receiver.rb
23
+ - lib/process_command/signal/command.rb
24
+ - lib/process_command/signal/setting.rb
25
+ - lib/process_command/signal/sender.rb
26
+ - lib/process_command/socket/receiver.rb
27
+ - lib/process_command/socket/setting.rb
28
+ - lib/process_command/socket/sender.rb
29
+ - lib/process_command.rb
30
+ - README.md
31
+ homepage: https://github.com/qianthinking/process_command
32
+ licenses: []
33
+ post_install_message:
34
+ rdoc_options:
35
+ - --line-numbers
36
+ - --inline-source
37
+ - --title
38
+ - RAlgorithms
39
+ - --main
40
+ - README.md
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '1.2'
55
+ requirements: []
56
+ rubyforge_project:
57
+ rubygems_version: 1.8.10
58
+ signing_key:
59
+ specification_version: 2
60
+ summary: Interprocess communication with command for ruby.
61
+ test_files: []