Class: Emissary::Agent::Mysql::Helper

Inherits:
Object
  • Object
show all
Defined in:
lib/emissary/agent/mysql.rb

Constant Summary collapse

DEFAULT_TIMEOUT =
30
@@class_monitor =
Monitor.new
@@locked_M =
Mutex.new

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#timeoutObject

Returns the value of attribute timeout.



142
143
144
# File 'lib/emissary/agent/mysql.rb', line 142

def timeout
  @timeout
end

Class Method Details

.new(host, user, password, timeout = nil) ⇒ Object

only return one locker per host+user combination



88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/emissary/agent/mysql.rb', line 88

def self.new(host, user, password, timeout = nil)
  @@class_monitor.synchronize do
    (@@lockers||={})["#{host}:#{user}"] ||= begin
        allocate.instance_eval(<<-EOS, __FILE__, __LINE__)
          initialize(host, user, password, timeout || DEFAULT_TIMEOUT)
          self
        EOS
    end
    @@lockers["#{host}:#{user}"].timeout = timeout unless timeout.nil?
    @@lockers["#{host}:#{user}"]
  end
end

Instance Method Details

#connected?Boolean

Returns:

  • (Boolean)


144
145
146
# File 'lib/emissary/agent/mysql.rb', line 144

def connected?
  !!@connection
end

#get_binlog_infoObject

Returns [file, position]



197
198
199
200
201
202
# File 'lib/emissary/agent/mysql.rb', line 197

def get_binlog_info
  raise "get_binlog_info must be called from within a lock." unless locked?
  (result = connection.query("SHOW MASTER STATUS")).fetch_row[0,2]
ensure
  result.free unless result.nil?
end

#kill_watcher_thread!Object



224
225
226
227
# File 'lib/emissary/agent/mysql.rb', line 224

def kill_watcher_thread!
  @watcher.kill unless not @watcher.is_a?(Thread) or not @watcher.alive?
  @watcher = nil
end

#lock!Object



161
162
163
164
165
166
167
168
# File 'lib/emissary/agent/mysql.rb', line 161

def lock!
  unless locked?
    kill_watcher_thread! # make sure we have a new thread for watching
    locked_M.synchronize { @locked = true }
    connection.query("FLUSH TABLES WITH READ LOCK")
    spawn_lockwatch_thread!
  end
end

#locked?Boolean

Returns:

  • (Boolean)


157
158
159
# File 'lib/emissary/agent/mysql.rb', line 157

def locked?
  !!@locked
end

#locked_MObject



102
# File 'lib/emissary/agent/mysql.rb', line 102

def locked_M() @@locked_M; end

#spawn_lockwatch_thread!Object



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/emissary/agent/mysql.rb', line 204

def spawn_lockwatch_thread!
  if @watcher.is_a?(Thread) and not @watcher.alive?
    ::Emissary.logger.notice "Agent::MySQL: Watcher is dead - restarting..."
    @watcher = nil
  end
  
  @watcher ||= Thread.new {
    begin
      ::Emissary.logger.debug "Agent::MySQL: Entering Watcher Loop"
      Timeout.timeout(@timeout) do
        loop { break unless locked? }
      end
    rescue Timeout::Error
    ensure
      unlock!
      Thread.exit
    end
  }
end

#unlock!Object



170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/emissary/agent/mysql.rb', line 170

def unlock!
  begin
    unless not locked?
      locked_M.synchronize {
        connection.query("UNLOCK TABLES")
        @locked = false
      }
    end
  ensure
    disconnect
    kill_watcher_thread!
  end
end

#valid?Boolean

Test whether our login info is valid by attempting a database connection.

Returns:

  • (Boolean)


186
187
188
189
190
191
192
193
194
# File 'lib/emissary/agent/mysql.rb', line 186

def valid?
  begin
    !!connection
  rescue => e
    false			# Don't throw an exception, just return false.
  ensure 
    disconnect if connected? 
  end
end

#with_lockObject

Acquire a lock and, with that lock, run a block/closure.



149
150
151
152
153
154
155
# File 'lib/emissary/agent/mysql.rb', line 149

def with_lock
  begin
    lock! && yield
  ensure
    unlock!
  end
end