Class: Archipelago::Sanitation::Officer
- Inherits:
-
Client::Base
- Object
- Client::Base
- Archipelago::Sanitation::Officer
- Defined in:
- lib/archipelago/sanitation.rb
Overview
The client class for the redundant Archipelago::Dump network.
Keeps track of our sites and writes and reads data.
Also keeps track of all the redundancy work needed, but lets Site do the work.
Instance Attribute Summary
Attributes inherited from Client::Base
#jockey, #service_descriptions, #services
Instance Method Summary collapse
-
#[](key) ⇒ Object
Get the data for
key
in the site network. -
#[]=(key, value, t = [Time.now.to_i].pack("I")) ⇒ Object
Write
key
andvalue
into the site network with a good level of redundancy etc. -
#belongs_at?(service_id, key) ⇒ Boolean
Returns whether the key belongs at the service with given id.
- #delete!(key) ⇒ Object
-
#initialize(options = {}) ⇒ Officer
constructor
A new instance of Officer.
-
#next_to?(service_id1, service_id2) ⇒ Boolean
Returns whether
service_id1
andservice_id2
would come in that order in the site array if both existed. -
#predecessor(service_id) ⇒ Object
Gets the predecessor of
service_id
in the array of services. -
#redistribute(key) ⇒ Object
Ensures that all the dumps responsible for
key
has chunks for that key without changing the timestamp forkey
. -
#responsible_sites(key) ⇒ Object
Returns => nr_of_chunks_it_should_have where sum(nr_of_chunks_it_should_have) ==
n
from self.sites having service_id >key
. -
#second_master_to(service_id) ⇒ Object
Returns the site after the first one that has keys that will be stored in the site identified by
service_id
. - #setup(options = {}) ⇒ Object
Methods inherited from Client::Base
#around_update_services, #method_missing, #setup_client, #stop!, #update_services!
Constructor Details
#initialize(options = {}) ⇒ Officer
Returns a new instance of Officer.
84 85 86 |
# File 'lib/archipelago/sanitation.rb', line 84 def initialize( = {}) setup() end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Archipelago::Client::Base
Instance Method Details
#[](key) ⇒ Object
Get the data for key
in the site network.
The key must be a SHA1 hash.
138 139 140 |
# File 'lib/archipelago/sanitation.rb', line 138 def [](key) fetch(key).first end |
#[]=(key, value, t = [Time.now.to_i].pack("I")) ⇒ Object
Write key
and value
into the site network with a good level of redundancy etc.
The key should must be a SHA1 hash.
Optionally the timestamp t
can be provided, but it defaults to now.
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/archipelago/sanitation.rb', line 109 def []=(key, value, t = [Time.now.to_i].pack("I")) super_string = Oneliner::SuperString.new(value) nr_of_needed_chunks = @minimum_nr_of_chunks / @minimum_redundancy_ratio chunk_size = (super_string.size / nr_of_needed_chunks) + @metadata_overhead chunk_size = @minimum_recoverable_size / nr_of_needed_chunks if chunk_size < @minimum_recoverable_size / nr_of_needed_chunks dump_hash = responsible_sites(key) super_string.encode(8) dump_hash.t_each do |dump_id, nr_of_chunks_needed| self.sites[dump_id][:service].insert!(key, (0...nr_of_chunks_needed).collect do |nr_of_chunks_needed| super_string.encode(chunk_size) end, t) end end |
#belongs_at?(service_id, key) ⇒ Boolean
Returns whether the key belongs at the service with given id.
164 165 166 |
# File 'lib/archipelago/sanitation.rb', line 164 def belongs_at?(service_id, key) responsible_sites(key).include?(service_id) end |
#delete!(key) ⇒ Object
126 127 128 129 130 131 |
# File 'lib/archipelago/sanitation.rb', line 126 def delete!(key) dump_hash = responsible_sites(key) dump_hash.t_each do |dump_id, nr_of_chunks_available| self.sites[dump_id][:service].delete!(key) end end |
#next_to?(service_id1, service_id2) ⇒ Boolean
Returns whether service_id1
and service_id2
would come in that order in the site array if both existed.
186 187 188 189 190 191 192 193 194 |
# File 'lib/archipelago/sanitation.rb', line 186 def next_to?(service_id1, service_id2) if self.sites.include?(service_id1) return get_least_greater_than(:sites, service_id1, 1).first[:service_id] <= service_id2 elsif self.sites.include?(service_id2) return get_greatest_less_than(:sites, service_id2, 1).first[:service_id] >= service_id1 else return false end end |
#predecessor(service_id) ⇒ Object
Gets the predecessor of service_id
in the array of services.
207 208 209 |
# File 'lib/archipelago/sanitation.rb', line 207 def predecessor(service_id) return get_greatest_less_than(:sites, service_id, 1).first[:service_id] end |
#redistribute(key) ⇒ Object
Ensures that all the dumps responsible for key
has chunks for that key without changing the timestamp for key
.
173 174 175 176 177 178 179 180 |
# File 'lib/archipelago/sanitation.rb', line 173 def redistribute(key) value, = fetch(key) # # Even if fetch didnt raise the exception we must, cause this is serious business. # raise NotEnoughDataException.new(self, key) if value.nil? self.[]=(key, value, ) end |
#responsible_sites(key) ⇒ Object
Returns => nr_of_chunks_it_should_have where sum(nr_of_chunks_it_should_have) == n
from self.sites having service_id > key
.
Will loop to the beginning if the number of elements run out.
149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/archipelago/sanitation.rb', line 149 def responsible_sites(key) raise NoRemoteDatabaseAvailableException.new(self) if self.sites.empty? rval = {} rval.extend(Archipelago::Current::ThreadedCollection) get_least_greater_than(:sites, key, @minimum_nr_of_chunks).each do |desc| rval[desc[:service_id]] ||= 0 rval[desc[:service_id]] += 1 end return rval end |
#second_master_to(service_id) ⇒ Object
Returns the site after the first one that has keys that will be stored in the site identified by service_id
.
200 201 202 |
# File 'lib/archipelago/sanitation.rb', line 200 def second_master_to(service_id) return get_greatest_less_than(:sites, service_id, @minimum_nr_of_chunks - 1).first[:service_id] end |
#setup(options = {}) ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/archipelago/sanitation.rb', line 88 def setup( = {}) @minimum_recoverable_size = [:minimum_recoverable_size] || MINIMUM_RECOVERABLE_SIZE @minimum_nr_of_chunks = [:minimum_nr_of_chunks] || MINIMUM_NR_OF_CHUNKS @minimum_redundancy_ratio = [:minimum_redundancy_ratio] || MINIMUM_REDUNDANCY_RATIO @metadata_overhead = [:metadata_overhead] || METADATA_OVERHEAD .merge!({ :service_descriptions => { :sites => Archipelago::Disco::Query.new(SITE_DESCRIPTION.merge([:site_description] || {})) } }) setup_client() end |