tyrantmanager 1.0.9 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,10 @@
1
1
  = Changelog
2
+ == Version 1.1.0 2009-08-10
3
+
4
+ * change 'status' command to 'process-status'
5
+ * add 'replication-status' command
6
+ * fix gem dependencies
7
+
2
8
  == Version 1.0.9 2009-08-01
3
9
 
4
10
  * First public versioned release
@@ -1,9 +1,10 @@
1
1
  == Tyrant Manager
2
2
 
3
- * Homepage[http://copiousfreetime.rubyforge.org/tokyo-manager]
3
+ * Homepage[http://copiousfreetime.rubyforge.org/tyrantmanager]
4
4
  * {Rubyforge project}[http://rubyforge.org/projects/copiousfreetime/]
5
5
  * email jeremy at copiousfreetime dot org
6
- * git clone git://github.com/copiousfreetime/tokyo-manager.git
6
+ * github[http://github.com/copiousfreetime/tyrantmanager]
7
+ * git clone git://github.com/copiousfreetime/tyrantmanager.git
7
8
 
8
9
  == INSTALLATION
9
10
 
@@ -15,7 +16,10 @@
15
16
 
16
17
  == DESCRIPTION
17
18
 
18
- A command line tool for managing Tokyo Tyrant instances.
19
+ A command line tool for managing Tokyo Tyrant instances. It allows for the
20
+ creation, starting, stopping, listing, stating of many tokyo tyrant instances
21
+ all on the same machine. The commands can be applied to a single or multiple
22
+ instances.
19
23
 
20
24
  === Setup a manager home
21
25
 
@@ -252,7 +256,7 @@ You can also look at the server statistics of each running instance
252
256
 
253
257
  == CREDITS
254
258
 
255
- * Inspired by the {Light Cloud}[http://opensource.plurk.com/LightCloud/Tyrant_manager/} tyrant manager
259
+ * Inspired by the {Light Cloud}[http://opensource.plurk.com/LightCloud/Tyrant_manager/] tyrant manager
256
260
  * {Tokyo Tyrant}[http://tokyocabinet.sourceforge.net/tyrantdoc/]
257
261
 
258
262
  == LICENSE
data/gemspec.rb CHANGED
@@ -20,10 +20,12 @@ TyrantManager::GEM_SPEC = Gem::Specification.new do |spec|
20
20
  spec.executables = pkg.files.bin.collect { |b| File.basename(b) }
21
21
 
22
22
  # add dependencies here
23
- # spec.add_dependency("rake", ">= 0.8.1")
24
23
  spec.add_dependency( "loquacious", "~> 1.3.0")
25
24
  spec.add_dependency( "rufus-tokyo", "~> 1.0.0")
26
-
25
+ spec.add_dependency( "logging", "~> 1.1.4" )
26
+ spec.add_dependency( "main", "~> 2.8.4" )
27
+
28
+ # development dependencies
27
29
  spec.add_development_dependency("configuration", ">= 0.0.5")
28
30
  spec.add_development_dependency( "rake", "~> 0.8.3")
29
31
 
@@ -70,15 +70,22 @@ class TyrantManager
70
70
  run { Cli.run_command_with_params( 'stop', params ) }
71
71
  }
72
72
 
73
+ mode('replication-status') {
74
+ description "Describe the replication status of those servers using replication"
75
+ mixin :option_home
76
+ mixin :option_log_level
77
+ mixin :argument_instances
78
+ run { Cli.run_command_with_params( 'replication-status', params ) }
79
+ }
73
80
 
74
- mode('status') {
81
+ mode('process-status') {
75
82
  description "Check the running status of all the tyrants listed"
76
83
  mixin :option_home
77
84
  mixin :option_log_level
78
85
 
79
86
  mixin :argument_instances
80
87
 
81
- run { Cli.run_command_with_params( 'status', params ) }
88
+ run { Cli.run_command_with_params( 'process-status', params ) }
82
89
  }
83
90
 
84
91
  mode( 'stats' ) {
@@ -116,3 +116,4 @@ require 'tyrant_manager/commands/stop'
116
116
  require 'tyrant_manager/commands/status'
117
117
  require 'tyrant_manager/commands/stats'
118
118
  require 'tyrant_manager/commands/list'
119
+ require 'tyrant_manager/commands/replication_status'
@@ -0,0 +1,92 @@
1
+ require 'tyrant_manager/command'
2
+ require 'socket'
3
+
4
+ class TyrantManager
5
+ module Commands
6
+ #
7
+ # Report on the replication status of the server(s)
8
+ #
9
+ class ReplicationStatus< Command
10
+ def self.command_name
11
+ 'replication-status'
12
+ end
13
+
14
+ def run
15
+ manager.each_instance do |instance|
16
+ ilist = options['instances']
17
+ if ilist == %w[ all ] or ilist.include?( instance.name ) then
18
+ if instance.running? and instance.is_slave? then
19
+ s_stat = instance.stat
20
+ logger.info "#{instance.name} is replicating from #{s_stat['mhost']}:#{s_stat['mport']}"
21
+ if m_conn = validate_master_connection( instance ) then
22
+ if validate_master_master( instance.connection, m_conn ) then
23
+ m_stat = m_conn.stat
24
+ m_name = "#{s_stat['mhost']}:#{s_stat['mport']}"
25
+
26
+ primary, failover = instance.connection, m_conn
27
+
28
+ if m_stat['delay'] > s_stat['delay'] then
29
+ primary, failover = m_conn, instance.connection
30
+ end
31
+
32
+ p_stat = primary.stat
33
+ p_name = "#{ip_of( primary.host )}:#{primary.port}"
34
+
35
+ f_stat = failover.stat
36
+ f_name = "#{ip_of( failover.host )}:#{failover.port}"
37
+
38
+ n_width = [ p_name.length, f_name.length ].max
39
+
40
+ logger.info " Primary master : #{p_name} -> #{p_stat['rnum']} records, primary since #{(Time.now - ( Float(primary.stat['delay']))).strftime("%Y-%m-%d %H:%M:%S")}"
41
+ logger.info " Failover master : #{f_name} -> #{f_stat['rnum']} records, last replicated #{failover.stat['delay']} seconds ago"
42
+ end
43
+ end
44
+ logger.info ""
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def validate_master_master( slave, master )
53
+ m_stat = master.stat
54
+ s_stat = slave.stat
55
+
56
+ if ( m_stat['mhost'] and m_stat['mport'] ) then
57
+ logger.info " #{s_stat['mhost']}:#{s_stat['mport']} is replicating from #{m_stat['mhost']}:#{m_stat['mport']}"
58
+ mm_ip = ip_of( m_stat['mhost'] )
59
+ s_ip = ip_of( slave.host )
60
+ if ( s_ip == mm_ip ) and ( slave.port == m_stat['mport'].to_i ) then
61
+ #logger.info " - this is a good master-master relationship"
62
+ return true
63
+ else
64
+ logger.error " Unsupported replication configuration!!!"
65
+ logger.error " (original hostnames) #{slave.host}:#{slave.port} -> #{(master.host)}:#{master.port} -> #{m_stat['mhost']}:#{m_stat['mport']}"
66
+ logger.error " (hostnames resolved) #{s_ip}:#{slave.port} -> #{ip_of(master.host)}:#{master.port} -> #{ip_of(m_stat['mhost'])}:#{m_stat['mport']}"
67
+ return false
68
+ end
69
+ end
70
+ end
71
+
72
+ def ip_of( hostname )
73
+ hostname = Socket.gethostname if %w[ localhost 0.0.0.0 ].include?( hostname )
74
+ addr_info = Socket.getaddrinfo( hostname, 1978, "AF_INET" )
75
+ return addr_info.first[3]
76
+ end
77
+
78
+ def validate_master_connection( slave )
79
+ begin
80
+ m_conn = slave.master_connection
81
+ m_stat = m_conn.stat
82
+ return m_conn
83
+ rescue => e
84
+ logger.error e
85
+ s_stat = slave.stat
86
+ logger.error "Master server #{s_stat["mhost"]}:#{s_stat['mport']} appears to be down."
87
+ end
88
+ return nil
89
+ end
90
+ end
91
+ end
92
+ end
@@ -10,8 +10,7 @@ class TyrantManager
10
10
  ilist = options['instances']
11
11
  if ilist == %w[ all ] or ilist.include?( instance.name ) then
12
12
  puts "Instance #{instance.name} at #{instance.home_dir}"
13
- conn = instance.connection
14
- stats = conn.stat
13
+ stats = instance.stat
15
14
  stats.keys.sort.each do |k|
16
15
  lhs = k.ljust(10, ".")
17
16
  puts " #{lhs} #{stats[k]}"
@@ -4,7 +4,11 @@ class TyrantManager
4
4
  #
5
5
  # Report the status of one ore more tyrant intances
6
6
  #
7
- class Status < Command
7
+ class ProcessStatus < Command
8
+ def self.command_name
9
+ 'process-status'
10
+ end
11
+
8
12
  def run
9
13
  manager.each_instance do |instance|
10
14
  ilist = options['instances']
@@ -308,13 +308,46 @@ class TyrantManager
308
308
  end
309
309
  end
310
310
 
311
+ #
312
+ # return the stats for this instance
313
+ #
314
+ def stat
315
+ connection.stat
316
+ end
317
+
311
318
  #
312
319
  # return a network connection to this instance
313
320
  #
314
321
  def connection
322
+ host = configuration.host
323
+
324
+ # you cannot connect to 0.0.0.0
325
+ if host == "0.0.0.0" then
326
+ host = "localhost"
327
+ end
315
328
  Rufus::Tokyo::Tyrant.new( configuration.host, configuration.port.to_i )
316
329
  end
317
330
 
331
+ #
332
+ # Is this instance a slave of another server? This means it could be in a
333
+ # master-slave or master-master relationship
334
+ #
335
+ def is_slave?
336
+ s = connection.stat
337
+ return (s['mhost'] and s['mport'])
338
+ end
339
+
340
+ #
341
+ # return a network connection to the master server of this instance
342
+ #
343
+ def master_connection
344
+ if is_slave? then
345
+ s = self.stat
346
+ return Rufus::Tokyo::Tyrant.new( s['mhost'], s['mport'].to_i )
347
+ end
348
+ return nil
349
+ end
350
+
318
351
 
319
352
  private
320
353
 
@@ -6,8 +6,8 @@
6
6
  class TyrantManager
7
7
  module Version
8
8
  MAJOR = 1
9
- MINOR = 0
10
- BUILD = 9
9
+ MINOR = 1
10
+ BUILD = 0
11
11
 
12
12
  def to_a
13
13
  [MAJOR, MINOR, BUILD]
@@ -51,6 +51,29 @@ describe TyrantManager::TyrantInstance do
51
51
  @tyrant.data_dir.should == File.join( @tdir, "instances", "test", "data" )
52
52
  end
53
53
 
54
+ describe "against running instances" do
55
+ before( :each ) do
56
+ @tyrant.start
57
+ start = Time.now
58
+ loop do
59
+ break if @tyrant.running?
60
+ sleep 0.1
61
+ break if (Time.now - start) > 2
62
+ end
63
+ end
64
+
65
+ after( :each ) do
66
+ @tyrant.stop
67
+ end
68
+
69
+ it "#is_slave?" do
70
+ @tyrant.running?.should == true
71
+ @tyrant.should_not be_is_slave
72
+ @tyrant.stop
73
+ end
74
+
75
+ end
76
+
54
77
 
55
78
  describe "database types" do
56
79
  { 'memory-hash' => "*",
data/tasks/config.rb CHANGED
@@ -12,11 +12,11 @@ Configuration.for('project') {
12
12
  author "Jeremy Hinegardner"
13
13
  email "jeremy@copiousfreetime.org"
14
14
  homepage "http://copiousfreetime.rubyforge.org/tyrantmanager/"
15
- description Utils.section_of("README", "description")
15
+ description Utils.section_of("README.rdoc", "description")
16
16
  summary description.split(".").first
17
- history "HISTORY"
17
+ history "HISTORY.rdoc"
18
18
  license FileList["LICENSE"]
19
- readme "README"
19
+ readme "README.rdoc"
20
20
  }
21
21
 
22
22
  #-----------------------------------------------------------------------
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tyrantmanager
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.9
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Hinegardner
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-01 00:00:00 -06:00
12
+ date: 2009-08-10 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -32,6 +32,26 @@ dependencies:
32
32
  - !ruby/object:Gem::Version
33
33
  version: 1.0.0
34
34
  version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: logging
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 1.1.4
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: main
47
+ type: :runtime
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 2.8.4
54
+ version:
35
55
  - !ruby/object:Gem::Dependency
36
56
  name: configuration
37
57
  type: :development
@@ -52,20 +72,21 @@ dependencies:
52
72
  - !ruby/object:Gem::Version
53
73
  version: 0.8.3
54
74
  version:
55
- description: A command line tool for managing Tokyo Tyrant instances.
75
+ description: A command line tool for managing Tokyo Tyrant instances. It allows for the creation, starting, stopping, listing, stating of many tokyo tyrant instances all on the same machine. The commands can be applied to a single or multiple instances.
56
76
  email: jeremy@copiousfreetime.org
57
77
  executables:
58
78
  - tyrantmanager
59
79
  extensions: []
60
80
 
61
81
  extra_rdoc_files:
62
- - README
63
- - HISTORY
82
+ - README.rdoc
83
+ - HISTORY.rdoc
64
84
  - LICENSE
65
85
  - lib/tyrant_manager/cli.rb
66
86
  - lib/tyrant_manager/command.rb
67
87
  - lib/tyrant_manager/commands/create_instance.rb
68
88
  - lib/tyrant_manager/commands/list.rb
89
+ - lib/tyrant_manager/commands/replication_status.rb
69
90
  - lib/tyrant_manager/commands/start.rb
70
91
  - lib/tyrant_manager/commands/stats.rb
71
92
  - lib/tyrant_manager/commands/status.rb
@@ -83,6 +104,7 @@ files:
83
104
  - lib/tyrant_manager/command.rb
84
105
  - lib/tyrant_manager/commands/create_instance.rb
85
106
  - lib/tyrant_manager/commands/list.rb
107
+ - lib/tyrant_manager/commands/replication_status.rb
86
108
  - lib/tyrant_manager/commands/start.rb
87
109
  - lib/tyrant_manager/commands/stats.rb
88
110
  - lib/tyrant_manager/commands/status.rb
@@ -102,8 +124,8 @@ files:
102
124
  - spec/version_spec.rb
103
125
  - data/config.rb
104
126
  - data/default_instance_config.rb
105
- - README
106
- - HISTORY
127
+ - README.rdoc
128
+ - HISTORY.rdoc
107
129
  - LICENSE
108
130
  - tasks/announce.rake
109
131
  - tasks/distribution.rake
@@ -118,7 +140,7 @@ homepage: http://tyrant-manager.rubyforge.org/
118
140
  post_install_message:
119
141
  rdoc_options:
120
142
  - --main
121
- - README
143
+ - README.rdoc
122
144
  require_paths:
123
145
  - lib
124
146
  required_ruby_version: !ruby/object:Gem::Requirement