dorsal 1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6b142bf4c6b5a14321f07c27e1de317bbe7bec8e
4
+ data.tar.gz: 31bbcd213f7c18aac8671d0041c00b6d7657e499
5
+ SHA512:
6
+ metadata.gz: 6dead18e0122a5999e7d6276e709ec05492e3a7abcea00759ab6851bc8bdc1d2f58190225e830e1bbfa5e82a9ce0ac18de4bc8a9e011f270cc715b757a6cde63
7
+ data.tar.gz: da7218d7a318d41d98ccd3dc814c7f90c0a6f5c4d8f755dbbd703c0150a17684518b8762343f425ccf25e548ec43d8d3a5ec21d01e18171a93ab814b1b5c6b06
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in dorsal.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Romain GEORGES
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,26 @@
1
+ # Dorsal
2
+
3
+ * *Authors* : Romain GEORGES
4
+ * *Email* : romain@ultragreen.net
5
+ * *Description* : Dorsal : Druby Objects's Ring Server as an simple Alternative to Linda
6
+ Dorsal provide a simple and easy to use Ring Server for DRuby Objects based services architectures
7
+ * *Homepage : http://www.ultragreen.net/projects/dorsal
8
+ * *License : BSD
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ gem 'dorsal'
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install dorsal
23
+
24
+ ## Usage
25
+
26
+
@@ -0,0 +1,61 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rubygems'
3
+ require 'rspec'
4
+ require 'rake'
5
+ require "rake/clean"
6
+ require "rubygems/package_task"
7
+ require "rdoc/task"
8
+ require 'code_statistics'
9
+ require 'rspec/core/rake_task'
10
+ require 'yard'
11
+ require 'yard/rake/yardoc_task.rb'
12
+ require "rake/tasklib"
13
+ require "roodi"
14
+ require "roodi_task"
15
+
16
+
17
+ RoodiTask.new() do | t |
18
+ t.patterns = %w(lib/**/*.rb)
19
+ t.config = "ultragreen_roodi_coding_convention.yml"
20
+ end
21
+
22
+
23
+ CLEAN.include('*.tmp','*.old')
24
+ CLOBBER.include('*.tmp', 'build/*','#*#')
25
+
26
+
27
+ content = File::readlines(File.join(File.dirname(__FILE__), 'dorsal.gemspec')).join
28
+ spec = eval(content)
29
+
30
+ RSpec::Core::RakeTask.new('spec')
31
+
32
+ YARD::Rake::YardocTask.new do |t|
33
+ t.files = [ 'lib/**/*.rb', '-', 'doc/**/*','spec/**/*_spec.rb']
34
+ t.options += ['--title', "Gem Documentation"]
35
+ t.options += ['-o', "yardoc"]
36
+ t.options += ['-r', "doc/manual.rdoc"]
37
+ end
38
+ YARD::Config.load_plugin('yard-rspec')
39
+
40
+ namespace :yardoc do
41
+ task :clobber do
42
+ rm_r "yardoc" rescue nil
43
+ rm_r ".yardoc" rescue nil
44
+ end
45
+ end
46
+ task :clobber => "yardoc:clobber"
47
+
48
+
49
+ Gem::PackageTask.new(spec) do |pkg|
50
+ pkg.need_tar = true
51
+ pkg.need_zip = true
52
+ end
53
+
54
+ Rake::RDocTask.new('rdoc') do |d|
55
+ d.rdoc_files.include('doc/**/*','bin/*')
56
+ d.main = 'doc/manual.rdoc'
57
+ d.title = 'Dorsal : Yard'
58
+ d.options << '--line-numbers' << '--diagram' << '-SHN'
59
+ end
60
+
61
+ task :default => [:gem]
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'dorsal/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "dorsal"
8
+ spec.version = Dorsal::VERSION
9
+ spec.authors = ["Romain GEORGES"]
10
+ spec.email = ["romain@ultragreen.net"]
11
+ spec.description = %q{Dorsal : Druby Objects's Ring Server as an simple Alternative to Linda}
12
+ spec.summary = %q{Dorsal provide a simple and easy to use Ring Server for DRuby Objects based services architectures}
13
+ spec.homepage = "http://www.ultragreen.net/projects/dorsal"
14
+ spec.license = "BSD"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+ spec.add_development_dependency('methodic', '>= 1.2')
21
+ spec.add_development_dependency('rspec')
22
+ spec.add_development_dependency('yard')
23
+ spec.add_development_dependency('rdoc')
24
+ spec.add_development_dependency('roodi')
25
+ spec.add_development_dependency('code_statistics')
26
+ spec.add_development_dependency('yard-rspec')
27
+ spec.add_development_dependency "bundler", "~> 1.3"
28
+ spec.add_dependency "daemons"
29
+
30
+ spec.required_ruby_version = '>= 1.8.1'
31
+ spec.rubyforge_project = "nowarning"
32
+ spec.has_rdoc = true
33
+ end
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ #---# Author : Romain GEORGES
4
+ # type : gem component library
5
+ # obj : Dorsal Module
6
+ #---
7
+ require "dorsal/version"
8
+ require 'rubygems'
9
+ require 'methodic'
10
+ require 'drb/drb'
11
+ require 'dorsal/privates'
12
+ require 'dorsal/exceptions'
13
+ require 'dorsal/implementation'
14
+ require 'dorsal/controller'
15
+
16
+ # module Dorsal
17
+ # @author Romain GEORGES <romain@ultragreen.net>
18
+ # @see http://www.ultragreen.net/projects/dorsal
19
+ # @version (See Dorsal::VERSION)
20
+ # @note this module is a namespace Dorsal
21
+ module Dorsal
22
+
23
+ # the default dir where write pid files
24
+ DEFAULT_DIR = '/tmp/dorsal'
25
+
26
+ # the default host name shared between Ring Server and DRb hosted services
27
+ DEFAULT_HOST = 'localhost'
28
+
29
+ # the default port of the Ring Server
30
+ DEFAULT_PORT = '8686'
31
+
32
+ # the default shortname of the ringserver
33
+ DEFAULT_RINGSERVER_NAME = 'ringserver'
34
+
35
+ # the default long description of the ring Server
36
+ DEFAULT_RINGSERVER_DESCRIPTION = 'Dorsal Ring Server'
37
+
38
+ # the default debug status
39
+ DEFAULT_DEBUG = false
40
+
41
+
42
+ end
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+
52
+
53
+
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ #---
4
+ # Author : Romain GEORGES
5
+ # type : gem component library
6
+ # obj : Dorsal Module
7
+ #---
8
+ require 'drb'
9
+ require 'methodic'
10
+ require 'dorsal/privates'
11
+ require 'dorsal/exceptions'
12
+
13
+ # the Dorsal namespace
14
+ module Dorsal
15
+ # the Controller Class, provide access and control of the Ring Server and services, via the Ring Server
16
+ # @example usage
17
+ # dorsal = Dorsal::Controller::new
18
+ # # or
19
+ # dorsal = Dorsal::Contoller::new :host => 'dorsal.example.com',
20
+ # :port => "8888", :dir => '/a/writable/path', :description => 'My Own Dorsal Ring Server'
21
+ class Controller
22
+
23
+ # use shared privates
24
+ include Dorsal::Privates
25
+ private :start
26
+ private :stop
27
+ private :status
28
+
29
+
30
+ # @example read
31
+ # dorsal = Dorsal::Controller::new
32
+ # p dorsal.options
33
+ # @attr_reader [Hash] options a hash table of all structured options of Dorsal
34
+ attr_reader :options
35
+
36
+ # contructor for Dorsal::Controller
37
+ # @param [Hash] _options (all options are optionals
38
+ # @note see default values from Dorsal namespace Constants
39
+ # @option _options [String] :name the name of the ringserver instance
40
+ # @option _options [String] :description the detail name of the the ring server, use for $0
41
+ # @option _options [String] :port the port where to bind ring server
42
+ # @option _options [String] :host the host name share between ring server and hosted DRb services
43
+ # @option _options [String] :dir a writable path where to write pid files and more.
44
+ # @option _options [TruClass,FalseClass] :debug to run Dorsal Ring server in foreground, with more traces
45
+ # @example usage
46
+ # dorsal = Dorsal::Controller::new
47
+ # # or
48
+ # dorsal = Dorsal::Contoller::new :host => 'dorsal.example.com',
49
+ # :port => "8888", :dir => '/a/writable/path', :description => 'My Own Dorsal Ring Server'
50
+ def initialize(_options = {})
51
+ @options = Methodic::get_options(_options)
52
+ @options.specify_defaults_values :description => Dorsal::DEFAULT_RINGSERVER_DESCRIPTION,
53
+ :debug => Dorsal::DEFAULT_DEBUG,
54
+ :host => Dorsal::DEFAULT_HOST,
55
+ :port => Dorsal::DEFAULT_PORT,
56
+ :dir => Dorsal::DEFAULT_DIR
57
+ @options.merge
58
+ @options[:dir].chomp!('/')
59
+ @options[:name] = Dorsal::DEFAULT_RINGSERVER_NAME
60
+ @options[:uri] = "druby://#{options[:host]}:#{options[:port]}"
61
+ Dir::mkdir(@options[:dir]) unless File::exist?(@options[:dir])
62
+ @options[:pid_file] = "#{@options[:dir]}/#{@options[:name]}.pid"
63
+ @options[:object] = Dorsal::ImplementationServer::new({ :dir => @options[:dir], :host => @options[:host], :debug => @options[:debug]})
64
+ end
65
+
66
+ # accessor to ring server if up
67
+ # @return [DRbObject, nil] the ring server Drb Object if Up or nil
68
+ # @example usage
69
+ # dorsal = Dorsal::Controller::new
70
+ # dorsal.start_ring_server
71
+ # ring = dorsal.bin_to_ring
72
+ def bind_to_ring
73
+ if ring_server_status then
74
+ DRb.start_service
75
+ return DRbObject.new nil, @options[:uri]
76
+ else
77
+ return nil
78
+ end
79
+ end
80
+
81
+ # start the ring server if not
82
+ # @return [Fixnum, FalseClass] the pid of the ring server or false if already start
83
+ # @example usage
84
+ # dorsal = Dorsal::Controller::new
85
+ # dorsal.start_ring_server #=> a Fixnum for the PID
86
+ # dorsal.start_ring_server #=> false
87
+ def start_ring_server
88
+ unless ring_server_status then
89
+ res = start(@options) do
90
+ DRb.start_service(@options[:uri], @options[:object])
91
+ DRb.thread.join
92
+ end
93
+ return res
94
+ else
95
+ return false
96
+ end
97
+
98
+ end
99
+
100
+ # stop the ring server if up
101
+ # @return [TrueClass, FalseClass] true if really shutdown, false otherwise
102
+ # @example usage
103
+ # dorsal = Dorsal::Controller::new
104
+ # dorsal.start_ring_server #=> a Fixnum for the PID
105
+ # dorsal.stop_ring_server #=> true
106
+ # dorsal.stop_ring_server #=> false
107
+ def stop_ring_server
108
+ if ring_server_status then
109
+ ring = self.bind_to_ring
110
+ ring.list_services.keys.each do |service|
111
+ ring.destroy_service :name => service
112
+ end
113
+ return stop @options
114
+ else
115
+ return false
116
+ end
117
+ end
118
+
119
+ # return the running status of the ring server
120
+ # @return [TrueClass, FalseClass] true if up, false if down
121
+ # @example usage
122
+ # dorsal = Dorsal::Controller::new
123
+ # dorsal.start_ring_server #=> a Fixnum for the PID
124
+ # dorsal.ring_server_status #=> true
125
+ # dorsal.stop_ring_server #=> true
126
+ # dorsal.ring_server_status #=> false
127
+ def ring_server_status
128
+ return status @options
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ #---
4
+ # Author : Romain GEORGES
5
+ # type : gem component library
6
+ # obj : Dorsal Module
7
+ #---
8
+
9
+ # the Dorsal Namespace
10
+ module Dorsal
11
+ # Exception class override from servers errors
12
+ class ServerError < Exception; end
13
+ end
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ #---
4
+ # Author : Romain GEORGES
5
+ # type : gem component library
6
+ # obj : Dorsal Module
7
+ #---
8
+ require 'drb'
9
+ require 'dorsal/privates'
10
+
11
+ # the dorsal namespace
12
+ module Dorsal
13
+
14
+ # the Ring Server DRbObject Implementation
15
+ # @note should NOT be instantiate
16
+ # @note this classe is made to be instantiate as a ring server
17
+ # @private
18
+ class ImplementationServer
19
+
20
+ include DRbUndumped
21
+ include Dorsal::Privates
22
+
23
+ # @attr_reader [Hash] data the internal Hash of the ring server
24
+ # @note for debug only
25
+ attr_reader :data
26
+
27
+ # the contructor of the Ring Server
28
+ # @param [Hash] _options the params of the constructor, keys must be symbols
29
+ # @note :description (default) 'Dorsal::DEFAULT_RINGSERVER_DESCRIPTION'
30
+ # @note :debug (default) 'Dorsal::DEFAULT_DEBUG'
31
+ # @note :host (default) 'Dorsal::DEFAULT_HOST'
32
+ # @note :port (default) 'Dorsal::DEFAULT_PORT'
33
+ # @note :dir (default) 'Dorsal::DEFAULT_DIR'
34
+ # @note :name (default) 'Dorsal::DEFAULT_RINGSERVER_NAME'
35
+ # @note :uri rule 'druby://(:host):(:port)'
36
+ # @note :pid_file rule '(:dir)/(:name).pid'
37
+ # @option _options [String] :description the description of ring server
38
+ # @option _options [TrueClass,FalseClass] :debug the deubg mode
39
+ # @option _options [String] :host the host for ring server and services
40
+ # @option _options [String] :port the port for the ring server
41
+ # @option _options [String] :dir the writable path for pids files
42
+ # @option _options [String] :name the ring server name
43
+ # @option _options [String] :uri the defined uri for ring server
44
+ # @option _options [String] :pid_file the defined pid_file for ring server
45
+ # @note DO NOT USE DIRECTLY
46
+ def initialize(_options = {})
47
+ @options = Methodic::get_options(_options)
48
+ @options.specify_defaults_values :name => 'ringserver',
49
+ :host => 'localhost',
50
+ :debug => false,
51
+ :dir => '/tmp/dorsal'
52
+ @options.merge
53
+ @data ={}
54
+ end
55
+
56
+
57
+ # start a service from the ring server
58
+ # @return [Fixnum,FalseClass] the pid of the process who host the DRb service, false if already started
59
+ # @param [Hash] _options the params of the constructor, keys must be symbols
60
+ # @option _options [String] :name the name of the service
61
+ # @option _options [String] :description the long name of the service, use for $0
62
+ # @option _options [Object] :object an object to be served by DRb
63
+ # @note access by Dorsal::Controller::new.bind_to_ring.start_service
64
+ # @example usage
65
+ # Dorsal::Controller::new.bind_to_ring.start_service :name => 'service', :description => 'a service', :object => MyService::new
66
+ def start_service(_options = {})
67
+ options = Methodic::get_options(_options)
68
+ options.specify_presences_of :name, :description, :object
69
+ options.validate
70
+ unless @data.include?(options[:name]) then
71
+ options[:pid_file] = "#{@options[:dir]}/service-#{options[:name]}.pid"
72
+ options[:uri] = "druby://#{@options[:host]}:#{get_free_port(40000,50000)}"
73
+ @data[options[:name]] = { :description => options[:description] , :pid_file => options[:pid_file], :uri => options[:uri] }
74
+ return start(options) do
75
+ require 'drb'
76
+ options[:object].extend DRb::DRbUndumped
77
+ DRb.start_service(options[:uri], options[:object])
78
+ DRb.thread.join
79
+ end
80
+ else
81
+ return false
82
+ end
83
+ end
84
+
85
+ # stop a service in the ring
86
+ # @return [TrueClass,FalseClass] true if really stop, false if already down
87
+ # @param [Hash] _options the params of the constructor, keys must be symbols
88
+ # @option _options [String] :name the name of the service
89
+ # @note access by Dorsal::Controller::new.bind_to_ring.destroy_service
90
+ # @example usage
91
+ # Dorsal::Controller::new.bind_to_ring.destroy_service :name => 'service'
92
+ def destroy_service(_options = {})
93
+ options = Methodic::get_options(_options)
94
+ options.specify_presences_of :name
95
+ options.validate
96
+ if @data.include? options[:name] then
97
+ options[:pid_file] = @data[options[:name]][:pid_file]
98
+ options[:description] = @data[options[:name]][:description]
99
+ if stop(options) then
100
+ @data.delete(options[:name])
101
+ return true
102
+ end
103
+ return false
104
+ end
105
+ return false
106
+ end
107
+
108
+
109
+ # bind to a service from the ring server
110
+ # @return [DRbObject,nil] the Distributed Service, nil if service not in the Ring
111
+ # @param [Hash] _options the params of the constructor, keys must be symbols
112
+ # @option _options [String] :name the name of the service
113
+ # @note access by Dorsal::Controller::new.bind_to_ring.bind_to_service
114
+ # @example usage
115
+ # Dorsal::Controller::new.bind_to_ring.bind_to_service :name => 'service'
116
+ def bind_to_service(_options = {})
117
+ options = Methodic::get_options(_options)
118
+ options.specify_presences_of :name
119
+ options.validate
120
+ if list_services.include?(options[:name]) then
121
+ DRb.start_service
122
+ return DRbObject.new nil, @data[options[:name]][:uri]
123
+ else
124
+ return nil
125
+ end
126
+ end
127
+
128
+ # list the services from the ring server
129
+ # @return [Hash] the structured list of services in the ring
130
+ # @note access by Dorsal::Controller::new.bind_to_ring.list_services
131
+ # @example usage
132
+ # Dorsal::Controller::new.bind_to_ring.list_services
133
+ def list_services
134
+ return @data
135
+ end
136
+
137
+ private
138
+ # return a free TCP port in range
139
+ # @param [Fixnum,String] _start the first port (default 40000)
140
+ # @param [Fixnum,String] _end the last port (default 50000)
141
+ # @return [fixnum, FalseClass] the port or false if no port found
142
+ def get_free_port(_start=40000,_end=50000)
143
+ list = IO.popen("netstat -an|grep tcp|awk '{ print $4}'").readlines.map!{|item| item.chomp! ; item = item.split('.').last}
144
+ _start.upto(_end) do |port|
145
+ return port unless list.include?(port.to_s)
146
+ end
147
+ return false
148
+ end
149
+
150
+ end
151
+ end
@@ -0,0 +1,183 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ #---
4
+ # Author : Romain GEORGES
5
+ # type : gem component library
6
+ # obj : Dorsal Module
7
+ #---
8
+
9
+ require 'methodic'
10
+
11
+ # the Dorsal Namespace
12
+ module Dorsal
13
+
14
+ # module mixin for privates methods for both Controller and ImplementationServer
15
+ # @private
16
+ module Privates
17
+
18
+ # method for daemonize blocks
19
+ # @param [Hash] _options the list of options, keys are symbols
20
+ # @option _options [String] :description the description of the process, use for $0
21
+ # @option _options [String] :pid_file the pid filenam
22
+ # @yield a process definion or block given
23
+ # @example usage inline
24
+ # require 'dorsal/privates'
25
+ # class Test
26
+ # include Dorsal::Privates
27
+ # private :daemonize
28
+ # def initialize
29
+ # @loop = Proc::new do
30
+ # loop do
31
+ # sleep 1
32
+ # end
33
+ # end
34
+ # end
35
+ #
36
+ # def run
37
+ # daemonize({:description => "A loop daemon", :pid_file => '/tmp/pid.file'}, &@loop)
38
+ # end
39
+ # end
40
+ #
41
+ # @example usage block
42
+ # require 'dorsal/privates'
43
+ # class Test
44
+ # include Dorsal::Privates
45
+ # private :daemonize
46
+ # def initialize
47
+ # end
48
+ #
49
+ # def run
50
+ # daemonize :description => "A loop daemon", :pid_file => '/tmp/pid.file' do
51
+ # loop do
52
+ # sleep 1
53
+ # end
54
+ # end
55
+ # end
56
+ # end
57
+ # @return [Fixnum] pid the pid of the forked processus
58
+ def daemonize(_options)
59
+ options = Methodic::get_options(_options)
60
+ options.specify_presences_of :description, :pid_file
61
+ options.validate
62
+ return yield if options[:debug]
63
+ pid = fork do
64
+ trap("SIGINT"){ exit! 0 }
65
+ trap("SIGTERM"){ exit! 0 }
66
+ trap("SIGHUP"){ exit! 0 }
67
+ Process.daemon
68
+ $0 = options[:description]
69
+ yield
70
+ end
71
+ File.open(options[:pid_file],"w"){|f| f.puts pid } if options[:pid_file]
72
+ return pid
73
+ end
74
+
75
+ # daemonize wrapper to prevent processus cloning
76
+ # @param [Hash] _options the list of options, keys are symbols
77
+ # @option _options [String] :description the description of the process, use for $0
78
+ # @option _options [String] :pid_file the pid filenam
79
+ # @return [Fixnum] pid the pid of the forked processus
80
+ # @yield a process definion or block given
81
+ # @raise [Dorsal::RingServerError] if pid_file exist or processus with the present description
82
+ # @example usage inline
83
+ # require 'dorsal/privates'
84
+ # class Test
85
+ # include Dorsal::Privates
86
+ # private :start
87
+ # private :daemonize
88
+ # def initialize
89
+ # @loop = Proc::new do
90
+ # loop do
91
+ # sleep 1
92
+ # end
93
+ # end
94
+ # end
95
+ #
96
+ # def run
97
+ # start({:description => "A loop daemon", :pid_file => '/tmp/pid.file'}, &@loop)
98
+ # end
99
+ # end
100
+ #
101
+ # @example usage block
102
+ # require 'dorsal/privates'
103
+ # class Test
104
+ # include Dorsal::Privates
105
+ # private :daemonize
106
+ # private :start
107
+ # def initialize
108
+ # end
109
+ #
110
+ # def run
111
+ # start :description => "A loop daemon", :pid_file => '/tmp/pid.file' do
112
+ # loop do
113
+ # sleep 1
114
+ # end
115
+ # end
116
+ # end
117
+ # end
118
+ def start(_options = {})
119
+ options = Methodic::get_options(_options)
120
+ options.specify_presences_of :description, :pid_file
121
+ options.validate
122
+ raise Dorsal::RingServerError::new('already running, pid file exist') if File::exist?(options[:pid_file])
123
+ raise Dorsal::RingServerError::new('already running') unless `ps aux|grep ruby|grep -v grep |grep '#{options[:description]}'`.empty?
124
+ return daemonize(options) do
125
+ yield
126
+ end
127
+ end
128
+
129
+ # stop a running processus
130
+ # @param [Hash] _options the list of options, keys are symbols
131
+ # @option _options [String] :description the description of the process, use for $0
132
+ # @option _options [String] :pid_file the pid filename
133
+ # @option _options [String] :name the name of the processus (OPTIONAL)
134
+ # @return [TrueClass,FalseClass] true if a service really closed, false otherwise
135
+ # @raise [Dorsal::ServerError] if can't close an existant service
136
+ # @example usage inline
137
+ # #in the same class
138
+ # def stop_service
139
+ # stop :name => 'service', :description => 'A loop daemon', :pid_file => '/tmp/pid.file'
140
+ # end
141
+ def stop(_options = {})
142
+ options = Methodic::get_options(_options)
143
+ options.specify_presences_of :description, :pid_file
144
+ options.validate
145
+ File::unlink(options[:pid_file]) if File::exist?(options[:pid_file])
146
+ pid = `COLUMNS=160 ps aux|grep ruby|grep -v grep |grep '#{options[:description]}'|awk '{ print $2}'`
147
+ if pid.empty? then
148
+ return false
149
+ else
150
+ if options[:name] == 'ringserver' then
151
+ raise Dorsal::ServerError::new('Stopping failed') unless system("kill -TERM #{pid} > /dev/null")
152
+ else
153
+ return false unless system("kill -TERM #{pid} > /dev/null")
154
+ end
155
+ return true
156
+ end
157
+ end
158
+
159
+ # give the status of a processus
160
+ # @param [Hash] _options the list of options, keys are symbols
161
+ # @option _options [String] :description the description of the process, use for $0
162
+ # @option _options [String] :pid_file the pid filename
163
+ # @option _options [String] :name the name of the processus (OPTIONAL)
164
+ # @return [TrueClass,FalseClass] true if service running, false otherwise
165
+ # @example usage inline
166
+ # #in the same class
167
+ # def service_status
168
+ # status :name => 'service', :description => 'A loop daemon', :pid_file => '/tmp/pid.file'
169
+ # end
170
+ def status(_options = {})
171
+ options = Methodic::get_options(_options)
172
+ options.specify_presences_of :description, :pid_file
173
+ options.validate
174
+ pid = `COLUMNS=160 ps aux|grep ruby|grep -v grep |grep '#{options[:description]}'|awk '{ print $2}'`
175
+ if pid.empty? then
176
+ return false
177
+ else
178
+ File.open(options[:pid_file],"w"){|f| f.puts pid } unless File::exist?(options[:pid_file])
179
+ return true
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ #---
4
+ # Author : Romain GEORGES
5
+ # type : gem component library
6
+ # obj : Carioca Module
7
+ #---
8
+
9
+ # the dorsal namespace
10
+ module Dorsal
11
+
12
+ # global version of Dorsal
13
+ VERSION = "1.1"
14
+ end
@@ -0,0 +1,168 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ #---
4
+ # Author : Romain GEORGES
5
+ # type : Rspec
6
+ # obj : Dorsal Spec
7
+ #---
8
+ require 'dorsal'
9
+ require './spec/samples/dummy'
10
+
11
+ RSpec.configure do |config|
12
+ config.expect_with :rspec do |c|
13
+ c.syntax = :should
14
+ end
15
+ config.mock_with :rspec do |c|
16
+ c.syntax = :should
17
+ end
18
+ end
19
+
20
+
21
+ describe "Dorsal" do
22
+ before :all do
23
+ File::unlink('/tmp/dorsal_ringserver.pid') if File::exist?('/tmp/dorsal_ringserver.pid')
24
+ pid = `ps aux|grep ruby|grep -v grep |grep 'Dorsal Ring Server'|awk '{ print $2}'`
25
+ unless pid.empty? then
26
+ res = `kill -TERM #{pid.chomp}`
27
+ end
28
+ $controller = Dorsal::Controller::new
29
+ end
30
+
31
+ subject { Dorsal }
32
+ it { should be_an_instance_of Module}
33
+ context "Dorsal::Controller" do
34
+ subject { $controller }
35
+ it { should be_an_instance_of Dorsal::Controller }
36
+ context "#initialize" do
37
+
38
+ end
39
+ context "Attributs accessor" do
40
+ context "#options (RO)" do
41
+ it { should respond_to :options }
42
+ it { should_not respond_to :options= }
43
+ it { subject.options[:debug].should eq false }
44
+ it { subject.options[:uri].should eq "druby://localhost:8686" }
45
+ it { subject.options[:object].should be_an_instance_of Dorsal::ImplementationServer }
46
+ it { subject.options[:pid_file].should eq "/tmp/dorsal/ringserver.pid" }
47
+ it { subject.options[:name].should eq "ringserver" }
48
+ it { subject.options[:description].should eq "Dorsal Ring Server" }
49
+ end
50
+ end
51
+ context "Instance Methods" do
52
+ context "#start_ring_server" do
53
+ it { should respond_to :start_ring_server }
54
+ it { subject.start_ring_server.should be_an_instance_of Fixnum }
55
+ it "should return false if try to start twice" do
56
+ subject.start_ring_server.should be false
57
+ end
58
+ it "should exist an instance process of the Ring server" do
59
+ pid = `ps aux|grep ruby|grep -v grep |grep 'Dorsal Ring Server'|awk '{ print $2}'`.chomp
60
+ pid.should_not be_empty
61
+ end
62
+
63
+ end
64
+
65
+ context "#bind_to_ring_server" do
66
+ it { should respond_to :bind_to_ring }
67
+ it "should be possible to bing distributed Ring Server" do
68
+ $ring = subject.bind_to_ring
69
+ end
70
+ context "Ring server Instance" do
71
+ it "should be an Instance of DRb::DRbObject" do
72
+ $ring.should be_an_instance_of DRb::DRbObject
73
+ end
74
+ it "should Ring server respond to start_service" do
75
+ $ring.should respond_to :start_service
76
+ end
77
+ it "should start a service" do
78
+ $ring.start_service({ :name => 'dummy', :object => Dummy::new, :description => 'A dummy distributed service' }).should > 0
79
+ end
80
+ it "should exist an instance process of dummy service" do
81
+ pid = `ps aux|grep ruby|grep -v grep |grep 'A dummy distributed service'|awk '{ print $2}'`.chomp
82
+ pid.should_not be_empty
83
+ end
84
+ it "should Ring server respond to list_services" do
85
+ $ring.should respond_to :list_services
86
+ end
87
+ it "should list_services return a Hash" do
88
+ $ring.list_services.should be_an_instance_of Hash
89
+ end
90
+ it "should list_services include 'dummy' service" do
91
+ $ring.list_services.should include 'dummy'
92
+ $ring.list_services['dummy'][:description].should eq 'A dummy distributed service'
93
+ $ring.list_services['dummy'][:pid_file].should eq '/tmp/dorsal/service-dummy.pid'
94
+ $ring.list_services['dummy'][:uri].should =~ /druby:\/\/localhost:\d+/
95
+ end
96
+ it "should exist pid_file : /tmp/dorsal/service-dummy.pid" do
97
+ File::exist?('/tmp/dorsal/service-dummy.pid').should be true
98
+ end
99
+ it "should ring server respond to bind_to_service" do
100
+ $ring.should respond_to :bind_to_service
101
+ end
102
+ it "should bind the dummy service" do
103
+ $dummy = $ring.bind_to_service :name => 'dummy'
104
+ $dummy.should be_an_instance_of DRb::DRbObject
105
+ $dummy.test.should eq 'OK'
106
+ end
107
+ it "should have a running daemon instance of the service dummy" do
108
+ pid = `ps aux|grep ruby|grep -v grep |grep 'A dummy distributed service'|awk '{ print $2}'`.chomp
109
+ pid.should_not be_empty
110
+ end
111
+
112
+ it "should ring server respond to destroy_service" do
113
+ $ring.should respond_to :destroy_service
114
+
115
+ end
116
+
117
+ it "should be possible to stop the dummy_service" do
118
+ res = $ring.destroy_service({ :name => 'dummy'})
119
+ res.should be true
120
+ $ring.list_services.should be_empty
121
+
122
+ end
123
+ it "should not exist pid_file : /tmp/dorsal/service-dummy.pid" do
124
+ File::exist?('/tmp/dorsal/service-dummy.pid').should be false
125
+ end
126
+
127
+ it "should return false if trying to stop again the dummy_service" do
128
+ $ring.destroy_service({ :name => 'dummy'}).should be false
129
+ end
130
+
131
+
132
+ end
133
+ end
134
+ context "#ring_server_status(running)" do
135
+ it { should respond_to :ring_server_status }
136
+ it "should respond true" do
137
+ subject.ring_server_status.should be true
138
+ end
139
+ end
140
+
141
+ context "#stop_ring_server" do
142
+ it "should re-start a service dummy for testing auto_destroy when stop Ring Server" do
143
+ $ring.start_service({ :name => 'dummy', :object => Dummy::new, :description => 'A dummy distributed service' }).should > 0
144
+ end
145
+ it { should respond_to :stop_ring_server }
146
+ it { subject.stop_ring_server.should eq true }
147
+ it "should no longer exist an instance process of the Ring server" do
148
+ pid = `ps aux|grep ruby|grep -v grep |grep 'Dorsal Ring Server'|awk '{ print $2}'`.chomp
149
+ pid.should be_empty
150
+ end
151
+ it "should not exist an instance process of dummy service" do
152
+ pid = `ps aux|grep ruby|grep -v grep |grep 'A dummy distributed service'|awk '{ print $2}'`.chomp
153
+ pid.should be_empty
154
+ end
155
+ it "should not exist pid_file : /tmp/dorsal/service-dummy.pid" do
156
+ File::exist?('/tmp/dorsal/service-dummy.pid').should be false
157
+ end
158
+ end
159
+
160
+ context "#ring_server_status(shutdown)" do
161
+ it "should respond false" do
162
+ subject.ring_server_status.should be false
163
+ end
164
+ end
165
+
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,10 @@
1
+ class Dummy
2
+
3
+ def initialize
4
+
5
+ end
6
+
7
+ def test
8
+ return 'OK'
9
+ end
10
+ end
@@ -0,0 +1,25 @@
1
+ AssignmentInConditionalCheck:
2
+ CaseMissingElseCheck:
3
+ ClassLineCountCheck:
4
+ line_count: 300
5
+ ClassNameCheck:
6
+ pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
7
+ #ClassVariableCheck:
8
+ CyclomaticComplexityBlockCheck:
9
+ complexity: 5
10
+ CyclomaticComplexityMethodCheck:
11
+ complexity: 10
12
+ EmptyRescueBodyCheck:
13
+ ForLoopCheck:
14
+ MethodLineCountCheck:
15
+ line_count: 30
16
+ MethodNameCheck:
17
+ pattern: !ruby/regexp /^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/
18
+ # MissingForeignKeyIndexCheck:
19
+ ModuleLineCountCheck:
20
+ line_count: 500
21
+ ModuleNameCheck:
22
+ pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
23
+ ParameterNumberCheck:
24
+ parameter_count: 5
25
+
metadata ADDED
@@ -0,0 +1,189 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dorsal
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.1'
5
+ platform: ruby
6
+ authors:
7
+ - Romain GEORGES
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-06-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: methodic
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '1.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: yard
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rdoc
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: roodi
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: code_statistics
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: yard-rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: bundler
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.3'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.3'
125
+ - !ruby/object:Gem::Dependency
126
+ name: daemons
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: 'Dorsal : Druby Objects''s Ring Server as an simple Alternative to Linda'
140
+ email:
141
+ - romain@ultragreen.net
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".gitignore"
147
+ - Gemfile
148
+ - LICENSE.txt
149
+ - README.md
150
+ - Rakefile
151
+ - doc/manual.rdoc
152
+ - dorsal.gemspec
153
+ - lib/dorsal.rb
154
+ - lib/dorsal/controller.rb
155
+ - lib/dorsal/exceptions.rb
156
+ - lib/dorsal/implementation.rb
157
+ - lib/dorsal/privates.rb
158
+ - lib/dorsal/version.rb
159
+ - spec/dorsal_spec.rb
160
+ - spec/samples/dummy.rb
161
+ - ultragreen_roodi_coding_convention.yml
162
+ homepage: http://www.ultragreen.net/projects/dorsal
163
+ licenses:
164
+ - BSD
165
+ metadata: {}
166
+ post_install_message:
167
+ rdoc_options: []
168
+ require_paths:
169
+ - lib
170
+ required_ruby_version: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ version: 1.8.1
175
+ required_rubygems_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ requirements: []
181
+ rubyforge_project: nowarning
182
+ rubygems_version: 2.4.7
183
+ signing_key:
184
+ specification_version: 4
185
+ summary: Dorsal provide a simple and easy to use Ring Server for DRuby Objects based
186
+ services architectures
187
+ test_files:
188
+ - spec/dorsal_spec.rb
189
+ - spec/samples/dummy.rb