Class: TyrantManager::TyrantInstance

Inherits:
Object
  • Object
show all
Defined in:
lib/tyrant_manager/tyrant_instance.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dir) ⇒ TyrantInstance

Create an instance connected to the tyrant located in the given directory



55
56
57
58
59
60
61
62
63
# File 'lib/tyrant_manager/tyrant_instance.rb', line 55

def initialize( dir )
  @home_dir = File.expand_path( dir )
  @name     = File.basename( @home_dir )
  if File.exist?( self.config_file ) then
    configuration # force a load
  else
    raise Error, "#{home_dir} is not a valid archive. #{self.config_file} does not exist"
  end
end

Instance Attribute Details

#home_dirObject (readonly)

the full path to the instance home directory



44
45
46
# File 'lib/tyrant_manager/tyrant_instance.rb', line 44

def home_dir
  @home_dir
end

#managerObject

the manager that is associated with this instance



50
51
52
# File 'lib/tyrant_manager/tyrant_instance.rb', line 50

def manager
  @manager
end

#nameObject (readonly)

the name of this instance



47
48
49
# File 'lib/tyrant_manager/tyrant_instance.rb', line 47

def name
  @name
end

Class Method Details

.loggerObject



8
9
10
# File 'lib/tyrant_manager/tyrant_instance.rb', line 8

def logger
  Logging::Logger[self]
end

.setup(dir) ⇒ Object

Create all the directories needed for a tyrant



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/tyrant_manager/tyrant_instance.rb', line 14

def setup( dir )
  unless File.directory?( dir )
    logger.info "Creating directory #{dir}"
    FileUtils.mkdir_p( dir )
  end

  cfg = File.join( dir, TyrantManager.config_file_basename )
  instance_name = File.basename( dir )

  unless File.exist?( cfg )
    template = TyrantManager::Paths.data_path( "default_instance_config.rb" )
    logger.info "Creating default config file #{cfg}"
    File.open( cfg, "w+" ) do |f|
      f.write ERB.new( IO.read( template ) ).result( binding )
    end
  end

  %w[ ulog data lua log ].each do |subdir|
    subdir = File.join( dir, subdir )
    unless File.directory?( subdir ) then
      logger.info "Creating directory #{subdir}"
      FileUtils.mkdir subdir 
    end
  end

  return TyrantInstance.new( dir )
end

Instance Method Details

#config_fileObject

The configuration file for the instance



72
73
74
# File 'lib/tyrant_manager/tyrant_instance.rb', line 72

def config_file
  @config_file ||= File.join( home_dir, TyrantManager.config_file_basename ) 
end

#configurationObject

load the configuration



79
80
81
82
83
84
85
# File 'lib/tyrant_manager/tyrant_instance.rb', line 79

def configuration
  unless @configuration then
    eval(  IO.read( self.config_file ) )
    @configuration = Loquacious::Configuration.for( name )
  end
  return @configuration
end

#connectionObject

return a network connection to this instance



328
329
330
331
332
333
334
335
336
# File 'lib/tyrant_manager/tyrant_instance.rb', line 328

def connection
  host = configuration.host

  # you cannot connect to 0.0.0.0
  if host == "0.0.0.0" then
    host = "localhost"
  end
  Rufus::Tokyo::Tyrant.new( configuration.host, configuration.port.to_i )
end

#data_dirObject

The directory housing the database file



125
126
127
# File 'lib/tyrant_manager/tyrant_instance.rb', line 125

def data_dir
  @data_dir ||= append_to_home_if_not_absolute( configuration.data_dir )
end

#db_file(type = configuration.type) ⇒ Object

The full path to the database file.



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/tyrant_manager/tyrant_instance.rb', line 132

def db_file( type = configuration.type )
  unless @db_file then
    @db_file = case type
               when "memory-hash" then "*"
               when "memory-tree" then "+"
               when "hash"        then File.join( data_dir, "#{name}.tch" )
               when "tree"        then File.join( data_dir, "#{name}.tcb" )
               when "fixed"       then File.join( data_dir, "#{name}.tcf" )
               when "table"       then File.join( data_dir, "#{name}.tct" )
               else
                 raise Error, "Unknown configuration type [#{configuration.type}]"
               end
  end
  return @db_file
end

#is_slave?Boolean

Is this instance a slave of another server? This means it could be in a master-slave or master-master relationship

Returns:

  • (Boolean)


342
343
344
345
# File 'lib/tyrant_manager/tyrant_instance.rb', line 342

def is_slave?
  s = connection.stat
  return (s['mhost'] and s['mport'])
end

#log_fileObject

The log file



104
105
106
# File 'lib/tyrant_manager/tyrant_instance.rb', line 104

def log_file
  @log_file ||= append_to_home_if_not_absolute( configuration.log_file )
end

#loggerObject



65
66
67
# File 'lib/tyrant_manager/tyrant_instance.rb', line 65

def logger
  Logging::Logger[self]
end

#lua_extension_fileObject

The lua extension file



111
112
113
# File 'lib/tyrant_manager/tyrant_instance.rb', line 111

def lua_extension_file
  @lua_extension_file ||= append_to_home_if_not_absolute( configuration.lua_extension_file )
end

#master_connectionObject

return a network connection to the master server of this instance



350
351
352
353
354
355
356
# File 'lib/tyrant_manager/tyrant_instance.rb', line 350

def master_connection
  if is_slave? then
    s = self.stat
    return Rufus::Tokyo::Tyrant.new( s['mhost'], s['mport'].to_i )
  end
  return nil
end

#pidObject

The pid of the service



