Class: Archipelago::Pirate::Captain

Inherits:
Client::Base show all
Defined in:
lib/archipelago/pirate.rb

Overview

The class that actually keeps track of the Archipelago::Treasure:Chests and the Archipelago::Treasure:Dubloons in them.

Instance Attribute Summary

Attributes inherited from Client::Base

#jockey, #service_descriptions, #services

Instance Method Summary collapse

Methods inherited from Client::Base

#method_missing, #setup_client, #stop!, #update_services!

Constructor Details

#initialize(options = {}) ⇒ Captain

Will look for Archipelago::Treasure::Chests matching :chest_description or CHEST_DESCRIPTION and Archipelago::Tranny::Managers matching :tranny_description or TRANNY_DESCRIPTION.

Will send off all :chest_eval_files to any chest found for possible evaluation to ensure existence of required classes and modules at the chest.



83
84
85
86
# File 'lib/archipelago/pirate.rb', line 83

def initialize(options = {})
  @transaction = nil
  setup(options)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Archipelago::Client::Base

Instance Method Details

#[](key, transaction = nil) ⇒ Object

Get a value from the distributed database network using a key, optionally within a transaction.



119
120
121
# File 'lib/archipelago/pirate.rb', line 119

def [](key, transaction = nil)
  responsible_chest(key)[:service][key, transaction || @transaction]
end

#[]=(key, p1, p2 = nil) ⇒ Object

Write a value to the distributed database network, optionally inside a transaction.

Usage:

  • p[“my key”, transaction] = value

  • p[“my key”] = value



131
132
133
134
135
136
137
# File 'lib/archipelago/pirate.rb', line 131

def []=(key, p1, p2 = nil)
  if @transaction && p2.nil?
    p2 = p1
    p1 = @transaction 
  end
  responsible_chest(key)[:service][key, p1] = p2
end

#abort!Object

Abort the transaction we are a member of and forget about it.

Returns the new state of the transaction.



219
220
221
222
223
224
225
# File 'lib/archipelago/pirate.rb', line 219

def abort!
  begin
    @transaction.abort!
  ensure
    @transaction = nil
  end
end

#active_transactionObject

Returns our active transaction, if any.



164
165
166
# File 'lib/archipelago/pirate.rb', line 164

def active_transaction
  @transaction
end

#beginObject

Return a clone of this instance bound to a newly created transaction.



150
151
152
153
154
155
156
157
158
159
# File 'lib/archipelago/pirate.rb', line 150

def begin
  raise NoTransactionManagerAvailableException.new(self) if self.trannies.empty?

  rval = self.clone
  rval.instance_eval do
    @transaction = self.trannies.values.first[:service].begin
  end

  return rval
end

#commit!Object

Commit the transaction we are a member of and forget about it.

Returns the new state of the transaction.



206
207
208
209
210
211
212
# File 'lib/archipelago/pirate.rb', line 206

def commit!
  begin
    return @transaction.commit!
  ensure
    @transaction = nil
  end
end

#delete(key, transaction = nil) ⇒ Object

Delete a value from the distributed database network, optionally inside a transaction.



143
144
145
# File 'lib/archipelago/pirate.rb', line 143

def delete(key, transaction = nil)
  responsible_chest(key)[:service].delete(key, transaction || @transaction)
end

#each(callable) ⇒ Object

Will do callable.call(key, value) for each key-and-value pair in this database network.

NB: This is totaly thread-unsafe, only do this for management or rescue!



242
243
244
245
246
# File 'lib/archipelago/pirate.rb', line 242

def each(callable)
  self.chests.t_each do |service_id, chest|
    chest[:service].each(callable)
  end
end

#evaluate!(filename) ⇒ Object

Evaluate this file in all known chests.



196
197
198
199
# File 'lib/archipelago/pirate.rb', line 196

def evaluate!(filename)
  @chest_eval_files << filename
  evaluate_in_chests
end

#include?(key, transaction = nil) ⇒ Boolean

Returns true if this Captain includes the given key, optionally within a transaction.

Returns:

  • (Boolean)


111
112
113
# File 'lib/archipelago/pirate.rb', line 111

def include?(key, transaction = nil)
  responsible_chest(key)[:service].include?(key, transaction || @transaction)
end

#responsible_chest(key) ⇒ Object

Get the chest responsible for key.



251
252
253
254
255
# File 'lib/archipelago/pirate.rb', line 251

def responsible_chest(key)
  raise NoRemoteDatabaseAvailableException.new(self) if self.chests.empty?

  return get_least_greater_than(:chests, Digest::SHA1.hexdigest(Marshal.dump(key)), 1).first
end

#setup(options = {}) ⇒ Object

Sets up this instance with the given options.



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/archipelago/pirate.rb', line 91

def setup(options = {})
  @chest_eval_files ||= []
  @chest_eval_files += options[:chest_eval_files] || []
  @chests_having_evaluated ||= {}

  @yar_counter = 0

  options.merge!({
                   :service_descriptions => {
                     :chests => CHEST_DESCRIPTION.merge(options[:chest_description] || {}),
                     :trannies => TRANNY_DESCRIPTION.merge(options[:tranny_description] || {})
                   }
                 })

  setup_client(options)
end

#successor(service_id) ⇒ Object

Gets the successor of service_id in the array of services.



260
261
262
263
# File 'lib/archipelago/pirate.rb', line 260

def successor(service_id)
  return nil if self.chests.empty?
  return get_least_greater_than(:chests, service_id, 1).first
end

#transaction(&block) ⇒ Object

Execute block within a transaction.

Will commit! transaction after the block is finished unless the transaction is aborted or commited already.

Will abort! the transaction if any exception is raised.



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/archipelago/pirate.rb', line 176

def transaction(&block) #:yields: a clone of this Archipelago::Pirate::Captain with the given transaction as default @transaction.
  raise NoTransactionManagerAvailableException.new(self) if self.trannies.empty?

  my_clone = self.begin
  transa = my_clone.active_transaction
  begin
    begin
      return yield(my_clone)
    ensure
      raise CommitFailedException.new(my_clone, transa) unless transa.commit! == :commited
    end
  rescue Exception => e
    transa.abort! unless transa.state == :aborted
    raise e
  end
end

#yar!Object

Yarrr!



230
231
232
233
# File 'lib/archipelago/pirate.rb', line 230

def yar!
  @yar_counter += 1
  'yar!'
end