tyrantmanager 1.3.2 → 1.4.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/HISTORY.rdoc +5 -0
- data/lib/tyrant_manager/cli.rb +29 -0
- data/lib/tyrant_manager/command.rb +1 -0
- data/lib/tyrant_manager/commands/archive_ulogs.rb +156 -0
- data/lib/tyrant_manager/commands/list.rb +9 -12
- data/lib/tyrant_manager/commands/replication_status.rb +10 -19
- data/lib/tyrant_manager/commands/start.rb +12 -15
- data/lib/tyrant_manager/commands/stats.rb +8 -10
- data/lib/tyrant_manager/commands/status.rb +5 -8
- data/lib/tyrant_manager/commands/stop.rb +6 -9
- data/lib/tyrant_manager/tyrant_instance.rb +38 -2
- data/lib/tyrant_manager/util.rb +9 -0
- data/lib/tyrant_manager/version.rb +2 -2
- data/lib/tyrant_manager.rb +14 -2
- data/spec/tyrant_instance_spec.rb +96 -29
- data/spec/tyrant_manager_spec.rb +18 -1
- metadata +6 -2
data/HISTORY.rdoc
CHANGED
data/lib/tyrant_manager/cli.rb
CHANGED
@@ -109,6 +109,35 @@ class TyrantManager
|
|
109
109
|
run { ::TyrantManager::Cli.run_command_with_params( 'list', params ) }
|
110
110
|
}
|
111
111
|
|
112
|
+
mode( 'archive-ulogs' ) {
|
113
|
+
description "Archive the ulog files that are no longer necessary for replication"
|
114
|
+
mixin :option_home
|
115
|
+
mixin :option_log_level
|
116
|
+
mixin :argument_instances
|
117
|
+
|
118
|
+
option( 'archive-method' ) {
|
119
|
+
description "The method of archiving, compress, or delete. Choosing 'delete' will also delete previously 'compressed' ulog files."
|
120
|
+
argument :required
|
121
|
+
validate { |m| %w[ compress delete ].include?( m.downcase ) }
|
122
|
+
default "compress"
|
123
|
+
}
|
124
|
+
|
125
|
+
option( 'dry-run' ) {
|
126
|
+
description "Do not archive, just show the commands"
|
127
|
+
default false
|
128
|
+
}
|
129
|
+
|
130
|
+
option( 'slaves' ) {
|
131
|
+
description "Comma separated list of slave instances connection strings host:port,host:port,..."
|
132
|
+
argument :required
|
133
|
+
cast :list_of_string
|
134
|
+
}
|
135
|
+
|
136
|
+
run { ::TyrantManager::Cli.run_command_with_params( 'archive-ulogs', params ) }
|
137
|
+
|
138
|
+
}
|
139
|
+
|
140
|
+
|
112
141
|
#--- Mixins ---
|
113
142
|
mixin :option_home do
|
114
143
|
option( :home ) do
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'tyrant_manager/command'
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
class TyrantManager
|
5
|
+
module Commands
|
6
|
+
#
|
7
|
+
# Archive ulog files that are no longer used for replication.
|
8
|
+
#
|
9
|
+
# You must give the list of slave connection strings on the commandline, or
|
10
|
+
# if the server is in a single master-master relationship, then you can
|
11
|
+
# allow tyrantmanager to figure that out and do the right thing.
|
12
|
+
#
|
13
|
+
# Give the slaves of a particular master
|
14
|
+
#
|
15
|
+
# tyrantmanager archive-ulogs master1 --slaves slave1:11011,slave2:11012,slave3:11013
|
16
|
+
#
|
17
|
+
# Or if there is a master-master relationship tyrant manager can figure it
|
18
|
+
# out.
|
19
|
+
#
|
20
|
+
# tyrantmanager archive-ulogs master1
|
21
|
+
#
|
22
|
+
#
|
23
|
+
class ArchiveUlogs < Command
|
24
|
+
def self.command_name
|
25
|
+
'archive-ulogs'
|
26
|
+
end
|
27
|
+
|
28
|
+
def run
|
29
|
+
instance_slaves = determine_master_slave_mappings( options['slaves'] )
|
30
|
+
|
31
|
+
manager.each_instance( options['instances'] ) do |instance|
|
32
|
+
if instance.is_master_master? then
|
33
|
+
manager.logger.debug "#{instance.name} is master_master"
|
34
|
+
instance_slaves[instance.connection_string] << instance.master_connection
|
35
|
+
end
|
36
|
+
slave_connections = instance_slaves[instance.connection_string]
|
37
|
+
|
38
|
+
potential_removals = potential_ulog_archive_files( instance )
|
39
|
+
manager.logger.info "Checking #{slave_connections.size} slaves of #{instance.name}"
|
40
|
+
|
41
|
+
slave_connections.each do |conn|
|
42
|
+
potential_removals = trim_potential_removals( instance, potential_removals, conn )
|
43
|
+
end
|
44
|
+
|
45
|
+
archive_files_with_method( potential_removals.keys.sort, options['archive-method'] )
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# Archive each of the files in the list with the given method
|
52
|
+
#
|
53
|
+
def archive_files_with_method( list, method )
|
54
|
+
list.each do |fname|
|
55
|
+
leader = (options['dry-run']) ? "(dry-run)" : ""
|
56
|
+
if "delete" == method then
|
57
|
+
File.unlink( fname ) unless options['dry-run']
|
58
|
+
manager.logger.info "deleted #{leader} #{fname}"
|
59
|
+
else
|
60
|
+
if File.extname( fname ) == ".ulog" then
|
61
|
+
%x[ gzip #{fname} ] unless options['dry-run']
|
62
|
+
manager.logger.info "#{leader} compressed #{fname}"
|
63
|
+
else
|
64
|
+
manager.logger.info "#{leader} already compressed #{fname}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Remove all items from the potential removals list that have a timestamp
|
72
|
+
# that is newer than the last replication timestamp of the tyrant
|
73
|
+
# connection
|
74
|
+
#
|
75
|
+
def trim_potential_removals( master_instance, potential, slave_conn )
|
76
|
+
slave_stat = slave_conn.stat
|
77
|
+
milliseconds = Float( slave_stat['rts'] )
|
78
|
+
last_replication_at = Time.at( milliseconds / 1_000_000 )
|
79
|
+
|
80
|
+
manager.logger.debug "Slave #{slave_conn.host}:#{slave_conn.port} last replicated at #{last_replication_at.strftime("%Y-%m-%d %H:%M:%S")} from #{master_instance.connection_string}"
|
81
|
+
|
82
|
+
if milliseconds.to_i == 0 then
|
83
|
+
manager.logger.warn "It appears that the slave at #{slave_conn.host}:#{slave_conn.port} has never replicated"
|
84
|
+
manager.logger.warn "This means that no ulogs on the master will be removed, since there is no evidence of replication."
|
85
|
+
manager.logger.warn "It may be necessary to force a replication by inserting a record into the master:"
|
86
|
+
manager.logger.warn ""
|
87
|
+
manager.logger.warn " tcrmgr put -port #{master_instance.configuration.port} #{master_instance.configuration.host} __tyrant_manager.force_replication_at #{Time.now.utc.to_i}"
|
88
|
+
manager.logger.warn ""
|
89
|
+
manager.logger.warn "And then removing that record if you so choose:"
|
90
|
+
manager.logger.warn ""
|
91
|
+
manager.logger.warn " tcrmgr out -port #{master_instance.configuration.port} #{master_instance.configuration.host} __tyrant_manager.force_replication_at"
|
92
|
+
manager.logger.warn ""
|
93
|
+
end
|
94
|
+
|
95
|
+
manager.logger.debug "Trimming ulog files that are newer than #{last_replication_at.strftime("%Y-%m-%d %H:%M:%S")}"
|
96
|
+
|
97
|
+
trimmed_potential = remove_newer_than( potential, last_replication_at )
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# Filter all the ulogs from the list whose value is greater than the input
|
102
|
+
# time.
|
103
|
+
#
|
104
|
+
def remove_newer_than( potential, whence )
|
105
|
+
potential.keys.sort.each do |fname|
|
106
|
+
if potential[fname] > whence then
|
107
|
+
potential.delete( fname )
|
108
|
+
end
|
109
|
+
end
|
110
|
+
return potential
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# The list of potential files to remove from the ulog directory. This is
|
115
|
+
# all the files in the ulog directory, minus the last one lexically.
|
116
|
+
#
|
117
|
+
# A hash of filename => File.mtime values is returned
|
118
|
+
#
|
119
|
+
def potential_ulog_archive_files( instance )
|
120
|
+
names = instance.ulog_files[0..-2]
|
121
|
+
names += Dir.glob( "#{instance.ulog_dir}/*.ulog.gz" )
|
122
|
+
potential = {}
|
123
|
+
names.each do |name|
|
124
|
+
potential[name] = File.mtime( name )
|
125
|
+
end
|
126
|
+
return potential
|
127
|
+
end
|
128
|
+
|
129
|
+
# Given a list of slaves, create a hash that has as the key, the instance
|
130
|
+
# connection string of a master, as as the value, an array of
|
131
|
+
# Rufus::Tokyo::Tyrant connections.
|
132
|
+
#
|
133
|
+
def determine_master_slave_mappings( list_of_slaves )
|
134
|
+
master_to_slaves = Hash.new{ |h,k| h[k] = [] }
|
135
|
+
|
136
|
+
list_of_slaves ||= []
|
137
|
+
list_of_slaves.each do |connection_string|
|
138
|
+
host, port = connection_string.split(":")
|
139
|
+
conn = Rufus::Tokyo::Tyrant.new( host, port.to_i )
|
140
|
+
stat = conn.stat
|
141
|
+
master_host = stat['mhost']
|
142
|
+
master_port = stat['mport']
|
143
|
+
if master_host and master_port then
|
144
|
+
master_to_slaves["#{master_host}:#{master_port}"] << conn
|
145
|
+
else
|
146
|
+
manager.logger.warn "Slave #{connection_string} does not have a master server configured, skipping using it as a slave"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
return master_to_slaves
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
|
@@ -7,20 +7,17 @@ class TyrantManager
|
|
7
7
|
#
|
8
8
|
class List < Command
|
9
9
|
def run
|
10
|
-
manager.each_instance do |instance|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
parts << "port #{instance.configuration.port}"
|
16
|
-
parts << instance.home_dir
|
10
|
+
manager.each_instance( options['instances'] ) do |instance|
|
11
|
+
parts = []
|
12
|
+
parts << ("%20s" % instance.name)
|
13
|
+
parts << "port #{instance.configuration.port}"
|
14
|
+
parts << instance.home_dir
|
17
15
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
22
|
-
puts parts.join(" : ")
|
16
|
+
if instance.configuration.master_server then
|
17
|
+
parts << "server id #{"%2d" % instance.configuration.server_id}"
|
18
|
+
parts << "replicating from #{instance.configuration.master_server}:#{instance.configuration.master_port}"
|
23
19
|
end
|
20
|
+
puts parts.join(" : ")
|
24
21
|
end
|
25
22
|
end
|
26
23
|
end
|
@@ -12,12 +12,10 @@ class TyrantManager
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def run
|
15
|
-
manager.each_instance do |instance|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
s_stat = instance.stat
|
20
|
-
logger.info "#{instance.name} is replicating from #{s_stat['mhost']}:#{s_stat['mport']}"
|
15
|
+
manager.each_instance( options['instances'] ) do |instance|
|
16
|
+
if instance.running? and instance.is_slave? then
|
17
|
+
s_stat = instance.stat
|
18
|
+
logger.info "#{instance.name} is replicating from #{s_stat['mhost']}:#{s_stat['mport']}"
|
21
19
|
if m_conn = validate_master_connection( instance ) then
|
22
20
|
if validate_master_master( instance.connection, m_conn ) then
|
23
21
|
m_stat = m_conn.stat
|
@@ -30,10 +28,10 @@ class TyrantManager
|
|
30
28
|
end
|
31
29
|
|
32
30
|
p_stat = primary.stat
|
33
|
-
p_name = "#{ip_of( primary.host )}:#{primary.port}"
|
31
|
+
p_name = "#{manager.ip_of( primary.host )}:#{primary.port}"
|
34
32
|
|
35
33
|
f_stat = failover.stat
|
36
|
-
f_name = "#{ip_of( failover.host )}:#{failover.port}"
|
34
|
+
f_name = "#{manager.ip_of( failover.host )}:#{failover.port}"
|
37
35
|
|
38
36
|
n_width = [ p_name.length, f_name.length ].max
|
39
37
|
|
@@ -41,8 +39,7 @@ class TyrantManager
|
|
41
39
|
logger.info " Failover master : #{f_name} -> #{f_stat['rnum']} records, last replicated #{failover.stat['delay']} seconds ago"
|
42
40
|
end
|
43
41
|
end
|
44
|
-
|
45
|
-
end
|
42
|
+
logger.info ""
|
46
43
|
end
|
47
44
|
end
|
48
45
|
end
|
@@ -55,26 +52,20 @@ class TyrantManager
|
|
55
52
|
|
56
53
|
if ( m_stat['mhost'] and m_stat['mport'] ) then
|
57
54
|
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 )
|
55
|
+
mm_ip = manager.ip_of( m_stat['mhost'] )
|
56
|
+
s_ip = manager.ip_of( slave.host )
|
60
57
|
if ( s_ip == mm_ip ) and ( slave.port == m_stat['mport'].to_i ) then
|
61
58
|
#logger.info " - this is a good master-master relationship"
|
62
59
|
return true
|
63
60
|
else
|
64
61
|
logger.error " Unsupported replication configuration!!!"
|
65
62
|
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']}"
|
63
|
+
logger.error " (hostnames resolved) #{s_ip}:#{slave.port} -> #{manager.ip_of(master.host)}:#{master.port} -> #{manager.ip_of(m_stat['mhost'])}:#{m_stat['mport']}"
|
67
64
|
return false
|
68
65
|
end
|
69
66
|
end
|
70
67
|
end
|
71
68
|
|
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
69
|
def validate_master_connection( slave )
|
79
70
|
begin
|
80
71
|
m_conn = slave.master_connection
|
@@ -6,24 +6,21 @@ class TyrantManager
|
|
6
6
|
#
|
7
7
|
class Start < Command
|
8
8
|
def run
|
9
|
-
manager.each_instance do |instance|
|
10
|
-
|
11
|
-
|
12
|
-
parts = [ "Starting #{instance.name}" ]
|
13
|
-
parts << instance.start_command
|
9
|
+
manager.each_instance( options['instances'] ) do |instance|
|
10
|
+
parts = [ "Starting #{instance.name}" ]
|
11
|
+
parts << instance.start_command
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
if options['dry-run'] then
|
14
|
+
parts << "(dry-run)"
|
15
|
+
logger.info parts.join(" : ")
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
24
|
-
else
|
25
|
-
logger.info "Instance #{instance.name} already running"
|
17
|
+
elsif not instance.running? then
|
18
|
+
logger.info parts.join(" : ")
|
19
|
+
Dir.chdir( instance.home_dir ) do
|
20
|
+
instance.start
|
26
21
|
end
|
22
|
+
else
|
23
|
+
logger.info "Instance #{instance.name} already running"
|
27
24
|
end
|
28
25
|
end
|
29
26
|
end
|
@@ -6,17 +6,15 @@ class TyrantManager
|
|
6
6
|
#
|
7
7
|
class Stats < Command
|
8
8
|
def run
|
9
|
-
manager.each_instance do |instance|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
puts " #{lhs} #{stats[k]}"
|
17
|
-
end
|
18
|
-
puts
|
9
|
+
manager.each_instance( options['instances'] ) do |instance|
|
10
|
+
puts "Instance #{instance.name} at #{instance.home_dir}"
|
11
|
+
stats = instance.stat
|
12
|
+
max_width = stats.keys.collect { |k| k.length }.sort.last + 2
|
13
|
+
stats.keys.sort.each do |k|
|
14
|
+
lhs = k.ljust(max_width, ".")
|
15
|
+
puts " #{lhs} #{stats[k]}"
|
19
16
|
end
|
17
|
+
puts
|
20
18
|
end
|
21
19
|
end
|
22
20
|
end
|
@@ -10,14 +10,11 @@ class TyrantManager
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def run
|
13
|
-
manager.each_instance do |instance|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
else
|
19
|
-
logger.info "#{instance.name} is not running, or its pid file is gone"
|
20
|
-
end
|
13
|
+
manager.each_instance( options['instances'] ) do |instance|
|
14
|
+
if instance.running? then
|
15
|
+
logger.info "#{instance.name} is running as pid #{instance.pid}"
|
16
|
+
else
|
17
|
+
logger.info "#{instance.name} is not running, or its pid file is gone"
|
21
18
|
end
|
22
19
|
end
|
23
20
|
end
|
@@ -6,15 +6,12 @@ class TyrantManager
|
|
6
6
|
#
|
7
7
|
class Stop < Command
|
8
8
|
def run
|
9
|
-
manager.each_instance do |instance|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
else
|
16
|
-
logger.info "Stopping #{instance.name} : no pid file, nothing to do"
|
17
|
-
end
|
9
|
+
manager.each_instance( options['instances'] ) do |instance|
|
10
|
+
if File.exist?( instance.pid_file ) then
|
11
|
+
logger.info "Stopping #{instance.name} : pid #{instance.pid}"
|
12
|
+
instance.stop
|
13
|
+
else
|
14
|
+
logger.info "Stopping #{instance.name} : no pid file, nothing to do"
|
18
15
|
end
|
19
16
|
end
|
20
17
|
end
|
@@ -152,6 +152,13 @@ class TyrantManager
|
|
152
152
|
@ulog_dir ||= append_to_home_if_not_absolute( configuration.ulog_dir )
|
153
153
|
end
|
154
154
|
|
155
|
+
#
|
156
|
+
# The list of .ulog files that are in the ulog/ directory
|
157
|
+
#
|
158
|
+
def ulog_files
|
159
|
+
Dir.glob( "#{ulog_dir}/*.ulog" ).sort
|
160
|
+
end
|
161
|
+
|
155
162
|
#
|
156
163
|
# The lua extension file
|
157
164
|
#
|
@@ -369,13 +376,21 @@ class TyrantManager
|
|
369
376
|
tclass.new( configuration.host, configuration.port.to_i )
|
370
377
|
end
|
371
378
|
|
379
|
+
#
|
380
|
+
# Return the host:port connection string of the instance
|
381
|
+
#
|
382
|
+
def connection_string
|
383
|
+
"#{configuration.host}:#{configuration.port}"
|
384
|
+
end
|
385
|
+
|
372
386
|
#
|
373
387
|
# Is this instance a slave of another server? This means it could be in a
|
374
|
-
# master-slave or master-master relationship
|
388
|
+
# master-slave or master-master relationship. returns true or false
|
389
|
+
# explicitly
|
375
390
|
#
|
376
391
|
def is_slave?
|
377
392
|
s = connection.stat
|
378
|
-
return (s['mhost'] and s['mport'])
|
393
|
+
return ((s['mhost'] and s['mport']) ? true : false )
|
379
394
|
end
|
380
395
|
|
381
396
|
#
|
@@ -389,6 +404,27 @@ class TyrantManager
|
|
389
404
|
return nil
|
390
405
|
end
|
391
406
|
|
407
|
+
#
|
408
|
+
# Is this instance in a master-master relationship with another server.
|
409
|
+
# This means that it is a slave, and its master server is also a slave of
|
410
|
+
# this server
|
411
|
+
#
|
412
|
+
def is_master_master?
|
413
|
+
if mc = self.master_connection then
|
414
|
+
mstat = mc.stat
|
415
|
+
mslave_host = manager.ip_of(mstat['mhost'])
|
416
|
+
mslave_port = mstat['mport']
|
417
|
+
|
418
|
+
mslave_conn_string = "#{mslave_host}:#{mslave_port}"
|
419
|
+
|
420
|
+
my_host = manager.ip_of( configuration.host )
|
421
|
+
my_conn_string = "#{my_host}:#{configuration.port}"
|
422
|
+
logger.debug "#is_master_master? -> my_conn_string = #{my_conn_string} mslave_conn_string = #{mslave_conn_string}"
|
423
|
+
|
424
|
+
return (my_conn_string == mslave_conn_string)
|
425
|
+
end
|
426
|
+
return false
|
427
|
+
end
|
392
428
|
|
393
429
|
private
|
394
430
|
|
data/lib/tyrant_manager.rb
CHANGED
@@ -7,10 +7,12 @@ require 'rubygems'
|
|
7
7
|
require 'loquacious'
|
8
8
|
require 'tyrant_manager/version'
|
9
9
|
require 'tyrant_manager/paths'
|
10
|
+
require 'tyrant_manager/util'
|
10
11
|
require 'tyrant_manager/log'
|
11
12
|
|
12
13
|
class TyrantManager
|
13
14
|
include TyrantManager::Paths
|
15
|
+
include TyrantManager::Util
|
14
16
|
|
15
17
|
class Error < StandardError; end
|
16
18
|
|
@@ -135,6 +137,8 @@ class TyrantManager
|
|
135
137
|
end
|
136
138
|
return TyrantManager.new( dir )
|
137
139
|
end
|
140
|
+
|
141
|
+
|
138
142
|
end
|
139
143
|
|
140
144
|
#
|
@@ -211,9 +215,17 @@ class TyrantManager
|
|
211
215
|
return @instances
|
212
216
|
end
|
213
217
|
|
214
|
-
|
218
|
+
# Yield each instance that exists in the limit list, if the limit exists.
|
219
|
+
# If the limit does not exist then yield each instance.
|
220
|
+
#
|
221
|
+
def each_instance( limit = %w[ all ])
|
222
|
+
limit = [ limit ].flatten
|
223
|
+
every = (limit.first == "all")
|
224
|
+
|
215
225
|
instances.keys.sort.each do |name|
|
216
|
-
|
226
|
+
if every or limit.include?( name ) then
|
227
|
+
yield instances[name]
|
228
|
+
end
|
217
229
|
end
|
218
230
|
end
|
219
231
|
|
@@ -5,17 +5,44 @@ require 'tyrant_manager/tyrant_instance'
|
|
5
5
|
|
6
6
|
describe TyrantManager::TyrantInstance do
|
7
7
|
before( :each ) do
|
8
|
-
@
|
8
|
+
@tyrant_manager_dir = File.join( temp_dir, 'tyrant' )
|
9
|
+
|
10
|
+
@instances = {
|
11
|
+
'standalone' => nil,
|
12
|
+
'slave_1' => nil,
|
13
|
+
'master_master_1' => nil,
|
14
|
+
'master_master_2' => nil
|
15
|
+
}
|
16
|
+
|
9
17
|
TyrantManager::Log.silent {
|
10
|
-
|
11
|
-
@
|
12
|
-
|
13
|
-
@
|
18
|
+
|
19
|
+
@mgr = TyrantManager.setup( @tyrant_manager_dir)
|
20
|
+
|
21
|
+
@instances.keys.each_with_index do |name, idx|
|
22
|
+
idir = @mgr.instances_path( name )
|
23
|
+
tyrant = TyrantManager::TyrantInstance.setup( idir )
|
24
|
+
tyrant.manager = @mgr
|
25
|
+
tyrant.configuration.port += idx
|
26
|
+
tyrant.configuration.server_id = tyrant.configuration.port
|
27
|
+
@instances[name] = tyrant
|
28
|
+
end
|
14
29
|
}
|
30
|
+
|
31
|
+
# set the slave_1 to be a slave of the standalone
|
32
|
+
@instances['slave_1'].configuration.master_server = "localhost"
|
33
|
+
@instances['slave_1'].configuration.master_port = @instances['standalone'].configuration.port
|
34
|
+
|
35
|
+
# set the master_master pairs into a master_master relationship
|
36
|
+
@instances['master_master_1'].configuration.master_server = "localhost"
|
37
|
+
@instances['master_master_1'].configuration.master_port = @instances['master_master_2'].configuration.port
|
38
|
+
|
39
|
+
@instances['master_master_2'].configuration.master_server = "localhost"
|
40
|
+
@instances['master_master_2'].configuration.master_port = @instances['master_master_1'].configuration.port
|
41
|
+
|
15
42
|
end
|
16
43
|
|
17
44
|
after( :each ) do
|
18
|
-
FileUtils.rm_rf @
|
45
|
+
FileUtils.rm_rf @tyrant_manager_dir
|
19
46
|
end
|
20
47
|
|
21
48
|
it "raises an exception if given an invalid directory on initialization" do
|
@@ -23,55 +50,95 @@ describe TyrantManager::TyrantInstance do
|
|
23
50
|
end
|
24
51
|
|
25
52
|
it "#config_file" do
|
26
|
-
@
|
27
|
-
File.exist?( @
|
53
|
+
@instances['standalone'].config_file.should == File.join( @tyrant_manager_dir, "instances", "standalone", "config.rb" )
|
54
|
+
File.exist?( @instances['standalone'].config_file ).should == true
|
28
55
|
end
|
29
56
|
|
30
57
|
it "#configuration" do
|
31
|
-
@
|
58
|
+
@instances['standalone'].configuration.should_not == nil
|
32
59
|
end
|
33
60
|
|
34
61
|
it "#pid_file" do
|
35
|
-
@
|
62
|
+
@instances['standalone'].pid_file.should == File.join( @tyrant_manager_dir, "instances", "standalone", "standalone.pid" )
|
36
63
|
end
|
37
64
|
|
38
65
|
it "#log_file" do
|
39
|
-
@
|
66
|
+
@instances['standalone'].log_file.should == File.join( @tyrant_manager_dir, "instances", "standalone", "log", "standalone.log" )
|
40
67
|
end
|
41
68
|
|
42
69
|
it "#replication_timestamp_file" do
|
43
|
-
@
|
70
|
+
@instances['standalone'].replication_timestamp_file.should == File.join( @tyrant_manager_dir, "instances", "standalone", "standalone.rts" )
|
44
71
|
end
|
45
72
|
|
46
73
|
it "#lua_extension_file" do
|
47
|
-
@
|
74
|
+
@instances['standalone'].lua_extension_file.should == File.join( @tyrant_manager_dir, "instances", "standalone", "lua", "standalone.lua" )
|
48
75
|
end
|
49
76
|
|
50
77
|
it "#data_dir" do
|
51
|
-
@
|
78
|
+
@instances['standalone'].data_dir.should == File.join( @tyrant_manager_dir, "instances", "standalone", "data" )
|
52
79
|
end
|
53
80
|
|
54
81
|
describe "against running instances" do
|
55
82
|
before( :each ) do
|
56
|
-
@
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
83
|
+
@instances.each_pair do |name, instance|
|
84
|
+
instance.start
|
85
|
+
start = Time.now
|
86
|
+
#print "#{name} : starting ->"
|
87
|
+
loop do
|
88
|
+
break if instance.running?
|
89
|
+
#print "+"
|
90
|
+
$stdout.flush
|
91
|
+
sleep 0.1
|
92
|
+
break if (Time.now - start) > 3
|
93
|
+
end
|
94
|
+
#puts
|
62
95
|
end
|
63
96
|
end
|
64
97
|
|
65
98
|
after( :each ) do
|
66
|
-
@
|
99
|
+
@instances.each_pair do |name, instance|
|
100
|
+
instance.stop
|
101
|
+
start = Time.now
|
102
|
+
#print "#{name} : stopping ->"
|
103
|
+
loop do
|
104
|
+
break unless instance.running?
|
105
|
+
#print "-"
|
106
|
+
$stdout.flush
|
107
|
+
sleep 0.1
|
108
|
+
break if (Time.now - start) > 3
|
109
|
+
end
|
110
|
+
#puts
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
it "#is_running?" do
|
115
|
+
@instances.each_pair do |name, instance|
|
116
|
+
[ name, instance.running? ].should == [ name, true ]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
it "#is_slave? when it is NOT a slave" do
|
121
|
+
@instances['standalone'].running?.should == true
|
122
|
+
@instances['standalone'].is_slave?.should == false
|
123
|
+
end
|
124
|
+
|
125
|
+
it "#is_slave? when it IS a slave" do
|
126
|
+
@instances['slave_1'].running?.should == true
|
127
|
+
@instances['slave_1'].is_slave?.should == true
|
67
128
|
end
|
68
129
|
|
69
|
-
it "#
|
70
|
-
@
|
71
|
-
@
|
72
|
-
@tyrant.stop
|
130
|
+
it "#is_master_master? when it is NOT in a master_master relationship" do
|
131
|
+
@instances['slave_1'].running?.should == true
|
132
|
+
@instances['slave_1'].is_master_master?.should == false
|
73
133
|
end
|
74
134
|
|
135
|
+
it "#is_master_master? when it IS in a master_master relationship" do
|
136
|
+
@instances['master_master_1'].running?.should == true
|
137
|
+
@instances['master_master_1'].is_master_master?.should == true
|
138
|
+
|
139
|
+
@instances['master_master_2'].running?.should == true
|
140
|
+
@instances['master_master_2'].is_master_master?.should == true
|
141
|
+
end
|
75
142
|
end
|
76
143
|
|
77
144
|
|
@@ -84,23 +151,23 @@ describe TyrantManager::TyrantInstance do
|
|
84
151
|
'table' => "tct"
|
85
152
|
}.each_pair do |db_type, db_ext|
|
86
153
|
it "db_type of #{db_type} is db file with ext #{db_ext}" do
|
87
|
-
f = @
|
154
|
+
f = @instances['standalone'].db_file( db_type )
|
88
155
|
if f.size == 1 then
|
89
156
|
f.should == db_ext
|
90
157
|
else
|
91
|
-
f.should == File.join( @
|
158
|
+
f.should == File.join( @tyrant_manager_dir, "instances", "standalone", "data", "standalone.#{db_ext}" )
|
92
159
|
end
|
93
160
|
end
|
94
161
|
end
|
95
162
|
end
|
96
163
|
|
97
164
|
it "#ulog_dir" do
|
98
|
-
@
|
165
|
+
@instances['standalone'].ulog_dir.should == File.join( @tyrant_manager_dir, "instances", "standalone", "ulog" )
|
99
166
|
end
|
100
167
|
|
101
168
|
|
102
169
|
it "#start_command" do
|
103
|
-
@
|
170
|
+
@instances['standalone'].start_command.should =~ /^ttserver/
|
104
171
|
end
|
105
172
|
|
106
173
|
end
|
data/spec/tyrant_manager_spec.rb
CHANGED
@@ -51,7 +51,7 @@ describe TyrantManager do
|
|
51
51
|
@mgr.configuration.ttserver.should == "ttserver"
|
52
52
|
end
|
53
53
|
|
54
|
-
it "
|
54
|
+
it "iterates over all its instances" do
|
55
55
|
3.times do |x|
|
56
56
|
idir = @mgr.instances_path( "test#{x}" )
|
57
57
|
TyrantManager::TyrantInstance.setup( idir )
|
@@ -66,4 +66,21 @@ describe TyrantManager do
|
|
66
66
|
|
67
67
|
names.sort.should == %w[ test0 test1 test2 ]
|
68
68
|
end
|
69
|
+
|
70
|
+
it "iterates over a subset of instances" do
|
71
|
+
3.times do |x|
|
72
|
+
idir = @mgr.instances_path( "test#{x}" )
|
73
|
+
TyrantManager::TyrantInstance.setup( idir )
|
74
|
+
end
|
75
|
+
|
76
|
+
@mgr.instances.size.should == 3
|
77
|
+
names = []
|
78
|
+
@mgr.each_instance( %w[ test0 test2] ) do |i|
|
79
|
+
i.name.should =~ /test\d/
|
80
|
+
names << i.name
|
81
|
+
end
|
82
|
+
|
83
|
+
names.sort.should == %w[ test0 test2 ]
|
84
|
+
end
|
85
|
+
|
69
86
|
end
|
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.
|
4
|
+
version: 1.4.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: 2010-01-
|
12
|
+
date: 2010-01-21 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -88,6 +88,7 @@ extra_rdoc_files:
|
|
88
88
|
- LICENSE
|
89
89
|
- lib/tyrant_manager/cli.rb
|
90
90
|
- lib/tyrant_manager/command.rb
|
91
|
+
- lib/tyrant_manager/commands/archive_ulogs.rb
|
91
92
|
- lib/tyrant_manager/commands/create_instance.rb
|
92
93
|
- lib/tyrant_manager/commands/list.rb
|
93
94
|
- lib/tyrant_manager/commands/replication_status.rb
|
@@ -99,6 +100,7 @@ extra_rdoc_files:
|
|
99
100
|
- lib/tyrant_manager/paths.rb
|
100
101
|
- lib/tyrant_manager/runner.rb
|
101
102
|
- lib/tyrant_manager/tyrant_instance.rb
|
103
|
+
- lib/tyrant_manager/util.rb
|
102
104
|
- lib/tyrant_manager/version.rb
|
103
105
|
- lib/tyrant_manager.rb
|
104
106
|
- lib/tyrantmanager.rb
|
@@ -106,6 +108,7 @@ files:
|
|
106
108
|
- bin/tyrantmanager
|
107
109
|
- lib/tyrant_manager/cli.rb
|
108
110
|
- lib/tyrant_manager/command.rb
|
111
|
+
- lib/tyrant_manager/commands/archive_ulogs.rb
|
109
112
|
- lib/tyrant_manager/commands/create_instance.rb
|
110
113
|
- lib/tyrant_manager/commands/list.rb
|
111
114
|
- lib/tyrant_manager/commands/replication_status.rb
|
@@ -117,6 +120,7 @@ files:
|
|
117
120
|
- lib/tyrant_manager/paths.rb
|
118
121
|
- lib/tyrant_manager/runner.rb
|
119
122
|
- lib/tyrant_manager/tyrant_instance.rb
|
123
|
+
- lib/tyrant_manager/util.rb
|
120
124
|
- lib/tyrant_manager/version.rb
|
121
125
|
- lib/tyrant_manager.rb
|
122
126
|
- lib/tyrantmanager.rb
|