97
98
99
# File 'lib/tyrant_manager/tyrant_instance.rb', line 97

def pid
  Float( IO.read( pid_file ).strip ).to_i
end

#pid_fileObject

The pid file



90
91
92
# File 'lib/tyrant_manager/tyrant_instance.rb', line 90

def pid_file
  @pid_file ||= append_to_home_if_not_absolute( configuration.pid_file )
end

#replication_timestamp_fileObject

The replication timestamp file



118
119
120
# File 'lib/tyrant_manager/tyrant_instance.rb', line 118

def replication_timestamp_file
  @replication_timestamp_file ||= append_to_home_if_not_absolute( configuration.replication_timestamp_file )
end

#running?Boolean

check if process is alive

Returns:

  • (Boolean)


299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/tyrant_manager/tyrant_instance.rb', line 299

def running?
  begin
    if File.exist?( self.pid_file ) then
      _pid = self.pid
      Process.kill( 0, _pid )
      return true
    else
      return false
    end
  rescue Errno::EPERM
    logger.info "Process #{_pid} is beyond my control"
  rescue Errno::ESRCH
    logger.info "Process #{_pid} is dead"
    return false
  rescue => e
    logger.error "Problem sending kill(0, #{_pid}) : #{e}"
  end
end

#startObject

Start the tyrant



273
274
275
276
# File 'lib/tyrant_manager/tyrant_instance.rb', line 273

def start
  o = %x[ #{start_command} ]
  logger.info o
end

#start_commandObject

Start command.

This is a bit convoluted to bring together all the options and put them into one big commandline item.



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/tyrant_manager/tyrant_instance.rb', line 176

def start_command

  ##-- ttserver executable
  parts = [ manager.configuration.ttserver ]

  ##-- host and port
  parts << "-host #{configuration.host}" if configuration.host
  parts << "-port #{configuration.port}" if configuration.port

  ##-- thread options
  if thnum = cascading_config( 'thread_count' ) then
    parts << "-thnum #{thnum}"
  end
  if tout = cascading_config( 'session_timeout' ) then
    parts << "-tout #{tout}"
  end

  ##-- daemoization and pid
  parts << "-dmn" if cascading_config( 'daemonize' )
  parts << "-pid #{pid_file}"


  ##-- logging
  parts << "-log #{log_file}"
  if log_level = cascading_config( 'log_level' ) then
    if log_level == "error" then
      parts << "-le"
    elsif log_level == "debug" then
      parts << "-ld" 
    elsif log_level == "info" then
      # leave it at info
    else
      raise Error, "Invalid log level setting [#{log_level}]"
    end
  end

  ##-- update logs
  parts << "-ulog #{ulog_dir}"
  if ulim = cascading_config( 'update_log_size' )then
    parts << "-ulim #{ulim}"
  end
  parts << "-uas" if cascading_config( 'update_log_async' )

  ##-- replication items, server id, master, replication timestamp file
  parts << "-sid #{configuration.server_id}"       if configuration.server_id
  parts << "-mhost #{configuration.master_server}" if configuration.master_server
  parts << "-mport #{configuration.master_port}"   if configuration.master_port
  parts << "-rts #{replication_timestamp_file}" if configuration.replication_timestamp_file

  ##-- lua extension
  if configuration.lua_extension_file then
    if File.exist?( lua_extension_file ) then
      parts << "-ext #{lua_extension_file}" 
      if pc = configuration.periodic_command then
        if pc.name and pc.period then
          parts << "-extpc #{pc.name} #{pc.period}"
        end
      end
    end
  end

  ##-- command permissiosn
  if deny = cascading_config( "deny_commands" ) then
    parts << "-mask #{deny.join(",")}"
  end

  if allow = cascading_config( "allow_commands" ) then
    parts << "-unmask #{allow.join(",")}"
  end

  ##-- now for the filename.  The format is
  #  filename.ext#opts=ld#mode=wc#tuning_param=value#tuning_param=value...
  #
  file_pairs = []
  file_pairs << "opts=#{configuration.opts}"
  file_pairs << "mode=#{configuration.mode}"
  Loquacious::Configuration::Iterator.new( configuration.tuning_params ).each do |node|
    # allow for multiple full-text indices
    if node.name == 'idx'
      node.obj.split(',').each do |idx|
        file_pairs << "idx=#{idx}"
      end if node.obj
    else
      file_pairs << "#{node.name}=#{node.obj}" if node.obj
    end
  end

  file_name_and_params = "#{db_file}##{file_pairs.join("#")}"

  parts << file_name_and_params

  return parts.join( " " )  
end

#statObject

return the stats for this instance



321
322
323
# File 'lib/tyrant_manager/tyrant_instance.rb', line 321

def stat
  connection.stat
end

#stopObject

kill the proc



281
282
283
284
285
286
287
288
289
290
291
292
293
# File 'lib/tyrant_manager/tyrant_instance.rb', line 281

def stop
  begin
    _pid = self.pid
    Process.kill( "TERM" , _pid )
    logger.info "Sent signal TERM to #{_pid}"
  rescue Errno::EPERM
    logger.info "Process #{_pid} is beyond my control"
  rescue Errno::ESRCH
    logger.info "Process #{_pid} is dead"
  rescue => e
    logger.error "Problem sending kill(TERM, #{_pid}) : #{e}"
  end
end

#ulog_dirObject

The directory housing the database file



151
152
153
# File 'lib/tyrant_manager/tyrant_instance.rb', line 151

def ulog_dir
  @ulog_dir ||= append_to_home_if_not_absolute( configuration.ulog_dir )
end