dorsal 1.1

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.
@@ -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